From 4cb155570833c71f6c1d685f909083dc2d541691 Mon Sep 17 00:00:00 2001 From: Lephe Date: Mon, 20 Jul 2020 20:37:34 +0200 Subject: [PATCH] kernel: add an add-in restart mechanism using gint_osmenu() This new mechanism allows an add-in to be restarted after exiting by just never exiting in the first place, calling gint_osmenu() instead. This makes sure that we can relaunch the add-in immediately, which is normally possible through an option in the OS though no OS-independent method of setting it is currently known. Because this is gint_osmenu(), known pitfalls apply. On all platforms, it is necessary to prepare the first frame before leaving. On fx-CG 50, the inevitable display border is also there. --- TODO | 1 - include/gint/gint.h | 12 ++++++++++++ src/core/start.c | 26 +++++++++++++++++++++----- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/TODO b/TODO index e4f9be6..bb3dff0 100644 --- a/TODO +++ b/TODO @@ -13,7 +13,6 @@ Extensions on existing code: * core: review forgotten globals and MPU addresses not in * build: make the build system simpler (two targets are enough by default) * core: run destructors when a task-switch results in leaving the app -* core: invoke main menu instead of returning after main() ends * core rtc: use qdiv10 to massively improve division performance * topti: let the font specify letter and word spacing diff --git a/include/gint/gint.h b/include/gint/gint.h index 8046b6e..65907e0 100644 --- a/include/gint/gint.h +++ b/include/gint/gint.h @@ -43,6 +43,18 @@ void gint_switch(void (*function)(void)); call to getkey(), but can also be called manually. */ void gint_osmenu(void); +/* gint_setrestart(): Set whether to restart the add-in after exiting + + An add-in that reaches the end of its code exits. On the calculator, except + using OS-dependent settings, it cannot be started again unless another + application is launched first. + + This setting allows the add-in to restart by calling gint_osmenu() instead + of exiting. This can give a proper illusion of restarting if used correctly. + + @restart 0 to exit, 1 to restart by using gint_osmenu() */ +void gint_setrestart(int restart); + /* gint_inthandler(): Install interrupt handlers This function installs (copies) interrupt handlers in the VBR space of the diff --git a/src/core/start.c b/src/core/start.c index 19cc2e7..344d9d1 100644 --- a/src/core/start.c +++ b/src/core/start.c @@ -36,6 +36,15 @@ extern void (*bdtors)(void), (*edtors)(void); /* User-provided main() function */ int main(int isappli, int optnum); +/* Whether to restart main through the OS menu rather than returning */ +int gint_restart = 0; + +/* gint_setrestart(): Set whether to restart the add-in after exiting */ +void gint_setrestart(int restart) +{ + gint_restart = restart; +} + /* regcpy(): Copy a memory region using symbol information @l Source pointer (load address) @s Size of area (should be a multiple of 16) @@ -77,8 +86,9 @@ static void callarray(void (**f)(void), void (**l)(void)) while(f < l) (*(*f++))(); } -/* start() - this is where it all starts - Returns a status code. Invoking main menu is better than returning! */ +/* start(): Where it all starts + Returns a status code. Invoking main menu is better than returning, see + gint_setrestart() for that. */ GSECTION(".text.entry") int start(int isappli, int optnum) { @@ -126,7 +136,15 @@ int start(int isappli, int optnum) destructors to work with. */ callarray(&bctors, &ectors); - int ret = main(isappli, optnum); + + int ret; + while(1) + { + ret = main(isappli, optnum); + if(!gint_restart) break; + gint_osmenu(); + } + callarray(&bdtors, &edtors); /* Before leaving the application, we need to clean everything we @@ -137,7 +155,5 @@ int start(int isappli, int optnum) /* Unload gint and give back control to the system. Driver settings will be restored while interrupts are disabled */ kquit(); - - /* TODO: Invoke main menu so that add-in can restart? */ return ret; }