kernel: make gint_setrestart() reset everything

This commit is contained in:
Lephe 2022-09-02 22:29:19 +02:00
parent 9924dc4684
commit 3e5c45c5ad
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
3 changed files with 37 additions and 26 deletions

View file

@ -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);

View file

@ -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));
}

View file

@ -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)
{