Improved C.Basic support + various fixes

This commit is contained in:
kishimisu 2023-12-07 21:09:13 +01:00
parent fa65bb14e6
commit a6e1d338a8
16 changed files with 214 additions and 100 deletions

BIN
JJSH3.g1a

Binary file not shown.

View File

@ -7,9 +7,13 @@
#define SCREEN_HEIGHT 64
// VRAM Size & Address
#define VRAM_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 8) // 1024 for 128*64 monochrome
#define VRAM_ADDRESS (RAM_ADDRESS_P1 + RAM_SIZE + 2048) // Arbitrary address relative to start of RAM (TODO: check if correct)
// 1024 for 128*64 monochrome
// + 1 to prevent out of bounds access on Gravity Duck
#define VRAM_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 8 + 1)
// Arbitrary address relative to start of RAM
// + needs to be un-aligned (+1) for correct behavior with MonochromeLib
#define VRAM_ADDRESS (RAM_ADDRESS_P1 + RAM_SIZE + 2048 + 1)
// LCD registers addresses
#define LCD_SELECT_REGISTER 0xB4000000
#define LCD_DATA_REGISTER 0xB4010000
@ -37,7 +41,7 @@
typedef struct {
int8_t col; // starts at 1
int8_t row; // starts at 1
int16_t flash_style; // -1 if not flashing
int16_t flash_style; // flashing icon style
int8_t flash_mode; // 0: no flashing cursor, 1: flashing cursor
int8_t blink_state; // (used when cursor is flashing) 0: not visible, 1: visible
} cursor_t;

View File

@ -9,6 +9,11 @@
#define IMB_WRITEMODIFY_NORMAL 0x01
#define IMB_WRITEMODIFY_REVERSE 0x02
#define IMB_WRITEKIND_OVER 0x01
#define IMB_WRITEKIND_OR 0x02
#define IMB_WRITEKIND_AND 0x03
#define IMB_WRITEKIND_XOR 0x04
void syscall_Bdisp_AllClr_DD(cpu_t* cpu);
void syscall_Bdisp_AllClr_VRAM(cpu_t* cpu);
void syscall_Bdisp_AllClr_DDVRAM(cpu_t* cpu);

View File

@ -50,6 +50,8 @@ struct fs_t {
// MCS Handle
const char* mcs_filename;
int32_t mcs_filesize;
uint8_t needs_sync; // Tells javascript to persist the files to the local storage
};
// https://bible.planet-casio.com/simlo/chm/v20/fx_legacy_Bfile.htm

View File

@ -9,7 +9,11 @@
#define KB_PORTB 0xA4000122
#define KB_PORTM 0xA4000138
#define KB_SIZE (0xA4000138 - 0xA4000102 + 1) // Max - min address + 1 (insclusive)
#define KB_START KB_PORTB_CTRL
#define KB_ADDRESS KB_PORTB_CTRL
// Keyboard register addresses (SH4-specific)
#define KEYSC_ADDRESS 0xA44B0000
#define KEYSC_SIZE (6 * 2)
// GetKey codes
#define KEY_EXIT 30002
@ -23,7 +27,7 @@
#define DEFAULT_REPEAT_TIME_NEXT_COUNT 5
struct keyboard_t {
uint8_t row_state[10]; // Keyboard rows state (1 = key not pressed)
uint8_t row_state[10]; // Keyboard rows state
uint8_t keyboard_registers[KB_SIZE]; // Keyboard registers
// Buffered keys that are waiting to be read

View File

@ -2,8 +2,8 @@
#include "syscalls.h"
#define MALLOC_START 0x22220000
#define MALLOC_SIZE (128 * 1024)
#define MALLOC_ADDRESS 0x22220000
#define MALLOC_SIZE (256 * 1024)
// Ugly malloc manager that works for testing
struct malloc_manager_t {

View File

@ -24,6 +24,7 @@ void syscall_Locate(cpu_t* cpu, int x, int y);
void syscall_Cursor_SetPosition(cpu_t* cpu, uint32_t column, uint32_t row);
void syscall_Cursor_GetFlashStyle(cpu_t* cpu);
void syscall_Cursor_SetFlashOn(cpu_t* cpu, uint32_t flash_style);
void syscall_Cursor_SetFlashOff(cpu_t* cpu);
void syscall_Cursor_SetFlashMode(cpu_t* cpu, uint32_t flashmode);
void draw_cursor(cpu_t* cpu);

View File

@ -62,7 +62,6 @@ display_t* init_display(memory_t* memory) {
// Init cursor
disp->cursor.row = 1;
disp->cursor.col = 1;
disp->cursor.flash_style = -1;
// Init useful SDK data
load_data_file("CharacterSet.data", CHARACTER_SET_SIZE, disp->character_set);
@ -92,7 +91,6 @@ cpu_t* init_cpu(memory_t* mem, display_t* disp) {
cpu->keyboard = calloc(1, sizeof(keyboard_t));
cpu->keyboard->repeat_time_first = DEFAULT_REPEAT_TIME_FIRST_COUNT;
cpu->keyboard->repeat_time_next = DEFAULT_REPEAT_TIME_NEXT_COUNT;
for (int i = 0; i < 10; i++) cpu->keyboard->row_state[i] = 0xFF;
cpu->malloc_manager = calloc(1, sizeof(malloc_manager_t));
cpu->malloc_manager->mallocs = malloc(MALLOC_SIZE * sizeof(int8_t));
@ -183,7 +181,8 @@ void init_loop_html(cpu_t* cpu) {
window.instructionPerFrame = $3;
window.instructionCount = $4;
window.rtcTicksPointer = $5;
window.cpuPointer = $6;
window.fsNeedsSyncPointer = $6;
window.cpuPointer = $7;
},
&cpu->disp->vram,
&cpu->disp->lcd,
@ -191,6 +190,7 @@ void init_loop_html(cpu_t* cpu) {
&cpu->instruction_per_frame,
&cpu->instruction_count,
&cpu->RTC_Ticks,
&cpu->fs->needs_sync,
cpu
);
@ -216,6 +216,7 @@ void reset_execution(cpu_t* cpu) {
for (int i = 0; i < VRAM_SIZE; i++) {
cpu->disp->vram[i] = 0;
cpu->disp->lcd[i] = 0;
}
free(cpu->fs);
@ -223,6 +224,10 @@ void reset_execution(cpu_t* cpu) {
cpu->malloc_manager->currentSize = 0;
cpu->malloc_manager->mallocCount = 0;
cpu->disp->cursor.row = 1;
cpu->disp->cursor.col = 1;
cpu->disp->cursor.flash_mode = 0;
}
void load_new_g1a(cpu_t* cpu, uint8_t* g1a_content, uint32_t g1a_size) {

View File

@ -20,9 +20,8 @@ uint8_t* get_memory_for_address(cpu_t* cpu, uint32_t address) {
if (check_memory_bounds(address, RAM_ADDRESS_P1, RAM_SIZE, cpu->mem->ram, &memory)) return memory;
if (check_memory_bounds(address, RAM_ADDRESS_P2, RAM_SIZE, cpu->mem->ram, &memory)) return memory;
if (check_memory_bounds(address, VRAM_ADDRESS, VRAM_SIZE, cpu->disp->vram, &memory)) return memory;
if (check_memory_bounds(address, VRAM_ADDRESS + VRAM_SIZE, 1, cpu->disp->vram, &memory)) return memory; // TODO: Check why Gravity Duck crash without this 1025th/1024 byte
if (check_memory_bounds(address, KB_START, KB_SIZE, cpu->keyboard->keyboard_registers, &memory)) return memory;
if (check_memory_bounds(address, MALLOC_START, MALLOC_SIZE, cpu->malloc_manager->mallocs, &memory)) return memory;
if (check_memory_bounds(address, KB_ADDRESS, KB_SIZE, cpu->keyboard->keyboard_registers, &memory)) return memory;
if (check_memory_bounds(address, MALLOC_ADDRESS, MALLOC_SIZE, cpu->malloc_manager->mallocs, &memory)) return memory;
if (check_memory_bounds(address, FKEYICON_ADDRESS, FKEYICON_SIZE, cpu->disp->fkey_icons, &memory)) return memory;
if (check_memory_bounds(address, 0xFFFFFE00, 511, cpu->mem->tmp, &memory)) {
printf("[Warning] Access to interrupt registers at 0x%08X\n", address);
@ -62,10 +61,22 @@ void mem_write(cpu_t* cpu, uint32_t address, uint32_t data, uint8_t bytes) {
// Read from the memory
uint32_t mem_read(cpu_t* cpu, uint32_t address, uint8_t bytes) {
// Keyboard output register
// SH3 keyboard emulation
if (address == KB_PORTA) {
return emulate_keyboard_register_read(cpu);
}
// SH4 keyboard emulation
else if (address >= KEYSC_ADDRESS && address < KEYSC_ADDRESS + KEYSC_SIZE) {
int row = address - KEYSC_ADDRESS;
int val;
if (bytes == 1)
val = cpu->keyboard->row_state[row + (row % 2 == 0 ? 1 : -1)];
else
val = cpu->keyboard->row_state[row] | (cpu->keyboard->row_state[row+1] << 8);
return val;
}
// Address that stores the model of the calculator (0 for emulator)
else if (address == 0x80000300) {
return 0;
@ -123,37 +134,49 @@ uint32_t emulate_keyboard_register_read(cpu_t* cpu) {
}
else {
// printf("Keyboard row %d: 0x%08X\n", row, cpu->keyboard->row_state[row]);
return cpu->keyboard->row_state[row];
return ~cpu->keyboard->row_state[row];
}
}
// Keep track of current row and column set in the LCD selector register
// and write data to the LCD buffer.
// Refresh the HTML canvas when the last row is written.
// Works well for MonochromeLib's DisplayVRAM() function, but might
// not work for more specific register accesses.
// Emulate register selection and data write to the LCD screen
// Register 1: Set counter (Graph 35+)
// Register 4/8: Set row (Graph 35+/35+eII)
// Register 6: Set contrast (Graph 35+)
// Register 7/10: Write data (Graph 35+/35+eII)
// https://bible.planet-casio.com/common/hardware/lcd/T6K11.pdf
void emulate_lcd_register_write(cpu_t* cpu, uint32_t address, uint32_t data) {
static int row = -1;
static int selected_register = 0;
static int col = 0;
static int write_data = 0;
static int row = 0;
// Setup LCD row
// Register selection
if (address == LCD_SELECT_REGISTER) {
if (data == 7) { // New row
write_data = 1;
col = 0;
if (++row >= 64) row = 0;
// printf("Set row: %d\n", row);
selected_register = data;
if (data != 1 && data != 4 && data != 6 && data != 7 && data != 8 && data != 10) {
printf("[Warning] write to LCD_SELECT_REGISTER %d not implemented\n", data);
}
else {
write_data = 0;
}
// printf("LCD_SELECT_REGISTER Write: 0x%08X, set row: %d\n", data, row);
}
// Write data to LCD row
else if (address == LCD_DATA_REGISTER) {
if (write_data) {
cpu->disp->lcd[row * 16 + col++] = data; // Update LCD buffer
// Data write
else if (address == LCD_DATA_REGISTER) {
// Graph 35+ (4), Graph 35+ E II (8)
if (selected_register == 4 || selected_register == 8) {
static int counter = 1;
if (counter) {
// Set new row
col = 0;
row = data & 0x3F;
}
counter = !counter;
}
// Graph 35+ (7), Graph 35+ E II (10)
else if (selected_register == 7 || selected_register == 10) {
if (row * 16 + col >= VRAM_SIZE) {
printf("[Warning] LCD_DATA_REGISTER write to invalid position col: %d, row: %d\n", col, row);
return;
}
// Write row to LCD buffer
cpu->disp->lcd[row * 16 + col++] = data;
}
}
}

View File

@ -1,13 +1,5 @@
#include "../headers/syscalls/bdisp.h"
// Refresh the HTML canvas with the current
// content of the LCD buffer.
void refresh_lcd_screen() {
#ifdef USE_EMSCRIPT
EM_ASM({ window.refreshScreen(); });
#endif
}
// Set the pixel at the specified position in the LCD buffer.
void set_lcd_pixel(cpu_t* cpu, int x, int y, int pixel) {
if (x < 0 || x >= SCREEN_WIDTH || y < 0 || y >= SCREEN_HEIGHT) return;
@ -22,7 +14,6 @@ void syscall_Bdisp_AllClr_DD(cpu_t* cpu) {
for (int i = 0; i < VRAM_SIZE; i++) {
cpu->disp->lcd[i] = 0;
}
refresh_lcd_screen();
}
// Clear the content of the VRAM
@ -45,11 +36,10 @@ void syscall_Bdisp_PutDisp_DD(cpu_t* cpu) {
for (int i = 0; i < VRAM_SIZE; i++) {
cpu->disp->lcd[i] = cpu->disp->vram[i];
}
refresh_lcd_screen();
}
void syscall_Bdisp_GetDisp_VRAM(cpu_t* cpu, uint32_t data_ptr) {
printf("Run syscall: Bdisp_GetDisp_VRAM (0x%08X)\n", data_ptr);
// printf("Run syscall: Bdisp_GetDisp_VRAM (0x%08X)\n", data_ptr);
uint8_t* data = get_memory_for_address(cpu, data_ptr);
@ -72,7 +62,7 @@ void syscall_Bdisp_SetPoint_VRAM(cpu_t* cpu, uint32_t x, uint32_t y, uint32_t po
uint32_t vramID = x/8 + y * 16;
uint8_t bit = 7 - x % 8;
cpu->disp->vram[vramID] = (cpu->disp->vram[vramID] & ~(1 << bit)) | (point << bit);
update_bit(cpu->disp->vram[vramID], bit, point);
}
/**
@ -130,13 +120,13 @@ void syscall_Bdisp_DrawLine_VRAM(cpu_t* cpu, uint32_t x1, uint32_t y1, uint32_t
// Draws a white line to VRAM.
void syscall_Bdisp_ClearLine_VRAM(cpu_t* cpu, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2) {
printf("Run syscall: Bdisp_ClearLine_VRAM (%d %d %d %d)\n", x1, y1, x2, y2);
// printf("Run syscall: Bdisp_ClearLine_VRAM (%d %d %d %d)\n", x1, y1, x2, y2);
draw_line(cpu, x1, y1, x2, y2, 0);
}
// Reverses the specified area of VRAM.
void syscall_Bdisp_AreaReverseVRAM(cpu_t* cpu, uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2) {
printf("Run syscall: Bdisp_AreaReverseVRAM (%d %d %d %d)\n", x1, y1, x2, y2);
// printf("Run syscall: Bdisp_AreaReverseVRAM (%d %d %d %d)\n", x1, y1, x2, y2);
for (int y = y1; y <= y2; y++) {
for (int x = x1; x <= x2; x++) {
@ -166,7 +156,7 @@ void syscall_Bdisp_WriteGraph_VRAM(cpu_t* cpu, uint32_t graph_ptr) {
uint8_t write_modify = mem_read(cpu, graph_ptr + 20, 1);
uint8_t write_kind = mem_read(cpu, graph_ptr + 21, 1);
if ((write_modify != IMB_WRITEMODIFY_NORMAL && write_modify != IMB_WRITEMODIFY_REVERSE) || write_kind != 1) {
if ((write_modify != IMB_WRITEMODIFY_NORMAL && write_modify != IMB_WRITEMODIFY_REVERSE) || (write_kind != IMB_WRITEKIND_OVER && write_kind != IMB_WRITEKIND_OR)) {
printf("[Warning] In syscall Bdisp_WriteGraph_VRAM: write_modify or write_kind not implemented (%d, %d)\n", write_modify, write_kind);
return;
}
@ -174,14 +164,23 @@ void syscall_Bdisp_WriteGraph_VRAM(cpu_t* cpu, uint32_t graph_ptr) {
// printf("Run syscall: Bdisp_WriteGraph_VRAM (x: %d, y: %d, w: %d, h: %d, modify: %d, kind: %d)\n", start_x, start_y, width, height, write_modify, write_kind);
uint8_t* bitmap_data = get_memory_for_address(cpu, bitmap_ptr);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int id = y * 8 + x;
int id = y * (width < 8 ? 8 : width) + x;
int packed_id = id / 8;
int bit = 7 - id % 8;
int val = get_bit(bitmap_data[packed_id], bit);
if (write_modify == IMB_WRITEMODIFY_REVERSE) val = !val;
if (write_kind == IMB_WRITEKIND_OR) {
int vram_id = (y + start_y) * 16 + (x + start_x) / 8;
int vram_bit = 7 - (x + start_x) % 8;
if (vram_id < 0 || vram_id >= VRAM_SIZE) continue;
int vram_pixel = get_bit(cpu->disp->vram[vram_id], vram_bit);
val |= vram_pixel;
}
syscall_Bdisp_SetPoint_VRAM(cpu, x + start_x, y + start_y, val);
}
}
@ -195,7 +194,7 @@ void syscall_Bdisp_WriteGraph_VRAM(cpu_t* cpu, uint32_t graph_ptr) {
void syscall_SaveDisp(cpu_t* cpu, unsigned char num) {
num = num == SAVEDISP_PAGE1 ? num - 1 : num - 4;
printf("Run syscall: SaveDisp (%d)\n", num);
// printf("Run syscall: SaveDisp (%d)\n", num);
memcpy(cpu->disp->saved_disps + VRAM_SIZE*num, cpu->disp->vram, VRAM_SIZE);
}
@ -208,7 +207,7 @@ void syscall_SaveDisp(cpu_t* cpu, unsigned char num) {
void syscall_RestoreDisp(cpu_t* cpu, unsigned char num) {
num = num == SAVEDISP_PAGE1 ? num - 1 : num - 4;
printf("Run syscall: RestoreDisp (%d)\n", num);
// printf("Run syscall: RestoreDisp (%d)\n", num);
memcpy(cpu->disp->vram, cpu->disp->saved_disps + VRAM_SIZE*num, VRAM_SIZE);
}

View File

@ -1,5 +1,6 @@
#include "../headers/syscalls/filesystem.h"
#include <dirent.h>
#include <ctype.h>
const char* permanent_path(const char* filename) {
char* path = malloc(sizeof(char) * (strlen(filename) + 7));
@ -8,6 +9,17 @@ const char* permanent_path(const char* filename) {
return (const char*)path;
}
// Lowercase the file extension
const char* lower_extension(const char* str) {
char* new_str = strdup(str);
int ext = 0;
for (int i = 0; i < strlen(new_str); i++) {
if (new_str[i] == '.') ext = 1;
else if (ext) new_str[i] = tolower(new_str[i]);
}
return (const char*)new_str;
}
const char* convertFileName(const char* filename, int trim) {
char name[40];
char ch;
@ -48,6 +60,7 @@ void syscall_Bfile_CreateEntry(cpu_t* cpu, uint32_t filename_ptr, int mode, uint
fwrite(data, 1, size, file);
fclose(file);
cpu->fs->needs_sync = 1;
R0 = 0; // Success
printf("Run syscall: Bfile_CreateEntry %s (0x%X, size: %d)\n", name, mode, mem_read(cpu, size_ptr, 4));
@ -72,6 +85,7 @@ void syscall_Bfile_DeleteEntry(cpu_t* cpu, uint32_t filename_ptr, int mode) {
const char* name = convertFileName(filename, 1);
if (remove(permanent_path(name)) == 0) {
cpu->fs->needs_sync = 1;
R0 = 0; // Success
printf("Run syscall: Bfile_DeleteEntry %s\n", name);
}
@ -84,7 +98,7 @@ void syscall_Bfile_DeleteEntry(cpu_t* cpu, uint32_t filename_ptr, int mode) {
// Used by Bfile_FindFirst and Bfile_FindNext
// Search an entry matching a search string starting from the specified index
// Writes the entry name to foundfile_ptr and the entry infos to fileinfo_ptr
int search_file(cpu_t* cpu, const char* search_str, uint32_t foundfile_ptr, uint32_t fileinfo_ptr, int index) {
int search_file(cpu_t* cpu, const char* search_string, uint32_t foundfile_ptr, uint32_t fileinfo_ptr, int index) {
// Open root directory
struct dirent *dir;
DIR *d = opendir("/idbfs");
@ -97,10 +111,13 @@ int search_file(cpu_t* cpu, const char* search_str, uint32_t foundfile_ptr, uint
int file_index = 0;
int found_type = -1;
char* found_name;
// Lowercase the file extension
const char* search_str = lower_extension(search_string);
// Loop through each file
while ((dir = readdir(d)) != NULL) {
if ((strcmp(search_str, "*.*") == 0 || strcmp(dir->d_name, search_str) == 0) && file_index >= index) {
while ((dir = readdir(d)) != NULL) {
if (((strcmp(search_str, "*.*") == 0 || strcmp(lower_extension(dir->d_name), search_str) == 0)) && file_index >= index) {
// Matching file found
found_type = dir->d_type;
found_name = strdup(dir->d_name);
@ -385,6 +402,7 @@ void syscall_Bfile_WriteFile(cpu_t* cpu, int handle, uint32_t buf_ptr, int size)
fwrite(&byte, 1, 1, file->file_handle);
}
cpu->fs->needs_sync = 1;
R0 = file->seek_pos;
}
@ -631,6 +649,7 @@ void syscall_MCSPutVar2(cpu_t* cpu, int32_t dir_ptr, int32_t item_ptr, int32_t d
fwrite(data, 1, data_len, file);
fclose(file);
cpu->fs->needs_sync = 1;
R0 = 0;
}
@ -668,6 +687,7 @@ void syscall_MCSOvwDat2(cpu_t* cpu, int32_t dir_ptr, int32_t item_ptr, int32_t b
fwrite(data + write_offset, 1, bytes_to_write, file);
fclose(file);
cpu->fs->needs_sync = 1;
R0 = 0;
}
@ -687,6 +707,7 @@ void syscall_MCSDelVar2(cpu_t* cpu, int32_t dir_ptr, int32_t item_ptr) {
// Delete file
if (remove(file_path) == 0) {
cpu->fs->mcs_filename = NULL;
cpu->fs->needs_sync = 1;
printf("Run syscall: MCSDelVar2, deleted file %s. MCS cleared\n", file_path);
R0 = 0;
}
@ -736,14 +757,29 @@ void syscall_MCS_SearchDirectoryItem(cpu_t* cpu, int32_t dir_ptr, int32_t item_n
// Get file size
fseek(file, 0, SEEK_END);
int32_t file_size = ftell(file);
fclose(file);
mem_write(cpu, data_ptr, 0x00000000, 4); // ???
mem_write(cpu, item_ptr, 0x00000000, 4); // ???
mem_write(cpu, len_ptr, file_size, 4);
fseek(file, 0, SEEK_SET);
printf("Run syscall: MCS_SearchDirectoryItem %s (0x%8X, 0x%8X, 0x%8X, 0x%8X) => %d\n", item_path, flags_ptr, item_ptr, data_ptr, len_ptr, file_size);
// TODO: Improve this (quick hack)
static int mcs_storage = 0;
if (mcs_storage == 0) {
syscall_Malloc(cpu, 32 * 1024, 0);
mcs_storage = R0;
}
for (int i = 0; i < file_size; i++) {
uint8_t byte;
fread(&byte, 1, 1, file);
mem_write(cpu, mcs_storage + i, byte, 1);
}
fclose(file);
mem_write(cpu, data_ptr, mcs_storage, 4);
mem_write(cpu, item_ptr, 0x000000bb, 4); // ???
mem_write(cpu, len_ptr, file_size, 4);
R0 = 0;
}
@ -755,9 +791,41 @@ void syscall_MCS_SearchDirectoryItem(cpu_t* cpu, int32_t dir_ptr, int32_t item_n
void syscall_MCS_OverwriteData(cpu_t* cpu, int32_t dir_ptr, int32_t item_ptr, int32_t write_offset, int32_t bytes_to_write, int32_t buffer_ptr) {
const char* item_path = getFilePath(cpu, dir_ptr, item_ptr);
printf("[Warning]: Skipped syscall MCS_OverwriteData %s (offset: %d, bytes: %d, buffer: 0x%8X)\n", item_path, write_offset, bytes_to_write, buffer_ptr);
printf("[Warning]: Run syscall MCS_OverwriteData %s (offset: %d, bytes: %d, buffer: 0x%8X)\n", item_path, write_offset, bytes_to_write, buffer_ptr);
R0 = 0x13;
FILE* file = fopen(item_path, "rb");
if (file == NULL) {
printf("[Warning] In syscall MCS_OverwriteData: File does not exist: %s\n", item_path);
R0 = 0x40;
return;
}
// Get file size
fseek(file, 0, SEEK_END);
int32_t file_size = ftell(file);
fclose(file);
if (write_offset + bytes_to_write > file_size) {
printf("[Warning] In syscall MCS_OverwriteData: Write offset + bytes to write exceeds file size: %s\n", item_path);
R0 = bytes_to_write > file_size ? 0x13 : 0x14;
return;
}
// Open file for writing
file = fopen(item_path, "wb");
fseek(file, write_offset, SEEK_SET);
for (int i = 0; i < bytes_to_write; i++) {
uint8_t byte = mem_read(cpu, buffer_ptr + i, 1);
fwrite(&byte, 1, 1, file);
}
fclose(file);
// fwrite(get_memory_for_address(cpu, buffer_ptr) + write_offset, 1, bytes_to_write, file);
cpu->fs->needs_sync = 1;
R0 = 0;
}
// Deletes dir.item.

View File

@ -44,19 +44,29 @@ EM_ASYNC_JS(int*, async_browser_getkey, (), {
// Used to resolve the promise when loading a new .g1a file (blocking otherwise)
window.getkeyEventResolve = resolve;
const onClick = (event) => {
const res = window.keyboardEvent(event, 'getkey');
if (res != null) {
// Valid key pressed, remove the event listener and return the key
document.getElementById("keyboard").removeEventListener("pointerdown", onClick);
const try_resolve_key = (key) => {
if (key != null) {
// Valid key pressed, remove the event listeners and return the key
window.removeEventListener("keydown", onKeyboardEvent);
document.getElementById("keyboard").removeEventListener("pointerdown", onClickEvent);
window.getkeyEventResolve = null;
resolve(res);
resolve(key);
}
};
const onClickEvent = (event) => {
const res = window.handleKeyboardEvent(event, "getkey");
try_resolve_key(res);
};
const onKeyboardEvent = (event) => {
const res = window.onKeyUpdate(event, "getkey");
try_resolve_key(res);
};
// Add a click event listener to the keyboard
document.getElementById("keyboard").addEventListener("pointerdown", onClick);
window.addEventListener("keydown", onKeyboardEvent);
document.getElementById("keyboard").addEventListener("pointerdown", onClickEvent);
});
})
#endif
@ -108,6 +118,7 @@ void syscall_GetKey(cpu_t* cpu, unsigned int keycode_address) {
void syscall_KeyBoard_GetKeyWait(cpu_t* cpu, uint32_t column_ptr, uint32_t row_ptr, uint32_t type_of_waiting, uint32_t timeout_period, uint32_t menu, uint32_t keycode_ptr) {
printf("[Warning]: Skipped syscall KeyBoard_GetKeyWait (wait type: %d, timeout: %d, menu: %d)X\n", type_of_waiting, timeout_period, menu);
syscall_Bdisp_PutDisp_DD(cpu);
mem_write(cpu, keycode_ptr, 0, 2);
R0 = 0;

View File

@ -9,7 +9,7 @@ void syscall_Malloc(cpu_t* cpu, uint32_t size, uint8_t clear_data) {
// Use the first 4 bytes to store the size of the malloc
*(uint32_t*)(&m->mallocs[m->currentSize]) = size;
R0 = MALLOC_START + m->currentSize + 4;
R0 = MALLOC_ADDRESS + m->currentSize + 4;
// Clear the data
for (int i = 0; i < size; i++) {
@ -19,7 +19,7 @@ void syscall_Malloc(cpu_t* cpu, uint32_t size, uint8_t clear_data) {
m->currentSize += size + 4;
m->mallocCount++;
printf("Run syscall: %salloc #%d (size: %d, addr: 0x%X) Total allocated: %d\n", clear_data ? clear_data == 1 ? "C" : "Re" : "M", m->mallocCount, size, R0, m->currentSize - m->mallocCount);
printf("Run syscall: %salloc #%d (size: %d, addr: 0x%X) Total allocated: %d\n", clear_data ? clear_data == 1 ? "C" : "Re" : "M", m->mallocCount, size, R0, m->currentSize - m->mallocCount*4);
}
void syscall_Realloc(cpu_t* cpu, uint32_t ptr, uint32_t size) {
@ -30,11 +30,11 @@ void syscall_Realloc(cpu_t* cpu, uint32_t ptr, uint32_t size) {
if (ptr == 0x0) return; // No pointer to reallocate, act as a malloc only
// Get the size of the previous malloc
uint32_t prev_size = *(uint32_t*)(&mallocs[ptr - MALLOC_START - 4]);
uint32_t prev_size = *(uint32_t*)(&mallocs[ptr - MALLOC_ADDRESS - 4]);
// Transfer data to the new malloc
for (int i = 0; i < prev_size; i++) {
mallocs[R0 - MALLOC_START + i] = mallocs[ptr - MALLOC_START + i];
mallocs[R0 - MALLOC_ADDRESS + i] = mallocs[ptr - MALLOC_ADDRESS + i];
}
syscall_Free(cpu, ptr);

View File

@ -75,10 +75,10 @@ void syscall_OpcodeToStr(cpu_t* cpu, uint32_t opcode, uint32_t string_ptr) {
printf("[Warning] In syscall OpcodeToStr: Invalid opcode: %d\n", opcode);
return;
}
if (opcode >= 63745) opcode -= 63745 - 1201;
if (opcode >= 63745) opcode -= 63745 - 1202;
else if (opcode >= 63232) opcode -= 63232 - 981;
else if (opcode >= 58624) opcode -= 58624 - 501;
else if (opcode >= 32512) opcode -= 32512 - 256;
else if (opcode >= 58624) opcode -= 58624 - 500;
else if (opcode >= 32512) opcode -= 32512 - 255;
for (int i = 0; i <= 15; i++) {
char current = cpu->disp->opcodes[opcode * 15 + i];

View File

@ -37,6 +37,7 @@ void run_syscall(cpu_t* cpu) {
else if (syscall_code == 0x138) syscall_Cursor_SetPosition(cpu, R4, R5);
else if (syscall_code == 0x80E) syscall_Cursor_GetFlashStyle(cpu);
else if (syscall_code == 0x811) syscall_Cursor_SetFlashOn(cpu, R4);
else if (syscall_code == 0x812) syscall_Cursor_SetFlashOff(cpu);
else if (syscall_code == 0x13A) syscall_Cursor_SetFlashMode(cpu, R4);
else if (syscall_code == 0xACD) syscall_Malloc(cpu, R4, 0);
@ -90,6 +91,7 @@ void run_syscall(cpu_t* cpu) {
else if (syscall_code == 0x3ED) { // Interrupt_SetOrClrStatusFlags
// https://bible.planet-casio.com/simlo/chm/v20/fx_legacy_INTERRUPT.HTM
printf("[Error] Blocking syscall not implemented: Interrupt_SetOrClrStatusFlags 0x%X\n", R5);
cpu->execution_finished = 1;
}
// Can be ignored
else if (syscall_code == 0x494) printf("Ignored syscall: SetQuitHandler\n");

View File

@ -273,42 +273,32 @@ void syscall_Cursor_SetPosition(cpu_t* cpu, uint32_t column, uint32_t row) {
// Returns the current cursor flash style
void syscall_Cursor_GetFlashStyle(cpu_t* cpu) {
// printf("Run syscall: Cursor_GetFlashStyle (%d)\n", cpu->disp->cursor.flash_style);
R0 = cpu->disp->cursor.flash_style;
// printf("Cursor style: %d, mode: %d\n", cpu->disp->cursor.flash_style, cpu->disp->cursor.flash_mode);
// printf("Run syscall: Cursor_GetFlashStyle => %d\n", cpu->disp->cursor.flash_style);
R0 = cpu->disp->cursor.flash_mode == 0 ? -1 : cpu->disp->cursor.flash_style;
}
// Sets the cursor flash style
// Remarks:
// - Sets flashmode on
// - Resets to cursor-textmode
// - Resets to cursor-textmode (?)
void syscall_Cursor_SetFlashOn(cpu_t* cpu, uint32_t flash_style) {
uint32_t mapped_style;
// printf("Run syscall: Cursor_SetFlashOn (%d)\n", flash_style);
cpu->disp->cursor.flash_style = flash_style;
cpu->disp->cursor.flash_mode = 1;
cpu->disp->cursor.blink_state = 0;
draw_cursor(cpu);
}
// printf("Cursor style: %d, mode: %d\n", cpu->disp->cursor.flash_style, cpu->disp->cursor.flash_mode);
// Disables cursor flashing
void syscall_Cursor_SetFlashOff(cpu_t* cpu) {
// printf("Run syscall: Cursor_SetFlashOff\n");
cpu->disp->cursor.flash_mode = 0;
}
// If flashmode is 0, the Flash mode is set to 0 and cursor flashing is turned off.
// If flashmode is nonzero, Flash mode is set to 1, and cursor flashing is turned on.
void syscall_Cursor_SetFlashMode(cpu_t* cpu, uint32_t flashmode) {
// printf("Run syscall: Cursor_SetFlashMode (%d)\n", flashmode);
if (flashmode == 0) {
cpu->disp->cursor.flash_mode = 0;
}
else {
cpu->disp->cursor.flash_mode = 1;
}
// printf("Cursor style: %d, mode: %d\n", cpu->disp->cursor.flash_style, cpu->disp->cursor.flash_mode);
cpu->disp->cursor.flash_mode = flashmode;
}
// Draw the cursor on the LCD screen