Compare commits

...

9 commits

Author SHA1 Message Date
Lephe
ff17b8c22c
kernel: syscall support for Math+ OS v2.00 2025-02-03 23:52:48 +01:00
Lephe
e44e4fa14e
keysc: add MPU module description for KEYSC 2025-02-03 23:52:48 +01:00
Lephe
87fff59527
keysc: fix keycodes mapping to multiple keys on Math+ 2025-02-03 23:52:48 +01:00
Lephe
232a4195d2
cpg: don't overclock beyond known limits on Math+ 2025-02-03 23:52:48 +01:00
Lephe
7ac9668dfd
keydev: add Catalog+4th row combo for F1...F6 on Math+ 2025-02-03 23:52:48 +01:00
Lephe
7a479e4f45
keydev: support for the Math+ layout and track row/col
key_event_t is now 8 bytes instead of 4, a change that was doomed to
happen anyway to deal with touch input (where it's not clear either
whether 8 bytes will be enough for double touch).
2025-02-03 23:52:48 +01:00
Lephe
a62ba8a026
kernel: further support for the Math+ in general
* Add a new HWCALC value HWCALC_FXCG100, detected based on being on an
  Area-3 RAM model and having OS version that's either less than 3 or
  3 and built after January 2025.
* Disable the _ostk heap arena, as the region might simply not exist,
  and improve the VRAM allocation code to account for this better than
  the hardcoded macro previously in place for the fx-CP 400.
* Disable gint_osmenu() which can't work with MPM right now.
* Add BFile_FindFirst() and GetVRAMAddress() syscalls.
2025-02-03 23:52:48 +01:00
Lephe
f953efdc82
kernel: partial support for Math+ OS 1.00 2025-02-03 23:52:47 +01:00
Lephe
1df334110e
kernel: allows syscalls to be called from fixed addresses 2025-02-03 23:52:44 +01:00
15 changed files with 366 additions and 114 deletions

View file

@ -184,6 +184,8 @@ typedef struct {
/* Candidate key for repeats (or 0 if no key is candidate yet) */ /* Candidate key for repeats (or 0 if no key is candidate yet) */
int16_t rep_key; int16_t rep_key;
/* Matrix code for rep_key, if rep_key is not 0. */
uint8_t rep_row, rep_col;
/* Number of repeats already sent */ /* Number of repeats already sent */
int16_t rep_count; int16_t rep_count;
/* Time since key was first pressed (us) */ /* Time since key was first pressed (us) */

View file

@ -111,6 +111,8 @@ void hw_detect(void);
#define HWCALC_FX9860G_SLIM 7 #define HWCALC_FX9860G_SLIM 7
/* fx-CP 400 */ /* fx-CP 400 */
#define HWCALC_FXCP400 8 #define HWCALC_FXCP400 8
/* fx-CG 100, successor to the CG-50 in the Prizm family. Also Graph Math+ */
#define HWCALC_FXCG100 9
/* /*
** Keyboard ** Keyboard

View file

@ -114,16 +114,25 @@ extern "C" {
* 0xffff is "just before" 0x0000, not "long after". */ * 0xffff is "just before" 0x0000, not "long after". */
typedef struct typedef struct
{ {
uint time :16; /* Time of event, unique over short periods */ /* Time of event, unique over short periods */
u16 time;
uint :2; /* Reserved for future use */ uint :2; /* Reserved for future use */
uint mod :1; /* Whether modifiers are used */ uint mod :1; /* Whether modifiers are used */
uint shift :1; /* If mod=1, whether SHIFT was pressed */ uint shift :1; /* If mod=1, whether SHIFT was pressed */
uint alpha :1; /* If mod=1, whether ALPHA was pressed */ uint alpha :1; /* If mod=1, whether ALPHA was pressed */
uint type :3; /* Type of key event */ uint type :3; /* Type of key event */
uint key :8; /* Hit key */
/* Key that was pressed or released. */
u8 key;
// The following attributes will be union'd with touch info on the CP.
/* Matrix code: physical location of the key being it. */
u8 row, col;
/* Reserved for future use. */
uint :16;
} GPACKED(4) key_event_t; } GPACKED(4) key_event_t;

View file

@ -9,7 +9,6 @@
extern "C" { extern "C" {
#endif #endif
/* Raw matrix codes */
enum { enum {
KEY_F1 = 0x91, KEY_F1 = 0x91,
KEY_F2 = 0x92, KEY_F2 = 0x92,
@ -87,7 +86,23 @@ enum {
KEY_EQUALS = 0xa5, KEY_EQUALS = 0xa5,
KEY_CLEAR = KEY_EXIT, KEY_CLEAR = KEY_EXIT,
/* Key aliases (handle with care =D) */ /* Key codes for the CG-100 */
KEY_ON = 0xa6,
KEY_HOME = KEY_MENU,
KEY_PREVTAB = 0xa7,
KEY_NEXTTAB = 0xa8,
KEY_PAGEUP = 0xa9,
KEY_PAGEDOWN = 0xaa,
KEY_SETTINGS = 0xab,
KEY_BACK = KEY_EXIT,
KEY_OK = 0xac,
KEY_CATALOG = 0xad,
KEY_TOOLS = KEY_OPTN,
KEY_FORMAT = KEY_FD,
KEY_SQRT = 0xae,
KEY_EXPFUN = 0xaf,
/* Key aliases (deprecated--no more will be added) */
KEY_X2 = KEY_SQUARE, KEY_X2 = KEY_SQUARE,
KEY_CARET = KEY_POWER, KEY_CARET = KEY_POWER,
KEY_SWITCH = KEY_FD, KEY_SWITCH = KEY_FD,

34
include/gint/mpu/keysc.h Normal file
View file

@ -0,0 +1,34 @@
//---
// gint:mpu:keysc - Key Scan Controller
//---
#ifndef GINT_MPU_KEYSC
#define GINT_MPU_KEYSC
#ifdef __cplusplus
extern "C" {
#endif
#include <gint/defs/attributes.h>
#include <gint/defs/types.h>
typedef volatile struct {
uint16_t KIUDATA[6];
uint16_t KIUCNTREG;
uint16_t KIAUTOFIXREG;
uint16_t KIUMODEREG;
uint16_t KIUSTATEREG;
uint16_t KIUINTREG;
uint16_t KIUWSETREG;
uint16_t KIUINTERVALREG;
uint16_t KOUTPINSET;
uint16_t KINPINSET;
} GPACKED(4) sh7305_keysc_t;
#define SH7305_KEYSC (*(sh7305_keysc_t *)0xa44b0000)
#ifdef __cplusplus
}
#endif
#endif /* GINT_MPU_KEYSC */

View file

@ -433,6 +433,66 @@ static struct cpg_overclock_setting const settings_fxcg50[5] = {
.CS5aWCR = 0x000203C1 }, .CS5aWCR = 0x000203C1 },
}; };
// TODO: These structures are big and many settings overlap. Make it smaller.
// This is fxcg50[0,1,2,3,3].
static struct cpg_overclock_setting const settings_fxcg100[5] = {
/* CLOCK_SPEED_F1 */
{ .FLLFRQ = 0x00004000 + 900,
.FRQCR = 0x0F011112,
.CS0BCR = 0x36DA0400,
.CS2BCR = 0x36DA3400,
.CS3BCR = 0x36DB4400,
.CS5aBCR = 0x17DF0400,
.CS0WCR = 0x000003C0,
.CS2WCR = 0x000003C0,
.CS3WCR = 0x000024D1,
.CS5aWCR = 0x000203C1 },
/* CLOCK_SPEED_F2 */
{ .FLLFRQ = 0x00004000 + 900,
.FRQCR = (SH4_PLL_16x<<24)+(SH4_DIV_4<<20)+(SH4_DIV_8<<12)+(SH4_DIV_8<<8)+SH4_DIV_8,
.CS0BCR = 0x24920400,
.CS2BCR = 0x24923400,
.CS3BCR = 0x24924400,
.CS5aBCR = 0x17DF0400,
.CS0WCR = 0x00000340,
.CS2WCR = 0x000003C0,
.CS3WCR = 0x000024D1,
.CS5aWCR = 0x000203C1 },
/* CLOCK_SPEED_F3 */
{ .FLLFRQ = 0x00004000 + 900,
.FRQCR = (SH4_PLL_26x<<24)+(SH4_DIV_4<<20)+(SH4_DIV_8<<12)+(SH4_DIV_8<<8)+SH4_DIV_8,
.CS0BCR = 0x24920400,
.CS2BCR = 0x24923400,
.CS3BCR = 0x24924400,
.CS5aBCR = 0x17DF0400,
.CS0WCR = 0x00000240,
.CS2WCR = 0x000003C0,
.CS3WCR = 0x000024D1,
.CS5aWCR = 0x000203C1 },
/* CLOCK_SPEED_F4 */
{ .FLLFRQ = 0x00004000 + 900,
.FRQCR = (SH4_PLL_32x<<24)+(SH4_DIV_2<<20)+(SH4_DIV_4<<12)+(SH4_DIV_8<<8)+SH4_DIV_16,
.CS0BCR = 0x24920400,
.CS2BCR = 0x24923400,
.CS3BCR = 0x24924400,
.CS5aBCR = 0x17DF0400,
.CS0WCR = 0x000002C0,
.CS2WCR = 0x000003C0,
.CS3WCR = 0x000024D1,
.CS5aWCR = 0x000203C1 },
/* CLOCK_SPEED_F5 is made identical to CLOCK_SPEED_F4 because clearly the
Graph Math+ cannot handle the higher bus speed. */
{ .FLLFRQ = 0x00004000 + 900,
.FRQCR = (SH4_PLL_32x<<24)+(SH4_DIV_2<<20)+(SH4_DIV_4<<12)+(SH4_DIV_8<<8)+SH4_DIV_16,
.CS0BCR = 0x24920400,
.CS2BCR = 0x24923400,
.CS3BCR = 0x24924400,
.CS5aBCR = 0x17DF0400,
.CS0WCR = 0x000002C0,
.CS2WCR = 0x000003C0,
.CS3WCR = 0x000024D1,
.CS5aWCR = 0x000203C1 },
};
#endif #endif
static struct cpg_overclock_setting const *get_settings(void) static struct cpg_overclock_setting const *get_settings(void)
@ -451,6 +511,8 @@ static struct cpg_overclock_setting const *get_settings(void)
return settings_prizm; return settings_prizm;
if(gint[HWCALC] == HWCALC_FXCG50) if(gint[HWCALC] == HWCALC_FXCG50)
return settings_fxcg50; return settings_fxcg50;
if(gint[HWCALC] == HWCALC_FXCG100)
return settings_fxcg100;
#endif #endif
return NULL; return NULL;

View file

@ -80,6 +80,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(code == 0x1060) name = "Memory init failed"; if(code == 0x1060) name = "Memory init failed";
if(code == 0x1080) name = "Stack overflow"; if(code == 0x1080) name = "Stack overflow";
if(code == 0x10a0) name = "UBC in bank 1 code"; if(code == 0x10a0) name = "UBC in bank 1 code";
// if(code == 0x10c0) name = "Missing syscall"; // not on FX
if(name[0]) dtext(1, 9, name); if(name[0]) dtext(1, 9, name);
else dprint(1, 9, "%03x", code); else dprint(1, 9, "%03x", code);
@ -121,6 +122,7 @@ GNORETURN static void gint_default_panic(GUNUSED uint32_t code)
if(code == 0x1060) name = "Memory initialization failed (heap)"; if(code == 0x1060) name = "Memory initialization failed (heap)";
if(code == 0x1080) name = "Stack overflow during world switch"; if(code == 0x1080) name = "Stack overflow during world switch";
if(code == 0x10a0) name = "UBC break in register bank 1 code"; if(code == 0x10a0) name = "UBC break in register bank 1 code";
if(code == 0x10c0) name = "Missing syscall for this OS version";
dprint(6, 25, "%03x %s", code, name); dprint(6, 25, "%03x %s", code, name);

View file

@ -11,6 +11,7 @@
#include <gint/config.h> #include <gint/config.h>
#include <string.h> #include <string.h>
#include "kernel.h"
/* Holds information about the current platform */ /* Holds information about the current platform */
GBSS uint32_t gint[HW_KEYS]; GBSS uint32_t gint[HW_KEYS];
@ -126,10 +127,28 @@ void hw_detect(void)
gint[HWCPUVR] = PVR; gint[HWCPUVR] = PVR;
gint[HWCPUPR] = PRR; gint[HWCPUPR] = PRR;
/* Tell Prizms apart from fx-CG 50 by checking the stack address*/
uint32_t stack; uint32_t stack;
__asm__("mov r15, %0" : "=r"(stack)); __asm__("mov r15, %0" : "=r"(stack));
gint[HWCALC] = (stack < 0x8c000000) ? HWCALC_PRIZM : HWCALC_FXCG50; char const *version = (void *)0x80020020;
char const *osdate = (void *)0x80b5ffe0;
/* Tell Prizms apart from fx-CG 50 by checking the stack address*/
if(stack < 0x8c000000) {
gint[HWCALC] = HWCALC_PRIZM;
}
/* Tell Math+/fx-CG 100 apart from CG-50 by checking OS version + date.
CG-50 OS versions use OS 3. Math+, for some reason, rewinds back to OS 1
and got updated to OS 2 in late 2024. We decide that we are on a CG-50 OS
if the version is 3 and the date is 201x-2024. */
else {
/* All known CG-50 versions have date at this address due to the footer
location. WARNING: not a future-proof address! */
char d0 = osdate[0], d1 = osdate[1], d2 = osdate[2], d3 = osdate[3];
bool cg50 = version[1] == '3' && d0 == '2' && d1 == '0' &&
(d2 == '1' || (d2 == '2' && d3 <= '4'));
gint[HWCALC] = cg50 ? HWCALC_FXCG50 : HWCALC_FXCG100;
}
gint[HWFS] = HWFS_FUGUE; gint[HWFS] = HWFS_FUGUE;
/* Tell the fx-CG emulator apart using the product ID */ /* Tell the fx-CG emulator apart using the product ID */

View file

@ -40,6 +40,18 @@ void *gint_stack_top = NULL;
/* kinit(): Install and start gint */ /* kinit(): Install and start gint */
void kinit(void) void kinit(void)
{ {
/* Figure out which CASIOWIN API to use based on the OS type. */
#if GINT_OS_CG
char *version = (void *)0x80020020;
if(!memcmp(version, "01.00", 5))
gint_set_CASIOWIN_API(1);
else if(gint[HWCALC] == HWCALC_FXCG100 && !memcmp(version, "02.00", 5))
gint_set_CASIOWIN_API(2);
else
gint_set_CASIOWIN_API(0);
#endif
#if GINT_HW_FX #if GINT_HW_FX
/* On fx-9860G, VBR is loaded at the end of the user RAM. On SH4, the /* 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 end of the user RAM hosts the stack, for which we leave 12 kB
@ -108,16 +120,18 @@ void kinit(void)
/* Create an arena in the OS stack as well, for VRAM and more data */ /* Create an arena in the OS stack as well, for VRAM and more data */
#if GINT_HW_CG && !defined(GINT_NO_OS_STACK) #if GINT_HW_CG && !defined(GINT_NO_OS_STACK)
static kmalloc_arena_t os_stack = { 0 }; if(gint[HWCALC] != HWCALC_FXCG100) {
os_stack.name = "_ostk"; static kmalloc_arena_t os_stack = { 0 };
os_stack.is_default = true; os_stack.name = "_ostk";
if(gint[HWCALC] == HWCALC_PRIZM || gint[HWCALC] == HWCALC_FXCG_MANAGER) os_stack.is_default = true;
os_stack.start = (void *)0x880f0000; if(gint[HWCALC] == HWCALC_PRIZM || gint[HWCALC] == HWCALC_FXCG_MANAGER)
else os_stack.start = (void *)0x880f0000;
os_stack.start = (void *)0x8c0f0000; else
os_stack.end = os_stack.start + (350 * 1024); os_stack.start = (void *)0x8c0f0000;
kmalloc_init_arena(&os_stack, true); os_stack.end = os_stack.start + (350 * 1024);
kmalloc_add_arena(&os_stack); kmalloc_init_arena(&os_stack, true);
kmalloc_add_arena(&os_stack);
}
#endif #endif
/* Allocate world buffers for the OS and for gint */ /* Allocate world buffers for the OS and for gint */

View file

@ -18,4 +18,7 @@ void kinit(void);
/* kquit(): Quit gint and give back control to the system */ /* kquit(): Quit gint and give back control to the system */
void kquit(void); void kquit(void);
/* Select the CASIOWIN API for syscalls. */
void gint_set_CASIOWIN_API(int API);
#endif /* GINT_CORE_KERNEL */ #endif /* GINT_CORE_KERNEL */

View file

@ -13,7 +13,6 @@ int __Timer_Deinstall(int id);
int __PutKeyCode(int row, int column, int keycode); int __PutKeyCode(int row, int column, int keycode);
int __GetKeyWait(int *col,int *row,int type,int time,int menu,uint16_t *key); int __GetKeyWait(int *col,int *row,int type,int time,int menu,uint16_t *key);
void __ClearKeyBuffer(void); /* ? */ void __ClearKeyBuffer(void); /* ? */
void __ConfigureStatusArea(int mode);
void __SetQuitHandler(void (*callback)(void)); void __SetQuitHandler(void (*callback)(void));
#if !GINT_OS_CP #if !GINT_OS_CP
@ -96,15 +95,17 @@ static os_menu_function_t *find_os_menu_function(void)
void gint_osmenu_native(void) void gint_osmenu_native(void)
{ {
#if GINT_OS_CG
if(gint[HWCALC] == HWCALC_FXCG100)
return;
#endif
// TODO: OS menu on fx-CP // TODO: OS menu on fx-CP
#if !GINT_OS_CP #if !GINT_OS_CP
__ClearKeyBuffer(); __ClearKeyBuffer();
gint_copy_vram(); gint_copy_vram();
#if GINT_OS_CG #if GINT_OS_CG
/* Unfortunately ineffective (main menu probably reenables it)
__ConfigureStatusArea(3); */
/* Try to use the internal function directly if we could figure out its /* Try to use the internal function directly if we could figure out its
address by dynamically disassembling */ address by dynamically disassembling */
os_menu_function_t *fun = find_os_menu_function(); os_menu_function_t *fun = find_os_menu_function();
@ -122,11 +123,6 @@ void gint_osmenu_native(void)
} }
#endif #endif
/* Mysteriously crashes when coming back; might be useful another time
instead of GetKeyWait()
int C=0x04, R=0x09;
__SpecialMatrixCodeProcessing(&C, &R); */
__osmenu_id = __Timer_Install(0, __osmenu_handler, 0 /* ms */); __osmenu_id = __Timer_Install(0, __osmenu_handler, 0 /* ms */);
if(__osmenu_id <= 0) return; if(__osmenu_id <= 0) return;
__Timer_Start(__osmenu_id); __Timer_Start(__osmenu_id);

View file

@ -42,8 +42,9 @@ int8_t gint_restart = 0;
/* gint_setrestart(): Set whether to restart the add-in after exiting */ /* gint_setrestart(): Set whether to restart the add-in after exiting */
void gint_setrestart(int restart) void gint_setrestart(int restart)
{ {
/* There is now return-to-menu so no restart on CP */ /* No restart on the machines for which there is no return-to-menu, i.e. on
gint_restart = restart && !GINT_OS_CP; fx-CP and on the fx-CG 100. */
gint_restart = restart && !GINT_OS_CP && gint[HWCALC] != HWCALC_FXCG100;
} }
/* Return value of main() */ /* Return value of main() */

View file

@ -144,82 +144,128 @@ syscall_table:
#endif /* GINT_OS_FX */ #endif /* GINT_OS_FX */
#if GINT_OS_CG #if GINT_OS_CG
#define CASIOWIN_API_VERSIONS 3
.global _gint_set_CASIOWIN_API
.global _gint_get_CASIOWIN_API
/* Dynamic allocation */ /* System for dynamically selecting between the syscall and fixed version of
each function based on the OS version.
@r0: Internal function ID (from table below) */
_CASIOWIN_call:
mov #CASIOWIN_API_VERSIONS, r1
mulu.w r0, r1
mov.l 3f, r0
mov.l @r0, r2
sts macl, r1
add r2, r1
shll2 r1
___malloc: /* API version 0 is the normal syscall table */
syscall(0x1f44) tst r2, r2
___free: mova .CASIOWIN_TABLE, r0
syscall(0x1f42) bt.s .syscall
___realloc: mov.l @(r0, r1), r0
syscall(0x1f46)
/* BFile driver */ /* Other API versions are the direct calls */
tst r0, r0
bt .missingCall
_BFile_Remove: jmp @r0
syscall(0x1db4) nop
_BFile_Rename:
syscall(0x1db3)
_BFile_Create:
syscall(0x1dae)
_BFile_Open:
mov #0, r6
syscall(0x1da3)
_BFile_Close:
syscall(0x1da4)
_BFile_Size:
syscall(0x1da6)
_BFile_Seek:
syscall(0x1da9)
_BFile_GetPos:
syscall(0x1dab)
_BFile_Write:
syscall(0x1daf)
_BFile_Read:
syscall(0x1dac)
_BFile_FindFirst:
syscall(0x1db6)
_BFile_FindNext:
syscall(0x1db8)
_BFile_FindClose:
syscall(0x1dba)
/* Return to menu */ .missingCall:
mov.l .gint_panic, r0
mov.w 2f, r4
jmp @r0
nop
___Timer_Install: .syscall:
syscall(0x8d9) mov.l 1f, r1
___Timer_Start: jmp @r1
syscall(0x8db) nop
___Timer_Stop:
syscall(0x8dc)
___Timer_Deinstall:
syscall(0x8da)
___PutKeyCode:
syscall(0x12c6)
___GetKeyWait:
syscall(0x12bf)
___ClearKeyBuffer:
syscall(0x12c7)
___GetVRAMAddress:
syscall(0x1e6)
___ConfigureStatusArea:
syscall(0x2b7)
___SetQuitHandler:
syscall(0x1e6e)
.global ___SpecialMatrixCodeProcessing 2: .word 0x10c0
___SpecialMatrixCodeProcessing: .balign 4
syscall(0x1e60) 1: .long 0x80020070
.gint_panic:
.long _gint_panic
/* Reset */ _gint_set_CASIOWIN_API:
mov.l 3f, r0
rts
mov.l r4, @r0
___PowerOff: _gint_get_CASIOWIN_API:
syscall(0x1839) mov.l 3f, r0
___Reset: rts
syscall(0x1187) mov.l @r0, r0
syscall_table: .balign 4
.long 0x80020070 3: .long .CASIOWIN_API
.CASIOWIN_TABLE:
.long 0x1f44, 0x8025e0fc, 0x80366708 /* malloc */
.long 0x1f42, 0x8025dec8, 0x803664d4 /* free */
.long 0x1f46, 0x8025ec3c, 0x803672c8 /* realloc */
.long 0x1db4, 0x802404d2, 0x80334212 /* BFile_Remove */
.long 0x1db3, 0x80240482, 0x803341c2 /* BFile_Rename */
.long 0x1dae, 0x802401b0, 0x80333ef0 /* BFile_Create */
.long 0x1da3, 0x8023fb90, 0x803338d0 /* BFile_Open */
.long 0x1da4, 0x8023fd0e, 0x80333a4e /* BFile_Close */
.long 0x1da6, 0x8023fdc4, 0x80333b04 /* BFile_Size */
.long 0x1da9, 0x8023ff2c, 0x80333c6c /* BFile_Seek */
.long 0x1dab, 0x8024003c, 0x80333d7c /* BFile_GetPos */
.long 0x1daf, 0x8024025e, 0x80333f9e /* BFile_Write */
.long 0x1dac, 0x80240082, 0x80333dc2 /* BFile_Read */
.long 0x1db6, 0x80240888, 0x803345c8 /* BFile_FindFirst */
.long 0x1db8, 0x80240b06, 0x80334846 /* BFile_FindNext */
.long 0x1dba, 0x80240c10, 0x80334950 /* BFile_FindClose */
.long 0x08d9, 0x800b130c, 0x8010de28 /* Timer_Install */
.long 0x08db, 0x800b1456, 0x8010df72 /* Timer_Start */
.long 0x08dc, 0x800b14b2, 0x8010dfce /* Timer_Stop */
.long 0x08da, 0x800b13d4, 0x8010def0 /* Timer_Deinstall */
.long 0x12c6, 0, 0 /* PutKeyCode */
.long 0x12bf, 0x8017be56, 0x802382fe /* GetKeyWait */
.long 0x12c7, 0, 0 /* ClearKeyBuffer */
.long 0x01e6, 0x8004579a, 0x8007569e /* GetVRAMAddress */
.long 0x1e6e, 0, 0 /* SetQuitHandler */
.long 0x1839, 0, 0 /* PowerOff */
.long 0x1187, 0, 0 /* Reset */
#define casiowin_call(id) bra _CASIOWIN_call; mov id, r0
___malloc: casiowin_call(#0)
___free: casiowin_call(#1)
___realloc: casiowin_call(#2)
_BFile_Remove: casiowin_call(#3)
_BFile_Rename: casiowin_call(#4)
_BFile_Create: casiowin_call(#5)
_BFile_Open: mov #0, r6; casiowin_call(#6)
_BFile_Close: casiowin_call(#7)
_BFile_Size: casiowin_call(#8)
_BFile_Seek: casiowin_call(#9)
_BFile_GetPos: casiowin_call(#10)
_BFile_Write: casiowin_call(#11)
_BFile_Read: casiowin_call(#12)
_BFile_FindFirst: casiowin_call(#13)
_BFile_FindNext: casiowin_call(#14)
_BFile_FindClose: casiowin_call(#15)
___Timer_Install: casiowin_call(#16)
___Timer_Start: casiowin_call(#17)
___Timer_Stop: casiowin_call(#18)
___Timer_Deinstall: casiowin_call(#19)
___PutKeyCode: casiowin_call(#20)
___GetKeyWait: casiowin_call(#21)
___ClearKeyBuffer: casiowin_call(#22)
___GetVRAMAddress: casiowin_call(#23)
___ConfigureStatusArea: casiowin_call(#24)
___SetQuitHandler: casiowin_call(#25)
___PowerOff: casiowin_call(#26)
___Reset: casiowin_call(#27)
.data
.CASIOWIN_API:
.long 0
#endif /* GINT_OS_CG */ #endif /* GINT_OS_CG */

View file

@ -8,6 +8,7 @@
#include <gint/drivers/keydev.h> #include <gint/drivers/keydev.h>
#include <gint/defs/types.h> #include <gint/defs/types.h>
#include <gint/defs/util.h> #include <gint/defs/util.h>
#include <gint/hardware.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
@ -45,14 +46,49 @@ static void keycode_to_keymatrix(int keycode, int *row, int *col)
*col = 0; *col = 0;
} }
#else #else
static GINLINE int keymatrix_to_keycode(int row, int col) static uint8_t const CG100_keymap[] = {
KEY_ON, KEY_HOME, KEY_PREVTAB, KEY_UP, KEY_NEXTTAB, KEY_PAGEUP,
KEY_SETTINGS, KEY_BACK, KEY_LEFT, KEY_OK, KEY_RIGHT, KEY_PAGEDOWN,
KEY_SHIFT, KEY_ALPHA, KEY_VARS, KEY_DOWN, KEY_CATALOG, KEY_TOOLS,
KEY_XOT, KEY_FRAC, KEY_SQRT, KEY_POWER, KEY_SQUARE, KEY_EXPFUN,
KEY_COMMA, KEY_SIN, KEY_COS, KEY_TAN, KEY_LEFTP, KEY_RIGHTP,
};
static int keymatrix_to_keycode(int row, int col)
{ {
if(gint[HWCALC] == HWCALC_FXCG100) {
if(row >= 7 && row <= 9)
return CG100_keymap[6 * (9-row) + (6-col)];
if(row == 1 && col == 3)
return KEY_FORMAT;
}
return (row << 4) + (7 - col); return (row << 4) + (7 - col);
} }
static GINLINE void keycode_to_keymatrix(int keycode, int *row, int *col) static void keycode_to_keymatrix(int keycode, int *row, int *col)
{ {
if(gint[HWCALC] == HWCALC_FXCG100) {
if(keycode == KEY_FORMAT) {
*row = 1;
*col = 3;
return;
}
for(int i = 0; i < (int)sizeof(CG100_keymap); i++) {
if(CG100_keymap[i] == keycode) {
*row = 9 - i / 6;
*col = 6 - (i % 6);
return;
}
}
}
*row = keycode >> 4; *row = keycode >> 4;
*col = 7 - (keycode & 7); *col = 7 - (keycode & 7);
if(gint[HWCALC] == HWCALC_FXCG100 &&
(*row > 4 || (*row == 1 && *col == 3))) {
// key that doesn't exist
*row = 0;
*col = 1;
}
} }
#endif #endif
@ -125,6 +161,8 @@ void keydev_process_state(keydev_t *d, uint8_t scan[12])
for(int mask = 0x80, col = 7; mask; mask >>= 1, col--) for(int mask = 0x80, col = 7; mask; mask >>= 1, col--)
{ {
ev.row = row;
ev.col = col;
ev.key = keymatrix_to_keycode(row, col); ev.key = keymatrix_to_keycode(row, col);
/* Update state only if the push succeeds */ /* Update state only if the push succeeds */
if((diff & mask) && keydev_queue_push(d, ev)) if((diff & mask) && keydev_queue_push(d, ev))
@ -173,6 +211,8 @@ key_event_t keydev_repeat_event(keydev_t *d)
ev.type = KEYEV_HOLD; ev.type = KEYEV_HOLD;
ev.key = d->rep_key; ev.key = d->rep_key;
ev.row = d->rep_row;
ev.col = d->rep_col;
return ev; return ev;
} }
@ -188,11 +228,11 @@ void keydev_tick(keydev_t *d, uint us)
/* Disable repeat if the repeating key was released */ /* Disable repeat if the repeating key was released */
if(d->rep_key != 0) if(d->rep_key != 0)
{ {
int row, col; if(!(d->state_now[d->rep_row] & (1 << d->rep_col)))
keycode_to_keymatrix(d->rep_key, &row, &col);
if(!(d->state_now[row] & (1 << col)))
{ {
d->rep_key = 0; d->rep_key = 0;
d->rep_row = 0;
d->rep_col = 0;
d->rep_count = -1; d->rep_count = -1;
d->rep_time = -1; d->rep_time = -1;
d->rep_delay = -1; d->rep_delay = -1;
@ -231,19 +271,27 @@ key_event_t keydev_unqueue_event(keydev_t *d)
if(!queue_poll(d, &ev)) if(!queue_poll(d, &ev))
return ev; return ev;
/* Compatibility combinations can transform the .key attribute */
#if GINT_HW_CG
if(gint[HWCALC] == HWCALC_FXCG100) {
if(keydev_keydown(d, KEY_CATALOG) && ev.row == 6)
ev.key = KEY_F1 + (6 - ev.col);
}
#endif
/* Update the event state accordingly */ /* Update the event state accordingly */
int row, col; int mask = 1 << ev.col;
keycode_to_keymatrix(ev.key, &row, &col);
int mask = 1 << col;
if(ev.type == KEYEV_DOWN) if(ev.type == KEYEV_DOWN)
{ {
d->state_queue[row] |= mask; d->state_queue[ev.row] |= mask;
d->state_flips[row] ^= mask; d->state_flips[ev.row] ^= mask;
/* Mark this key as the currently repeating one */ /* Mark this key as the currently repeating one */
if(d->rep_key == 0 && can_repeat(d, ev.key)) if(d->rep_key == 0 && can_repeat(d, ev.key))
{ {
d->rep_key = ev.key; d->rep_key = ev.key;
d->rep_row = ev.row;
d->rep_col = ev.col;
d->rep_count = -1; d->rep_count = -1;
d->rep_time = 0; d->rep_time = 0;
d->rep_delay = 0; d->rep_delay = 0;
@ -251,8 +299,8 @@ key_event_t keydev_unqueue_event(keydev_t *d)
} }
else if(ev.type == KEYEV_UP) else if(ev.type == KEYEV_UP)
{ {
d->state_queue[row] &= ~mask; d->state_queue[ev.row] &= ~mask;
d->state_flips[row] ^= mask; d->state_flips[ev.row] ^= mask;
} }
return ev; return ev;

View file

@ -97,16 +97,15 @@ bool dvram_init(void)
{ {
int const MARGIN = 32; int const MARGIN = 32;
char const *arena = NULL;
if(kmalloc_get_arena("_ostk"))
arena = "_ostk";
/* Leave MARGIN bytes on each side of the region; this enables some /* Leave MARGIN bytes on each side of the region; this enables some
important optimizations in the image renderer. We also add another important optimizations in the image renderer. We also add another
32 bytes so we can manually 32-align the region */ 32 bytes so we can manually 32-align the region */
uint32_t region = (uint32_t)kmalloc(DWIDTH*DHEIGHT*2 + MARGIN*2 + 32, uint32_t region =
#if !defined(GINT_NO_OS_STACK) (uint32_t)kmalloc(DWIDTH*DHEIGHT*2 + MARGIN*2 + 32, arena);
"_ostk"
#else
NULL
#endif
);
if(region == 0) if(region == 0)
return false; return false;