diff --git a/include/gint/gint.h b/include/gint/gint.h index 14dad5f..6925175 100644 --- a/include/gint/gint.h +++ b/include/gint/gint.h @@ -59,14 +59,23 @@ void gint_world_sync(void); call to getkey(), but can also be called manually. */ void gint_osmenu(void); +/* gint_osmenu_native(): Like gint_osmenu() without the world switch + This is a replacement for gint_osmenu() which can be used when the current + kernel is already the native OS kernel. */ +void gint_osmenu_native(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. + An add-in that returns from its main() function automatically exits to the + OS' main menu. However, when this happens the OS does not allow the add-in + to be restarted unless another add-in is launched first. (This is because + the OS tries to *resume* the current add-in, which then proceeds to exit + again immediately.) - 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. + This function enables a gint trick where after main() returns the add-in + will invoke the main menu with gint_osmenu() rather than exiting. If the + add-in is selected again, gint will jump back to the entry point, creating + the illusion that the add-in exited and was then restarted. @restart 0 to exit, 1 to restart by using gint_osmenu() */ void gint_setrestart(int restart); diff --git a/src/kernel/osmenu.c b/src/kernel/osmenu.c index 8e726bb..3f6a608 100644 --- a/src/kernel/osmenu.c +++ b/src/kernel/osmenu.c @@ -23,7 +23,7 @@ static void __osmenu_handler(void) __Timer_Deinstall(__osmenu_id); } -static void __osmenu(void) +void gint_osmenu_native(void) { __ClearKeyBuffer(); @@ -70,5 +70,5 @@ static void __osmenu(void) /* gint_osmenu() - switch out of gint and call the calculator's main menu */ void gint_osmenu(void) { - gint_world_switch(GINT_CALL(__osmenu)); + gint_world_switch(GINT_CALL(gint_osmenu_native)); } diff --git a/src/kernel/start.c b/src/kernel/start.c index 7530519..0902967 100644 --- a/src/kernel/start.c +++ b/src/kernel/start.c @@ -94,11 +94,7 @@ static void callarray(void (**f)(void), void (**l)(void)) while(f < l) (*(*f++))(); } -/* 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) +static int start2(int isappli, int optnum) { /* We are currently in a dynamic userspace mapping of an add-in run from the storage memory. We are running in privileged mode with one @@ -179,20 +175,14 @@ int start(int isappli, int optnum) hosted user application, which has its own constructors and destructors to work with. */ - while(1) - { - /* Here, we use exit() to allow the standard library to do - what it wants in exit() after main() finishes executing */ - if(!setjmp(gint_exitbuf)) { - callarray(&bctors, &ectors); - exit(main(isappli, optnum)); - } - else { - callarray(&bdtors, &edtors); - } - - if(!gint_restart) break; - gint_osmenu(); + /* Here, we use exit() to allow the standard library to do + what it wants in exit() after main() finishes executing */ + if(!setjmp(gint_exitbuf)) { + callarray(&bctors, &ectors); + exit(main(isappli, optnum)); + } + else { + callarray(&bdtors, &edtors); } /* Before leaving the application, we need to clean everything we @@ -206,6 +196,18 @@ int start(int isappli, int optnum) return gint_exitcode; } +GSECTION(".text.entry") +int start(int isappli, int optnum) +{ + int rc; + while(1) { + rc = start2(isappli, optnum); + if(!gint_restart) break; + gint_osmenu_native(); + } + return rc; +} + /* Standard _Exit, used by the fxlibc exit() to leave control */ void _Exit(int rc) {