Compare commits

...

2 Commits

Author SHA1 Message Date
kishimisu 9d17d644cc add SaveDisp/RestoreDisp syscalls 2023-11-22 20:54:11 +01:00
kishimisu 961c0c1d77 add Bdisp_DrawLine_VRAM syscall 2023-11-22 02:58:14 +01:00
11 changed files with 155 additions and 60 deletions

View File

@ -27,7 +27,7 @@ Then:
Then, until I find a nicer way to integrate this into the Makefile, run the following command:
emcc -O2 ".\CMakeFiles\fx9860-emulator.dir\main.o" ".\CMakeFiles\fx9860-emulator.dir\utils.o" ".\CMakeFiles\fx9860-emulator.dir\memory.o" ".\CMakeFiles\fx9860-emulator.dir\instructions\instructions.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\syscalls.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\filesystem.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\malloc.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\misc.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\print.o" \
emcc -O2 ".\CMakeFiles\fx9860-emulator.dir\main.o" ".\CMakeFiles\fx9860-emulator.dir\utils.o" ".\CMakeFiles\fx9860-emulator.dir\memory.o" ".\CMakeFiles\fx9860-emulator.dir\instructions\instructions.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\syscalls.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\filesystem.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\malloc.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\misc.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\bdisp.o" ".\CMakeFiles\fx9860-emulator.dir\syscalls\text.o" \
--embed-file "..\..\U+0020.png@U+0020.png" \
--embed-file "..\..\PrintMini.bmp@PrintMini.bmp" \
--embed-file "..\..\JJSH3.G1A@JJSH3.G1A" \

View File

@ -12,12 +12,14 @@ add_executable (fx9860-emulator
"syscalls/filesystem.c"
"syscalls/malloc.c"
"syscalls/misc.c"
"syscalls/print.c"
"syscalls/bdisp.c"
"syscalls/text.c"
"headers/syscalls/syscalls.h"
"headers/syscalls/filesystem.h"
"headers/syscalls/malloc.h"
"headers/syscalls/misc.h"
"headers/syscalls/print.h"
"headers/syscalls/bdisp.h"
"headers/syscalls/text.h"
"headers/stb_image.h"
"headers/display.h"
)

View File

@ -27,6 +27,8 @@ struct display_t {
// LCD screen emulation
uint8_t lcd_registers; // Use for both selector & data registers
uint8_t saved_disps[VRAM_SIZE * 3]; // used in SaveDisp and RestoreDisp syscalls
// Current cursor position
cursor_t cursor;
};

View File

@ -5,7 +5,7 @@
// Memory start addresses
#define ROM_START 0x00300000
#define RAM_START_MMU_ALIAS 0x08100000
#define RAM_START 0x8801c000 // 0x88048000 on 35+E II
#define RAM_START 0x88000000 // 0x8801c000 // 0x88048000 on 35+E II
#define XRAM_START 0xe5007000
#define YRAM_START 0xe5017000
#define ILRAM_START 0xe5200000

View File

@ -0,0 +1,18 @@
#pragma once
#include "syscalls.h"
#define SAVEDISP_PAGE1 1
#define SAVEDISP_PAGE2 5
#define SAVEDISP_PAGE3 6
void syscall_Bdisp_AllClr_DD(cpu_t* cpu);
void syscall_Bdisp_AllClr_VRAM(cpu_t* cpu);
void syscall_Bdisp_AllClr_DDVRAM(cpu_t* cpu);
void syscall_Bdisp_PutDisp_DD(cpu_t* cpu);
void syscall_Bdisp_SetPoint_VRAM(cpu_t* cpu, uint32_t x, uint32_t y, uint32_t point);
void syscall_Bdisp_DrawLine_VRAM(cpu_t* cpu, int x1, int y1, int x2, int y2);
void syscall_SaveDisp(cpu_t* cpu, unsigned char num);
void syscall_RestoreDisp(cpu_t* cpu, unsigned char num);

View File

@ -2,7 +2,8 @@
#include "../main.h"
#include "filesystem.h"
#include "print.h"
#include "bdisp.h"
#include "text.h"
#include "malloc.h"
#include "misc.h"

View File

@ -10,12 +10,6 @@
#define CHAR_WIDTH 6
#define CHAR_HEIGHT 8
void syscall_Bdisp_AllClr_DD(cpu_t* cpu);
void syscall_Bdisp_AllClr_VRAM(cpu_t* cpu);
void syscall_Bdisp_AllClr_DDVRAM(cpu_t* cpu);
void syscall_Bdisp_PutDisp_DD(cpu_t* cpu);
void syscall_Bdisp_SetPoint_VRAM(cpu_t* cpu, uint32_t x, uint32_t y, uint32_t point);
void syscall_Locate(cpu_t* cpu, int x, int y);
void syscall_Print(cpu_t* cpu, uint32_t str_ptr);
void syscall_PrintXY(cpu_t* cpu, int x, int y, uint32_t str_ptr, int mode);

View File

@ -0,0 +1,110 @@
#include "../headers/syscalls/bdisp.h"
// Clear the content of the screen
void syscall_Bdisp_AllClr_DD(cpu_t* cpu) {
// Does nothing for now
}
// Clear the content of the VRAM
void syscall_Bdisp_AllClr_VRAM(cpu_t* cpu) {
for (int i = 0; i < VRAM_SIZE; i++) {
cpu->disp->vram[i] = 0;
}
}
// Clear the content of the VRAM and the screen
void syscall_Bdisp_AllClr_DDVRAM(cpu_t* cpu) {
syscall_Bdisp_AllClr_DD(cpu);
syscall_Bdisp_AllClr_VRAM(cpu);
}
// Transfer the contents of VRAM to the screen.
void syscall_Bdisp_PutDisp_DD(cpu_t* cpu) {
// printf("Run syscall: Bdisp_PutDisp_DD\n");
#ifdef USE_EMSCRIPT
EM_ASM({
window.refreshScreen();
});
#endif
}
/**
* Set or erase a dot at the specified position of VRAM and/or DD (Display Driver).
* @param x (0~127) This is the x coordinate of the specified position.
* @param y (0~63) This is the y coordinate of the specified position.
* @param point If you set point to 1 then the dot is made black. If you set point to 0 then the dot is cleared.
*/
void syscall_Bdisp_SetPoint_VRAM(cpu_t* cpu, uint32_t x, uint32_t y, uint32_t point) {
uint32_t vramID = x/8 + y * 16;
uint8_t bit = 7 - x % 8;
if (vramID < 0 || vramID >= VRAM_SIZE) return;
cpu->disp->vram[vramID] = (cpu->disp->vram[vramID] & ~(1 << bit)) | (point << bit);
}
/**
* Draws a line to VRAM.
* Code from the MonochromeLib library's ML_Line() function.
* @param x1 (0 ~ 127) x starting point
* @param y1 (0 ~ 63) y starting point
* @param x2 (0 ~ 127) x ending point
* @param y2 (0 ~ 63) y ending point
*/
void syscall_Bdisp_DrawLine_VRAM(cpu_t* cpu, int x1, int y1, int x2, int y2) {
int x = x1;
int y = y1;
int dx = x2 - x1;
int dy = y2 - y1;
int sx = dx < 0 ? -1 : 1;
int sy = dy < 0 ? -1 : 1;
dx = abs(dx);
dy = abs(dy);
syscall_Bdisp_SetPoint_VRAM(cpu, x, y, 1);
if(dx > dy) {
int cumul = dx / 2;
for(int i = 1; i < dx; i++) {
x += sx;
cumul += dy;
if(cumul > dx) {
cumul -= dx;
y += sy;
}
syscall_Bdisp_SetPoint_VRAM(cpu, x, y, 1);
}
}
else {
int cumul = dy / 2;
for(int i = 1; i < dy; i++) {
y += sy;
cumul += dx;
if(cumul > dy) {
cumul -= dy;
x += sx;
}
syscall_Bdisp_SetPoint_VRAM(cpu, x, y, 1);
}
}
}
/**
* Saves a screen image in the system area.
* @param num SAVEDISP_PAGE1 - SAVEDISP_PAGE3.
* @remarks The screen image is copied from VRAM.
*/
void syscall_SaveDisp(cpu_t* cpu, unsigned char num) {
num = num == SAVEDISP_PAGE1 ? num - 1 : num - 4;
memcpy(cpu->disp->saved_disps + VRAM_SIZE*num, cpu->disp->vram, VRAM_SIZE);
}
/**
* Restores a screen image from the system area.
* @param num SAVEDISP_PAGE1 - SAVEDISP_PAGE3.
* @remarks The screen image is copied to VRAM.
*/
void syscall_RestoreDisp(cpu_t* cpu, unsigned char num) {
num = num == SAVEDISP_PAGE1 ? num - 1 : num - 4;
memcpy(cpu->disp->vram, cpu->disp->saved_disps + VRAM_SIZE*num, VRAM_SIZE);
}

View File

@ -56,7 +56,7 @@ void syscall_RTC_GetTicks(cpu_t* cpu) {
// https://bible.planet-casio.com/simlo/chm/v20/fx_legacy_Sleep.HTM
void syscall_OS_inner_Sleep(cpu_t* cpu, uint32_t ms) {
#ifdef USE_EMSCRIPT
emscripten_sleep(ms * .75);
emscripten_sleep(ms * .75);
#endif
// printf("Run syscall: OS_inner_Sleep %d\n", ms);
}
@ -67,11 +67,11 @@ EM_ASYNC_JS(int, async_browser_getkey, (), {
const onClick = (event) => {
const res = window.keyboardEvent(event, 'getkey');
if (res != null) {
document.getElementById("keyboard").removeEventListener("click", onClick);
document.getElementById("keyboard").removeEventListener("pointerdown", onClick);
resolve(res);
}
};
document.getElementById("keyboard").addEventListener("click", onClick);
document.getElementById("keyboard").addEventListener("pointerdown", onClick);
});
})
#else
@ -83,9 +83,13 @@ int async_browser_getkey() {
void syscall_GetKey(cpu_t* cpu, unsigned int keycode_address) {
printf("Run syscall: GetKey\n");
syscall_Bdisp_PutDisp_DD(cpu); // Update display
int key = async_browser_getkey();
mem_write(cpu, keycode_address, key, 4);
printf("Return key: %d\n", key);
R0 = key;
}

View File

@ -10,9 +10,14 @@ void run_syscall(cpu_t* cpu) {
int arg4 = cpu->r[7];
if (syscall_code == 0x135) syscall_GetVRAMAddress(cpu);
else if (syscall_code == 0x143) syscall_Bdisp_AllClr_VRAM(cpu);
else if (syscall_code == 0x144) syscall_Bdisp_AllClr_DDVRAM(cpu);
else if (syscall_code == 0x028) syscall_Bdisp_PutDisp_DD(cpu);
else if (syscall_code == 0x146) syscall_Bdisp_SetPoint_VRAM(cpu, arg1, arg2, arg3);
else if (syscall_code == 0x030) syscall_Bdisp_DrawLine_VRAM(cpu, arg1, arg2, arg3, arg4);
else if (syscall_code == 0x813) syscall_SaveDisp(cpu, arg1);
else if (syscall_code == 0x814) syscall_RestoreDisp(cpu, arg1);
else if (syscall_code == 0x807) syscall_Locate(cpu, arg1, arg2);
else if (syscall_code == 0x808) syscall_Print(cpu, arg1);
else if (syscall_code == 0x9AD) syscall_PrintXY(cpu, arg1, arg2, arg3, arg4);

View File

@ -1,45 +1,4 @@
#include "../headers/syscalls/print.h"
// These functions clear the specified area of VRAM and/or DD (Display Driver).
void syscall_Bdisp_AllClr_DD(cpu_t* cpu) {
// Does nothing for now
}
void syscall_Bdisp_AllClr_VRAM(cpu_t* cpu) {
for (int i = 0; i < VRAM_SIZE; i++) {
cpu->disp->vram[i] = 0;
}
}
void syscall_Bdisp_AllClr_DDVRAM(cpu_t* cpu) {
printf("Run syscall: Bdisp_AllClr_DDVRAM\n");
syscall_Bdisp_AllClr_DD(cpu);
syscall_Bdisp_AllClr_VRAM(cpu);
}
void syscall_Bdisp_PutDisp_DD(cpu_t* cpu) {
// printf("Run syscall: Bdisp_PutDisp_DD\n");
#ifdef USE_EMSCRIPT
EM_ASM({
window.refreshScreen();
});
#endif
}
/**
* Set or erase a dot at the specified position of VRAM and/or DD (Display Driver).
* @param x (0~127) This is the x coordinate of the specified position.
* @param y (0~63) This is the y coordinate of the specified position.
* @param point If you set point to 1 then the dot is made black. If you set point to 0 then the dot is cleared.
*/
void syscall_Bdisp_SetPoint_VRAM(cpu_t* cpu, uint32_t x, uint32_t y, uint32_t point) {
uint32_t vramID = x/8 + y * 16;
uint8_t bit = 7 - x % 8; // Current bit
cpu->disp->vram[vramID] = (cpu->disp->vram[vramID] & ~(1 << bit)) | (point << bit);
// printf("Run syscall: Bdisp_SetPoint_VRAM (%d, %d, %d)\n", x, y, point);
}
#include "../headers/syscalls/text.h"
// Sets the position of the display cursor
// x: [1-21], y: [1-8]
@ -169,11 +128,11 @@ void syscall_Print(cpu_t* cpu, uint32_t str_ptr) {
if (c == 0x00) break; // Line terminator
// Character x,y on screen (21x7)
int screen_x = cpu->disp->cursor.col;
int screen_y = cpu->disp->cursor.row;
int screen_x = cpu->disp->cursor.col - 1;
int screen_y = cpu->disp->cursor.row - 1;
// Pixel start x,y on screen (128x64)
screen_x = screen_x * CHAR_WIDTH + 1;
screen_y = screen_y * CHAR_HEIGHT;
screen_x = screen_x * CHAR_WIDTH;
screen_y = screen_y * CHAR_HEIGHT - 1;
draw_character(cpu, c, screen_x, screen_y, 0);