From 3a42b5d386ad83ef09bb801fdb5cb5b205704164 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sat, 23 Mar 2024 23:57:23 +0100 Subject: [PATCH] gint: switch away from FX9860G/FXCG50 macros Not changing much for now, just distilling them into hardware/OS/render macros. Later on the rendering stuff will become more dynamic and down the line I want to unify the APIs more. --- TODO | 31 ++++++++++++++++++++++++++++++- fxcg50.ld.c | 5 +++++ include/gint/config.h.in | 3 +++ include/gint/hardware.h | 24 ++++++++++-------------- include/gint/keyboard.h | 3 +-- include/gint/usb-ff-bulk.h | 3 ++- src/cpg/cpg.c | 7 ++++--- src/cpg/overclock.c | 16 ++++++++-------- src/kernel/exch.c | 5 +++-- src/kernel/hardware.c | 11 ++++++----- src/kernel/inth.S | 5 +++-- src/kernel/kernel.c | 11 ++++++----- src/kernel/osmenu.c | 4 ++-- src/kernel/start.c | 13 ++++--------- src/kernel/syscalls.S | 10 ++++++---- src/kernel/tlbh.S | 30 ++++++++++++++---------------- src/keysc/getkey.c | 6 ++---- src/keysc/iokbd.c | 5 +++-- src/mmu/mmu.c | 2 +- src/usb/setup.c | 24 +++++++++--------------- 20 files changed, 122 insertions(+), 96 deletions(-) diff --git a/TODO b/TODO index 501e373..269ba4b 100644 --- a/TODO +++ b/TODO @@ -3,7 +3,7 @@ Bugs to fix: Extensions on existing code: * clock: mono support -* usb: add PC->calc reading, and interrupt pipes +* usb: and interrupt pipes * fs: support RAM files * fs: support USB streams as generic file descriptors * fugue: support glob() to abstract away BFile entirely @@ -24,3 +24,32 @@ Future directions: * Serial communication * Make fx9860g projects work out of the box on fxcg50 * Base for Yatis' threads library + +TODO: +* SPLIT CONFIG HEADER IN VARIANTS SO THEY DON'T CLASH WHEN INSTALLED + +Bits that need to abstract out into APIs: +- display: Toggle backlight (or set level) + -> Have a backlight property with min/max values + @ getkey + @ justui jscene +- os: OS interface to access OS info, like in fxos + @ usb/setup.c set_strings + @ usb/classes/ff-bulk.c identify command +- render: current video mode + @ usb/classes/ff-bulk.c capture_vram +- gray: make gray engine a subset of t6k11 which then supports two modes + +Video formats: +- i1msb +- 2i1msb +- rgb565 + +T6K11: + mode 0 : i1msb 128x64 @64 Hz + mode 1 : 2i1msb 128x64 @64 Hz +R61524: + mode 0 : rgb565 396x224 @? Hz + mode 1 : i3??? 396x224 @? Hz + mode 2 : i1msb 128x64 @? Hz # <- for g1a emulation :) + mode 3 : 2i1msb 128x64 @? Hz # <- for g1a emulation :) diff --git a/fxcg50.ld.c b/fxcg50.ld.c index d62819a..d6d2753 100644 --- a/fxcg50.ld.c +++ b/fxcg50.ld.c @@ -161,6 +161,11 @@ SECTIONS _silram = SIZEOF(.ilram); _sxyram = SIZEOF(.xyram); + _lgmapped = ABSOLUTE(0); + _sgmapped = ABSOLUTE(0); + _lreloc = ABSOLUTE(0); + _sreloc = ABSOLUTE(0); + /* gint's uninitialized BSS section, going to static RAM. All the large data arrays will be located here */ .gint.bss (NOLOAD) : { diff --git a/include/gint/config.h.in b/include/gint/config.h.in index d43c7f3..00fc5be 100644 --- a/include/gint/config.h.in +++ b/include/gint/config.h.in @@ -18,9 +18,11 @@ #if defined(FX9860G) # define GINT_HW_FX 1 # define GINT_HW_CG 0 +# define GINT_HW_SWITCH(FX,CG) (FX) #elif defined(FXCG50) # define GINT_HW_FX 0 # define GINT_HW_CG 1 +# define GINT_HW_SWITCH(FX,CG) (CG) #endif /* Shorthand to simplify definitions below. Won't be needed for long. */ @@ -34,6 +36,7 @@ see no reason this would be different from hardware, but who knows. */ #define GINT_OS_FX GINT_HW_FX #define GINT_OS_CG GINT_HW_CG +#define GINT_OS_SWITCH GINT_HW_SWITCH /* GINT_NO_OS_STACK: Disables using a chunk of the OS stack as a heap. The top section covering 355/512 ko is otherwise used. (fx-CG 50) */ diff --git a/include/gint/hardware.h b/include/gint/hardware.h index 06924fd..f2e2545 100644 --- a/include/gint/hardware.h +++ b/include/gint/hardware.h @@ -18,6 +18,8 @@ extern "C" { #endif +#include + /* For compatibility with ASM, include the following bits only in C code */ #ifndef CPP_ASM @@ -40,20 +42,14 @@ void hw_detect(void); dual-platform version for libraries. Warning: this macro is also used hardcoded in exch.s. */ -#if defined(FX9860G) || (!defined(FX9860G) && !defined(FXCG50)) -#define isSH3() (gint[HWMPU] & 1) -#define isSH4() (!isSH3()) -#endif - -#if defined(FX9860G) -#define isSlim() (gint[HWCALC] == HWCALC_FX9860G_SLIM) -#else -#define isSlim() 0 -#endif - -#ifdef FXCG50 -#define isSH3() 0 -#define isSH4() 1 +#if GINT_HW_FX +# define isSH3() (gint[HWMPU] & 1) +# define isSH4() (!isSH3()) +# define isSlim() (gint[HWCALC] == HWCALC_FX9860G_SLIM) +#elif GINT_HW_CG +# define isSH3() 0 +# define isSH4() 1 +# define isSlim() 0 #endif /* This bit should be set in all data longwords except HWMPU, HWCPUVR, HWCPUPR diff --git a/include/gint/keyboard.h b/include/gint/keyboard.h index 73fb87d..4bf8b3f 100644 --- a/include/gint/keyboard.h +++ b/include/gint/keyboard.h @@ -253,8 +253,7 @@ enum { GETKEY_REP_PROFILE = 0x0040, /* Enable application shortcuts; see getkey_set_feature_function() */ GETKEY_FEATURES = 0x0080, - /* After coming back from the main menu, redraw the screen with dupdate - (has an effect on fx-CG 50 only) */ + /* After coming back from the main menu, redraw the screen with dupdate */ GETKEY_MENU_DUPDATE = 0x0100, /* After coming back from the main menu, send a KEYEV_OSMENU event */ GETKEY_MENU_EVENT = 0x0200, diff --git a/include/gint/usb-ff-bulk.h b/include/gint/usb-ff-bulk.h index 2d962b5..ddd823b 100644 --- a/include/gint/usb-ff-bulk.h +++ b/include/gint/usb-ff-bulk.h @@ -32,6 +32,7 @@ extern "C" { #endif #include +#include struct usb_fxlink_header; /* This bulk transfer interface with class code 0xff/0x77 implements a simple @@ -74,7 +75,7 @@ void usb_fxlink_screenshot(bool onscreen); automatically send new frames to fxlink. */ void usb_fxlink_videocapture(bool onscreen); -#ifdef FX9860G +#if GINT_RENDER_MONO /* Similar to usb_fxlink_screenshot(), but takes a gray screenshot if the gray engine is currently running. */ void usb_fxlink_screenshot_gray(bool onscreen); diff --git a/src/cpg/cpg.c b/src/cpg/cpg.c index ecaa134..ae230b4 100644 --- a/src/cpg/cpg.c +++ b/src/cpg/cpg.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,7 @@ const clock_frequency_t *clock_freq(void) // SH7705 Clock signals //--- -#if defined(FX9860G) || (!defined(FX9860G) && !defined(FXCG50)) +#if GINT_HW_FX void sh7705_probe(void) { @@ -57,7 +58,7 @@ void sh7705_probe(void) freq.Pphi_f = (ckio * pll1) / freq.Pphi_div; } -#endif /* FX9860G and platform-agnostic */ +#endif //--- // SH7305 clock signals @@ -111,7 +112,7 @@ void cpg_compute_freq(void) { /* This avoids warnings about sh7705_probe() being undefined when building for fxcg50 */ - #if defined(FX9860G) || (!defined(FX9860G) && !defined(FXCG50)) + #if GINT_HW_FX isSH3() ? sh7705_probe() : #endif sh7305_probe(); diff --git a/src/cpg/overclock.c b/src/cpg/overclock.c index a9fa138..7f95c41 100644 --- a/src/cpg/overclock.c +++ b/src/cpg/overclock.c @@ -141,7 +141,7 @@ void cpg_set_overclock_setting(struct cpg_overclock_setting const *s) cpu_atomic_end(); } -#ifdef FX9860G +#if GINT_HW_FX static struct cpg_overclock_setting const settings_fx9860g_sh3[5] = { /* CLOCK_SPEED_F1 */ @@ -312,9 +312,9 @@ static struct cpg_overclock_setting const settings_g35pe2[5] = { .CS5aWCR = 0x00031B40 }, }; -#endif /* FX9860G */ +#endif -#ifdef FXCG50 +#if GINT_HW_CG static struct cpg_overclock_setting const settings_prizm[5] = { /* CLOCK_SPEED_F1 */ @@ -432,25 +432,25 @@ static struct cpg_overclock_setting const settings_fxcg50[5] = { .CS5aWCR = 0x000203C1 }, }; -#endif /* FXCG50 */ +#endif static struct cpg_overclock_setting const *get_settings(void) { -#ifdef FX9860G +#if GINT_HW_FX if(gint[HWCALC] == HWCALC_FX9860G_SH3) return settings_fx9860g_sh3; if(gint[HWCALC] == HWCALC_FX9860G_SH4) return settings_fx9860g_sh4; if(gint[HWCALC] == HWCALC_G35PE2) return settings_g35pe2; -#endif /* FX9860G */ +#endif -#ifdef FXCG50 +#if GINT_HW_CG if(gint[HWCALC] == HWCALC_PRIZM) return settings_prizm; if(gint[HWCALC] == HWCALC_FXCG50) return settings_fxcg50; -#endif /* FXCG50 */ +#endif return NULL; } diff --git a/src/kernel/exch.c b/src/kernel/exch.c index 1efcfbc..e06aa5d 100644 --- a/src/kernel/exch.c +++ b/src/kernel/exch.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -59,7 +60,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code) dfont(NULL); - #ifdef FX9860G + #if GINT_RENDER_MONO memset(gint_vram, 0, 1024); dtext(1, 0, "Exception! (SysERROR)"); for(int i = 0; i < 32; i++) gint_vram[i] = ~gint_vram[i]; @@ -96,7 +97,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code) } #endif - #ifdef FXCG50 + #if GINT_RENDER_RGB /* Don't require the DMA driver just for a clear */ memset(gint_vram, 0xff, DWIDTH*DHEIGHT*2); dtext(6, 3, "An exception occured! (System ERROR)"); diff --git a/src/kernel/hardware.c b/src/kernel/hardware.c index f94fcaa..5b4f834 100644 --- a/src/kernel/hardware.c +++ b/src/kernel/hardware.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -19,7 +20,7 @@ GBSS uint32_t gint[HW_KEYS]; /* Product Register */ #define PRR (*((volatile uint32_t *)0xff000044)) -#if defined(FX9860G) || (!defined(FX9860G) && !defined(FXCG50)) +#if GINT_HW_FX /* mpu_detect() - detect the underlying MPU Many thanks to Simon Lothar for relevant documentation. @@ -116,9 +117,7 @@ void hw_detect(void) else utlb_mapped_memory(NULL, NULL); } -#endif /* FX9860G and platform-agnostic */ - -#ifdef FXCG50 +#elif GINT_HW_CG /* hw_detect(): Basic hardware detection */ void hw_detect(void) @@ -146,4 +145,6 @@ void hw_detect(void) utlb_mapped_memory(NULL, NULL); } -#endif /* FXCG50 */ +#else +#error unknown hardware type for hw_detect +#endif diff --git a/src/kernel/inth.S b/src/kernel/inth.S index 4823cd7..d158ffb 100644 --- a/src/kernel/inth.S +++ b/src/kernel/inth.S @@ -7,10 +7,11 @@ #define CPP_ASM #include +#include .global _gint_inth_7305 -#ifdef FX9860G +#if GINT_HW_FX .global _gint_inth_7705 #endif @@ -100,7 +101,7 @@ _gint_inth_7305: 1: .long 0xff000028 .first_entry: -#ifdef FX9860G +#if GINT_HW_FX /* SH7705-TYPE INTERRUPT HANDLER ENTRY - 56 BYTES */ diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 33a3176..feed797 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -42,7 +42,7 @@ void kinit(void) { uint32_t VBR = 0; - #ifdef FX9860G + #if GINT_HW_FX /* On fx-9860G, VBR is loaded at the end of the user RAM. On SH4, the end of the user RAM hosts the stack, for which we leave 12 kB (0x3000 bytes). The VBR space takes about 0x600 bytes on SH3 due to @@ -60,9 +60,9 @@ void kinit(void) /* VBR is advanced 0x100 bytes because of an unused gap */ uram_end -= (isSH3() ? 0x600 : 0x1100); VBR = uram_end - 0x100; - #endif /* FX9860G */ + #endif - #ifdef FXCG50 + #if GINT_HW_CG /* On fx-CG 50, VBR is loaded at the start of the user RAM; the linker script leaves 5 kB (0x1400 bytes) before the start of the data segment. The stack is again placed at the end of the region, and we @@ -96,7 +96,7 @@ void kinit(void) kmalloc_add_arena(&static_ram); /* Create an arena in the OS stack as well, for VRAM and more data */ - #if defined(FXCG50) && !defined(GINT_NO_OS_STACK) + #if GINT_HW_CG && !defined(GINT_NO_OS_STACK) static kmalloc_arena_t os_stack = { 0 }; os_stack.name = "_ostk"; os_stack.is_default = true; @@ -107,13 +107,14 @@ void kinit(void) os_stack.end = os_stack.start + (350 * 1024); kmalloc_init_arena(&os_stack, true); kmalloc_add_arena(&os_stack); - #endif /* FXCG50 && !GINT_NO_OS_STACK */ + #endif /* Allocate world buffers for the OS and for gint */ gint_world_os = gint_world_alloc(); gint_world_addin = gint_world_alloc(); gint_driver_flags = malloc(gint_driver_count()); + /* Allocate VRAMs, which is important for panic screens */ extern bool dvram_init(void); if(!dvram_init()) abort(); diff --git a/src/kernel/osmenu.c b/src/kernel/osmenu.c index a98a721..55a5472 100644 --- a/src/kernel/osmenu.c +++ b/src/kernel/osmenu.c @@ -29,7 +29,7 @@ static void __osmenu_handler(void) __Timer_Deinstall(__osmenu_id); } -#ifdef FXCG50 +#if GINT_OS_CG typedef void (os_menu_function_t)(void); /* This method is possible thanks to reverse-engineering by Dr-Carlos. @@ -97,7 +97,7 @@ void gint_osmenu_native(void) __ClearKeyBuffer(); gint_copy_vram(); - #ifdef FXCG50 + #if GINT_OS_CG /* Unfortunately ineffective (main menu probably reenables it) __ConfigureStatusArea(3); */ diff --git a/src/kernel/start.c b/src/kernel/start.c index 4421cc8..ca33608 100644 --- a/src/kernel/start.c +++ b/src/kernel/start.c @@ -25,12 +25,9 @@ extern uint32_t ldata, sdata, rdata, /* User's data section */ lilram, silram, rilram, /* IL memory section */ lxyram, sxyram, rxyram, /* X and Y memory section */ - sbss, rbss; /* User's BSS section */ -#ifdef FX9860G -extern uint32_t + sbss, rbss, /* User's BSS section */ lgmapped, sgmapped, /* Permanently mapped functions */ lreloc, sreloc; /* Relocatable references */ -#endif /* Constructor and destructor arrays */ extern void (*bctors)(void), (*ectors)(void); @@ -136,7 +133,7 @@ static int start2(int isappli, int optnum) 1.00 and the fx-9860G emulator) is not clear yet, so gint can't load pages dynamically. Load everything preventively (works only if the add-in is small enough) */ - #ifdef FX9860G + #if GINT_OS_FX if(isSH3()) { /* Try to map every ROM address up to _srom */ @@ -159,9 +156,8 @@ static int start2(int isappli, int optnum) gint_load_onchip_sections(); - #ifdef FX9860G - /* Copy permanently-mapped code to start of user RAM (on fx-CG 50 it - is loaded along ILRAM contents) */ + /* Copy permanently-mapped code to start of user RAM (this section is + only used on fx-9860G; on fx-CG 50 it's fixed in ILRAM) */ void *rgmapped = mmu_uram(); regcpy(&lgmapped, &sgmapped, rgmapped); @@ -171,7 +167,6 @@ static int start2(int isappli, int optnum) { fixups[i] += (uint32_t)rgmapped; } - #endif /* Install gint, switch VBR and initialize drivers */ kinit(); diff --git a/src/kernel/syscalls.S b/src/kernel/syscalls.S index cb7a58d..7f43a88 100644 --- a/src/kernel/syscalls.S +++ b/src/kernel/syscalls.S @@ -9,6 +9,8 @@ ** * File system, because it's a mess and we might ruin the ROM. */ +#include + .text /* Dynamic allocation */ @@ -58,7 +60,7 @@ #define syscall(id) syscall_(id, syscall_table) -#ifdef FX9860G +#if GINT_OS_FX /* Dynamic allocation */ @@ -129,9 +131,9 @@ ___Reset: syscall_table: .long 0x80010070 -#endif /* FX9860G */ +#endif /* GINT_OS_FX */ -#ifdef FXCG50 +#if GINT_OS_CG /* Dynamic allocation */ @@ -209,4 +211,4 @@ ___Reset: syscall_table: .long 0x80020070 -#endif /* FXCG50 */ +#endif /* GINT_OS_CG */ diff --git a/src/kernel/tlbh.S b/src/kernel/tlbh.S index ff51acd..71c022b 100644 --- a/src/kernel/tlbh.S +++ b/src/kernel/tlbh.S @@ -1,7 +1,19 @@ +#include + .global _gint_tlbh .section .gint.tlbh, "ax" .align 4 +#if GINT_OS_FX +# define SYSCALL_TABLE 0x80010070 +# define SYSCALL_TLBH 3 +#elif GINT_OS_CG +# define SYSCALL_TABLE 0x80020070 +# define SYSCALL_TLBH 12 +#else +# error Unknown HW for tlbh.S! +#endif + _gint_tlbh: sts.l pr, @-r15 stc.l gbr, @-r15 @@ -28,16 +40,9 @@ test_tea: map: /* If TEA is mappable, map a page and return */ - #ifdef FX9860G - mov #3, r0 - #endif - #ifdef FXCG50 - mov #12, r0 - #endif - mov.l .syscall, r2 jsr @r2 - nop + mov #SYSCALL_TLBH, r0 lds.l @r15+, macl lds.l @r15+, mach @@ -73,12 +78,5 @@ panic: .long 0x00300000 .max_mapped_rom: .long 0x00300000 + _srom - -#ifdef FX9860G .syscall: - .long 0x80010070 -#endif -#ifdef FXCG50 -.syscall: - .long 0x80020070 -#endif + .long SYSCALL_TABLE diff --git a/src/keysc/getkey.c b/src/keysc/getkey.c index 0aa16fd..118e3b6 100644 --- a/src/keysc/getkey.c +++ b/src/keysc/getkey.c @@ -8,7 +8,7 @@ #include #include -#ifdef FX9860G +#if GINT_HW_FX #include #endif @@ -49,7 +49,7 @@ key_event_t getkey_opt(int opt, volatile int *timeout) continue; } - #ifdef FX9860G + #if GINT_HW_FX /* Backlight toggle */ if((opt & GETKEY_BACKLIGHT) && e.type == KEYEV_DOWN && ((e.key == KEY_LIGHT) || @@ -65,10 +65,8 @@ key_event_t getkey_opt(int opt, volatile int *timeout) e.key == KEY_MENU && !e.shift && !e.alpha) { gint_osmenu(); - #ifdef FXCG50 if(opt & GETKEY_MENU_DUPDATE) dupdate(); - #endif if(!(opt & GETKEY_MENU_EVENT)) continue; diff --git a/src/keysc/iokbd.c b/src/keysc/iokbd.c index 09a70f2..76e0426 100644 --- a/src/keysc/iokbd.c +++ b/src/keysc/iokbd.c @@ -5,9 +5,10 @@ #include #include #include +#include /* This file is SH7705-only. */ -#ifdef FX9860G +#if GINT_HW_FX #define PFC SH7705_PFC /* iokbd_delay() - wait a bit so that I/O can keep up @@ -162,4 +163,4 @@ void iokbd_scan(uint8_t *scan) } } -#endif /* FX9860G */ +#endif /* GINT_HW_FX */ diff --git a/src/mmu/mmu.c b/src/mmu/mmu.c index ff12ce0..baaffbb 100644 --- a/src/mmu/mmu.c +++ b/src/mmu/mmu.c @@ -57,7 +57,7 @@ bool mmu_is_rom(void const *ptr) // SH7705 TLB //--- -#ifdef FX9860G +#if GINT_HW_FX /* tlb_addr() - get the P4 address of a TLB address entry */ GINLINE const tlb_addr_t *tlb_addr(uint way, uint E) diff --git a/src/usb/setup.c b/src/usb/setup.c index 95184dd..55d9e42 100644 --- a/src/usb/setup.c +++ b/src/usb/setup.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -14,11 +15,12 @@ // SETUP requests //--- -#ifdef FX9860G -#define ID_PRODUCT 0x6101 /* fx-9860G II, Protocol 7.00, etc. */ -#else -#define ID_PRODUCT 0x6102 /* fx-CP 400, fx-CG 50, Mass Storage, etc. */ -#endif +/* 0x6101: fx-9860G II, Protocol 7.00, etc. + 0x6102: fx-CP 400, fx-CG 50, Mass Storage, etc. */ +#define ID_PRODUCT GINT_HW_SWITCH(0x6101, 0x6102) +#define DESC_PRODUCT GINT_HW_SWITCH( \ + u"CASIO fx-9860G family on gint", \ + u"CASIO fx-CG family on gint") static usb_dc_device_t dc_device = { .bLength = sizeof(usb_dc_device_t), @@ -54,22 +56,14 @@ static usb_dc_string_t dc_string0 = { GCONSTRUCTOR static void set_strings(void) { - #ifdef FX9860G - char const *serial_base = (void *)0x8000ffd0; - uint16_t const *product = u"CASIO fx-9860G family on gint"; - #endif - - #ifdef FXCG50 - char const *serial_base = (void *)0x8001ffd0; - uint16_t const *product = u"CASIO fx-CG 50 family on gint"; - #endif + char const *serial_base = (void *)GINT_OS_SWITCH(0x8000ffd0, 0x8001ffd0); /* Convert the serial number to UTF-16 */ uint16_t serial[8]; for(int i = 0; i < 8; i++) serial[i] = serial_base[i]; dc_device.iManufacturer = usb_dc_string(u"CASIO Computer Co., Ltd", 0); - dc_device.iProduct = usb_dc_string(product, 0); + dc_device.iProduct = usb_dc_string(DESC_PRODUCT, 0); dc_device.iSerialNumber = usb_dc_string(serial, 8); }