Casio_asm/common/platform.c

675 lines
15 KiB
C

#include "platform.h"
#include "event.h"
#include "opcodeInfo.h"
int running=1;
int error=0;
int Platform_running() {
return running;
}
void Platform_setError(int err) {
error=err;
}
int Platform_getError() {
return error;
}
#if defined(PC)
#include <stdio.h>
#include <stdlib.h>
//BEGIN SDL handling
#include <SDL2/SDL.h>
#include "keyboard.h"
#define ZOOM 4
//prepare variables
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Rect rect={.w=ZOOM, .h=ZOOM};
//create our own vram and screen buffers
char vram[VRAM_LENGTH];
char screen[VRAM_LENGTH];
//macros to draw to screen
#define white() SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE)
#define black() SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE)
#define pixel(x, y) do {rect.x=x*ZOOM; rect.y=y*ZOOM; SDL_RenderFillRect(renderer, &rect);} while(0)
void sdlInit() {
//create a window
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER);
SDL_CreateWindowAndRenderer(VRAM_WIDTH*ZOOM, VRAM_HEIGHT*ZOOM, 0, &window, &renderer);
//clear the window
white();
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void sdlQuit() {
//destroy everything and quit SDL
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
char* Graph_getVramAddress() {
return vram;
}
void printScreen() {
for(unsigned char y=0; y<VRAM_HEIGHT; y++) {
for(unsigned char x=0; x<VRAM_WIDTH; x++) {
//read the color of the pixel
int byte=y*VRAM_BYTES_PER_LINE+x/8;
char bit=x%8;
char value=(vram[byte]>>(8-bit-1))&0x01;
//set the color accordingly
if(value) black();
else white();
//and print this now
pixel(x, y);
}
}
SDL_RenderPresent(renderer);
}
void Graph_printVram() {
//copy the VRAM into the screen buffer and then display it
for(int i=0; i<VRAM_LENGTH; i++) screen[i]=vram[i];
printScreen();
}
void sdlEvt(SDL_Event *event) {
//if it's a quit event, then quit
if(event->type==SDL_QUIT) running=0;
//redraw the window if it gets exposed
if(event->type==SDL_WINDOWEVENT&&event->window.event==SDL_WINDOWEVENT_EXPOSED) printScreen();
//if it's a keyboard event, handle it
if(event->type==SDL_KEYDOWN||event->type==SDL_KEYUP) {
event_t evt={
.type=EVENT_TYPE_KEYBOARD,
.subtype=event->type==SDL_KEYDOWN?EVENT_TYPE_KEYBOARD_PRESS:EVENT_TYPE_KEYBOARD_RELEASE
};
evt.keyevent.repeat=event->key.repeat;
evt.keyevent.code=Keyboard_getCode(event->key.keysym.sym);
if(evt.keyevent.code!=-1) Event_put(&evt);
}
//if it's a timer event(using USEREVENT as a convinience), handle it
if(event->type==SDL_USEREVENT) {
event_t evt={
.type=EVENT_TYPE_TIMER,
.subtype=0
};
evt.timerevent.code=event->user.code;
Event_put(&evt);
}
}
void sdlTick(int block) {
SDL_Event event;
if(block) {
//block until we have an event
if(SDL_WaitEvent(&event)) sdlEvt(&event);
}
//iterate all pending events
while(SDL_PollEvent(&event)) sdlEvt(&event);
}
//END SDL handling
#endif
#if defined(LINUX)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//BEGIN file handling
#define MAX_FILES 256
typedef struct file_info_t {
int fd;
int offset;
int mode;
} file_info_t;
int fileCount=0;
file_info_t files[MAX_FILES];
//check if a file is opened
int checkFile(int fd) {
for(int i=0; i<fileCount; i++) {
if(files[i].fd==fd) return i;
}
return -1;
}
//seeks a file
int seekFile(int no, int off) {
int val=lseek(files[no].fd, off, SEEK_SET);
if(val==-1) return -1;
files[no].offset=off;
return val;
}
int File_open(char* path, int mode) {
if(fileCount==MAX_FILES) return -1;
int flags=0;
if((mode&FILE_OPEN_read)&&(mode&FILE_OPEN_write)) flags=O_RDWR;
else if(mode&FILE_OPEN_write) flags=O_WRONLY;
else if(mode&FILE_OPEN_read) flags=O_RDONLY;
if(mode&FILE_OPEN_create) flags|=O_CREAT;
int fd=open(path, flags);
if(fd!=-1) {
files[fileCount].offset=0;
files[fileCount].mode=mode;
files[fileCount++].fd=fd;
return fd;
}
return -1;
}
int File_close(int fd) {
for(int i=0; i<fileCount; i++) {
if(files[i].fd==fd) {
files[i]=files[--fileCount];
fsync(fd);
return close(fd);
}
}
return -1;
}
int File_read(int fd, int pos, void* buffer, int len) {
int no=checkFile(fd);
if(no==-1) return -1;
if(pos<0) return -1;
if(!(files[no].mode&FILE_OPEN_read)) return -1;
seekFile(no, pos);
return read(fd, buffer, len);
}
int File_write(int fd, int pos, void* buffer, int len) {
int no=checkFile(fd);
if(no==-1) return -1;
if(pos<0) return -1;
if(!(files[no].mode&FILE_OPEN_write)) return -1;
seekFile(no, pos);
return write(fd, buffer, len);
}
int File_length(int fd) {
int no=checkFile(fd);
if(no==-1) return -1;
int len=lseek(fd, 0, SEEK_END);
if(len!=-1) files[no].offset=len;
return len;
}
int File_truncate(int fd, int len) {
int no=checkFile(fd);
if(no==-1) return -1;
return !ftruncate(fd, len);
}
int File_mkdir(char* path) {
return !mkdir(path, 0755);
}
int File_delete(char* path) {
return !unlink(path);
}
int fileExit() {
for(int i=1; i<fileCount; i++) {
close(files[i].fd);
}
}
//END file handling
//BEGIN common
int Platform_init() {
Event_init();
sdlInit();
running=1;
}
void Platform_tick(int block) {
sdlTick(block);
}
int Platform_quit() {
sdlQuit();
fileExit();
Opcode_quit();
Event_quit();
running=0;
}
//END common
#endif
#if defined(CASIO_fxlib)
#include "fxlib.h"
#include "keybios.h"
#include "keyboard.h"
#include "string.h"
//BEGIN syscals
#define SCA 0xD201D002
#define SCB 0x422B0009
#define SCE 0x80010070
typedef void*(*sc_vp_i)(int);
typedef void*(*sc_vp_i_i)(int,int);
typedef void(*sc_v_vp)(void*);
typedef void(*sc_v_v)(void);
typedef void*(*sc_vp_v)(void);
typedef void*(*sc_vp_vp_i)(void*, int);
typedef int(*sc_i_sp)(short*);
const unsigned int sc_malloc[] = { SCA, SCB, SCE, 0x0ACD };
const unsigned int sc_realloc[] = { SCA, SCB, SCE, 0x0E6D };
const unsigned int sc_free[] = { SCA, SCB, SCE, 0x0ACC };
const unsigned int sc_calloc[] = { SCA, SCB, SCE, 0x0E6B };
const unsigned int sc_isKeyPressed[] = { SCA, SCB, SCE, 0x024B };
const unsigned int sc_printVram[] = { SCA, SCB, SCE, 0x0028 };
const unsigned int sc_getVramAddress[] = { SCA, SCB, SCE, 0x0135 };
void* malloc(int sz) {
return ((*(sc_vp_i)sc_malloc)(sz));
}
void free(void* ptr) {
if(!ptr) return;
(*(sc_v_vp)sc_free)(ptr);
}
void* realloc(void* ptr, int sz) {
if(!ptr) return malloc(sz);
return ((*(sc_vp_vp_i)sc_realloc)(ptr, sz));
}
void* calloc(int sz, int n) {
return ((*(sc_vp_i_i)sc_calloc)(sz,n));
}
int isKeyDown(int keycode){
return key_down(keycode);
//yeah, this function is supposed to work better
/*short matcode=0x0000;
if(keycode>=0x0101||keycode==0x0000) matcode=keycode;
else if(keycode!=34) {
matcode=(keycode/10-1)<<8;
matcode|=keycode%10;
}
return ((*(sc_i_sp)sc_isKeyPressed)(&matcode));*/
}
void printVram() {
(*(sc_v_v)sc_printVram)();
}
void* getVramAddress() {
return ((*(sc_vp_v)sc_getVramAddress)());
}
//END syscalls
//BEGIN graphical functions
char* Graph_getVramAddress() {
return getVramAddress();
}
void Graph_printVram() {
printVram();
}
//END graphical functions
//BEGIN file functions
//get the file path
FONTCHARACTER path[32];
FONTCHARACTER* getPath(char* filename) {
char* str="\\\\fls0\\";
for(int i=0; i<32; i++) path[i]='\0';
for(int i=0; i<7; i++) path[i]=str[i];
int len=strlend(filename);
for(int i=0; i<=len; i++) path[i+7]=filename[i];
return path;
}
//fuck CASIO for making me do this!
//store information on the files
int deleteFile(int fd);
int lastFd;
typedef struct file_info_t {
int fd;
int handle;
int length;
char mode;
FONTCHARACTER path[32];
char* buffer;
} file_info_t;
file_info_t* files=0;
int fileInit() {
files=calloc(32, sizeof(file_info_t));
lastFd=1;
return files!=0;
}
int fileQuit() {
for(int i=0; i<32; i++) {
if(files[i].fd) deleteFile(files[i].fd);
}
free(files);
return 1;
}
//get free space
int getFreeFile() {
for(int i=0; i<32; i++) {
if(files[i].fd==0) return i;
}
return -1;
}
//create a file information
int openFile(char* path, int mode) {
//check if we have enough room for files
int spot=getFreeFile();
if(spot==-1) return -100;
//store info here
file_info_t info;
info.fd=lastFd++;
info.mode=mode;
info.buffer=0;
info.handle=-1;
//set path
FONTCHARACTER* fPath=getPath(path);
for(int i=0; i<32; i++) info.path[i]=fPath[i];
if(mode&FILE_OPEN_read) {
//read file size
int len=0;
int handle=Bfile_OpenFile(info.path, _OPENMODE_READ);
if(handle>=0) len=Bfile_GetFileSize(handle);
else return handle;
info.length=len>=0?len:0;
//read file data
if(len&&handle) {
char* ptr=malloc(len);
info.buffer=ptr;
if(!ptr) {
Bfile_CloseFile(handle);
return -200;
}
int val=Bfile_ReadFile(handle, ptr, len, 0);
if(val<0) {
free(ptr);
Bfile_CloseFile(handle);
return val;
}
}
} else {
info.length=0;
info.buffer=0;
}
//add the file to the list
files[spot]=info;
//return the fd
return info.fd;
}
//retrieve a file information
int getFile(int fd, file_info_t *info) {
for(int i=0; i<32; i++) {
*info=files[i];
if(info->fd==fd) return 1;
}
return 0;
}
void putFile(int fd, file_info_t *info) {
for(int i=0; i<32; i++) {
if(info->fd==fd) {
files[i]=*info;
return;
}
}
}
//returns the mode
int getMode(int mode) {
if((mode&FILE_OPEN_read)&&(mode&FILE_OPEN_write)) return _OPENMODE_READWRITE;
else if(mode&FILE_OPEN_write) return _OPENMODE_WRITE;
return _OPENMODE_READ;
}
//delete a file information
int deleteFile(int fd) {
for(int i=0; i<32; i++) {
if(files[i].fd==fd) {
file_info_t info=files[i];
//close the file if it is already open
if(info.handle) {
Bfile_CloseFile(info.handle);
info.handle=0;
}
//if the file is not empty
int err=0;
if(info.length) {
if(!info.buffer) err=-101;
//create it if absent
Bfile_DeleteFile(info.path);
int create=Bfile_CreateFile(info.path, info.length);
if(create&&!err) err=create;
//write data to file
info.handle=Bfile_OpenFile(info.path, getMode(info.mode));
if(info.handle<0) err=info.handle;
int len=Bfile_WriteFile(info.handle, info.buffer, info.length);
if(len<0&&!err) err=len;
int close=Bfile_CloseFile(info.handle);
if(close<0&!err) err=close;
}
//free the buffer
if(info.buffer) free(info.buffer);
//some checks
if(info.length<0) err=-102;
if((info.mode&FILE_OPEN_write)&&!info.length) err=-103;
// remove the data
info.fd=0;
files[i]=info;
return err;
}
}
return -100;
}
int File_open(char* path, int mode) {
return openFile(path, mode);
}
int File_close(int fd) {
return deleteFile(fd);
}
int File_read(int fd, int pos, void* buffer, int len) {
//get file and check the position
file_info_t info;
if(!getFile(fd, &info)) return -1;
if(pos<0||len<0) return -2;
if(pos+len>info.length) len=info.length;
//if we have the file in a buffer, read from the buffer
if(info.buffer) {
char* ptr=(char*) buffer;
for(int i=0; i<len; i++) ptr[i]=info.buffer[i+pos];
return len;
}
//we don't, so read from disk
return Bfile_ReadFile(info.handle, buffer, len, pos);
}
int File_write(int fd, int pos, void* buffer, int len) {
//get file and check the position
file_info_t info;
if(!getFile(fd, &info)) return -1;
if(pos<0||len<0) return -2;
//if we already have a buffer, AND it is big enough, write in it
if(info.buffer&&pos+len<=info.length) {
char* ptr=(char*) buffer;
for(int i=0; i<len; i++) info.buffer[i+pos]=ptr[i];
return len;
}
//if we have one, enlarge it
else if(info.buffer) {
char* newptr=realloc(info.buffer, pos+len);
if(!newptr) {
//we couldn't enlarge the buffer, write what we can and fail properly
char* ptr=(char*) buffer;
for(int i=0; i<info.length; i++) info.buffer[i+pos]=ptr[i];
putFile(fd, &info);
return info.length;
}
//fill the new buffer
info.buffer=newptr;
char* ptr=(char*) buffer;
for(int i=0; i<len; i++) info.buffer[i+pos]=ptr[i];
putFile(fd, &info);
return len;
}
//we don't have any buffer, create one
info.buffer=calloc(1, pos+len);
if(!info.buffer) return -3;
char* ptr=(char*) buffer;
for(int i=0; i<len; i++) info.buffer[i+pos]=ptr[i];
info.length=pos+len;
putFile(fd, &info);
return len;
}
int File_length(int fd) {
//get file info
file_info_t info;
if(!getFile(fd, &info)) return -1;
//return file size
return info.length;
}
int File_truncate(int fd, int size) {
//get file and check size
file_info_t info;
if(!getFile(fd, &info)) return -1;
if(size<0) return -2;
//check if we have a buffer already
if(info.buffer) {
if(info.length>size) {
info.length=size;
putFile(fd, &info);
return 0;
} else {
char* newptr=realloc(info.buffer, size);
if(newptr) {
info.length=size;
info.buffer=newptr;
putFile(fd, &info);
return 0;
}
return -4;
}
} else {
info.buffer=calloc(1, size);
if(!info.buffer) return -3;
info.length=size;
putFile(fd, &info);
return 0;
}
}
int File_delete(char* path) {
if(!Bfile_DeleteFile(getPath(path))) return 0;
return Bfile_DeleteDirectory(getPath(path));
}
int File_mkdir(char* path) {
return Bfile_CreateDirectory(getPath(path));
}
//END file functions
//BEGIN timer-related functions
#define KEY_TIMER 1
#define KEY_DELAY 50
#define KEY_COUNT 50
typedef struct key_info_t {
char code;
char time;
//short matcode;
} key_info_t;
key_info_t keys[KEY_COUNT];
#include "test.h"
void keyHandle(int pos) {
event_t evt={
.type=EVENT_TYPE_KEYBOARD,
.keyevent={
.code=keys[pos].code,
.repeat=0
}
};
// check the old status of the key
if(keys[pos].time) {
// check if the key is still down
if(isKeyDown(keys[pos].code)) {
// first repeat is after 10 periods, so 500ms or 1/2sec
if(keys[pos].time==10) {
evt.subtype=EVENT_TYPE_KEYBOARD_PRESS;
evt.keyevent.repeat=1;
Event_put(&evt);
// repeat event every 4 periods, so 200ms or 1/5sec
keys[pos].time-=4;
}
// increment key time counter
keys[pos].time++;
} else {
// detect key release
evt.subtype=EVENT_TYPE_KEYBOARD_RELEASE;
Event_put(&evt);
keys[pos].time=0;
}
} else if(isKeyDown(keys[pos].code)) {
// set the key status to pressed
evt.subtype=EVENT_TYPE_KEYBOARD_PRESS;
Event_put(&evt);
keys[pos].time=1;
}
}
void keyHandler() {
for(int i=0; i<KEY_COUNT; i++) keyHandle(i);
}
void keyClear() {
int pos=0;
for(int x=1; x<=6; x++) {
for(int y=(x==1?5:1); y<=9; y++) {
key_info_t key;
key.time=0;
key.code=10*(x+1)+y;
//key.matcode=(x<<8)|y;
//if(x==2&&y==4) key.matcode=0x0000;
keys[pos++]=key;
}
}
}
void startTimers() {
SetTimer(KEY_TIMER, KEY_DELAY, keyHandler);
}
void killTimers() {
KillTimer(KEY_TIMER);
}
//END timer-related functions
//BEGIN common functions
int Platform_init() {
Event_init();
fileInit();
keyClear();
startTimers();
return 1;
}
int Platform_quit() {
killTimers();
Event_quit();
fileQuit();
return 1;
}
void Platform_tick(int block) {
if(block) while(Platform_running()&&!Event_count()) Sleep(1);
}
//END common functions
#endif