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.
This commit is contained in:
Lephe 2020-07-20 20:37:34 +02:00
parent 6c535bf7df
commit 4cb1555708
Signed by untrusted user: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 33 additions and 6 deletions

1
TODO
View File

@ -13,7 +13,6 @@ Extensions on existing code:
* core: review forgotten globals and MPU addresses not in <gint/mpu/*.h>
* 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

View File

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

View File

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