- [GUIDE] How to open the main menu from an addin
- 07 Dec 2022 03:46:09 am
- Last edited by dr-carlos on 08 May 2023 02:58:20 am; edited 2 times in total
Have you ever wanted to open the main menu, and let the user return to the exact state they were in just before opening it?
Well, now you can!
Here's the function:
Code:
Running this function should reliably open the main menu and allow you to access other apps, whether or not GetKey to main function return is enabled. If the user does not open a different app, but chooses to re-open the one it was previously in, the function will exit and execution continues.
How I found it:
By reverse-engineering (disassembling) the GetKey, GetKeyWait, and SpecialMatrixcodeProcessing syscalls, I have found the OS' internal method of opening the main menu.
A function which I call 'SaveAndOpenMainMenu' is called, which saves state information such as the VRAM, input mode, and frame colour, among other things, then runs another function (which I dub 'OpenMainMenu') and reloads the saved information. Obviously, OpenMainMenu opens the main menu.
Unfortunately, there is no way to access SaveAndOpenMainMenu or OpenMainMenu directly through syscalls. The closest to this is syscall 0x1e58, which does some currently unknown stuff, and then starts an infinite loop, calling SaveAndOpenMainMenu.
This is not very useful as there are many situations where you want to continue execution after opening the menu (not having it infinitely open). It also seems to crash when run on the calculator - this is probably due to the unknown stuff beforehand.
With all of this in mind, I created a function which looks at the assembly of syscall 0x1e58, finds the pointer to SaveAndOpenMainMenu, and runs the function! This works on both the fx-CG 20 and 50 emulators, as well as my OS 3.60 fx-CG 50 AU physical calculator. The function should work on all OS versions, but I don't have access to OS 1.00/2.00 emulators or physical calculators to test it on.
If you want more details, check out my Planete Casio bible folder. In the Syscalls/ folder, you can see the C equivalent of over 110 syscalls/subroutines, including the ones mentioned above. Documenting these and many others are Disassembly.ods/Disassembly.pdf, a spreadsheet and PDF providing the signature of, and information about, many syscalls and other stuff. For example, if you want to know how the called function works, check out SaveAndOpenMainMenu.c and related files.
If you have any questions, feel free to ask.
Thanks for reading,
dr-carlos.
Well, now you can!
Here's the function:
Code:
void SaveAndOpenMainMenu(void) {
int addr;
// get the address of the syscall table in it
addr = *(unsigned int *)0x8002007C;
if (addr < (int)0x80020070)
return;
if (addr >= (int)0x81000000)
return;
// get the pointer to syscall 1E58 - SwitchToMainMenu
addr += 0x1E58 * 4;
if (addr < (int)0x80020070)
return;
if (addr >= (int)0x81000000)
return;
addr = *(unsigned int *)addr;
if (addr < (int)0x80020070)
return;
if (addr >= (int)0x81000000)
return;
// Now addr has the address of the first operation in %1e58
// Run up to 150 times (300/2). OS 3.60's is 59 instructions, so this should
// be plenty, but will let it stop if nothing is found
for (unsigned short *currentAddr = (unsigned short *)addr;
(unsigned int)currentAddr < ((unsigned int)addr + 300); currentAddr++) {
// MOV.L GetkeyToMainFunctionReturn Flag, r14
if (*(unsigned char *)currentAddr != 0xDE)
continue;
// MOV #3, 2
if (*(currentAddr + 1) != 0xE203)
continue;
// BSR <SaveAndOpenMainMenu>
if ((*(unsigned char *)(currentAddr + 2) & 0xF0) != 0xB0)
continue;
// MOV.B r2, @r14
if (*(currentAddr + 3) != 0x2E20)
continue;
// BRA <some addr>
if ((*(unsigned char *)(currentAddr + 4) & 0xF0) != 0xA0)
continue;
// NOP
if (*(currentAddr + 5) != 0x0009)
continue;
unsigned short branchInstruction = *(currentAddr + 2);
// Clear first 4 bits (BSR identifier)
branchInstruction <<= 4;
branchInstruction >>= 4;
// branchInstruction is now the displacement of BSR
// Create typedef so we can cast the pointer
typedef void (*voidFunc)(void);
// JMP to disp*2 + PC + 4
((voidFunc)((unsigned int)branchInstruction * 2 +
(unsigned int)currentAddr + 4 + 4))();
return;
}
}
Running this function should reliably open the main menu and allow you to access other apps, whether or not GetKey to main function return is enabled. If the user does not open a different app, but chooses to re-open the one it was previously in, the function will exit and execution continues.
How I found it:
By reverse-engineering (disassembling) the GetKey, GetKeyWait, and SpecialMatrixcodeProcessing syscalls, I have found the OS' internal method of opening the main menu.
A function which I call 'SaveAndOpenMainMenu' is called, which saves state information such as the VRAM, input mode, and frame colour, among other things, then runs another function (which I dub 'OpenMainMenu') and reloads the saved information. Obviously, OpenMainMenu opens the main menu.
Unfortunately, there is no way to access SaveAndOpenMainMenu or OpenMainMenu directly through syscalls. The closest to this is syscall 0x1e58, which does some currently unknown stuff, and then starts an infinite loop, calling SaveAndOpenMainMenu.
This is not very useful as there are many situations where you want to continue execution after opening the menu (not having it infinitely open). It also seems to crash when run on the calculator - this is probably due to the unknown stuff beforehand.
With all of this in mind, I created a function which looks at the assembly of syscall 0x1e58, finds the pointer to SaveAndOpenMainMenu, and runs the function! This works on both the fx-CG 20 and 50 emulators, as well as my OS 3.60 fx-CG 50 AU physical calculator. The function should work on all OS versions, but I don't have access to OS 1.00/2.00 emulators or physical calculators to test it on.
If you want more details, check out my Planete Casio bible folder. In the Syscalls/ folder, you can see the C equivalent of over 110 syscalls/subroutines, including the ones mentioned above. Documenting these and many others are Disassembly.ods/Disassembly.pdf, a spreadsheet and PDF providing the signature of, and information about, many syscalls and other stuff. For example, if you want to know how the called function works, check out SaveAndOpenMainMenu.c and related files.
If you have any questions, feel free to ask.
Thanks for reading,
dr-carlos.