|
40 | 40 |
|
41 | 41 | /* X-BASIC FNC file information table format */
|
42 | 42 | typedef struct _x68k_fnc_info_t {
|
43 |
| - void (*entry_boot)(void); |
| 43 | + union { |
| 44 | + void (*entry_boot)(void); |
| 45 | + struct _x68k_fnc_info_t *next; |
| 46 | + }; |
44 | 47 | void (*entry_run)(void);
|
45 | 48 | void (*entry_end)(void);
|
46 | 49 | void (*entry_exit)(void);
|
@@ -85,6 +88,8 @@ typedef struct _mp_obj_fun_x68kfnc_t {
|
85 | 88 | MP_DEFINE_CONST_FUN_OBJ_VAR(x68k_fnc_obj, 0, 0);
|
86 | 89 | static uint32_t x68kfnc_t_addr;
|
87 | 90 |
|
| 91 | +static x68k_fnc_info_t *xfnc_list = NULL; |
| 92 | + |
88 | 93 | /****************************************************************************/
|
89 | 94 |
|
90 | 95 | STATIC mp_obj_t x68k_callfncentry(size_t n_args, const mp_obj_t *args) {
|
@@ -283,9 +288,33 @@ STATIC mp_obj_t x68k_loadfnc(size_t n_args, const mp_obj_t *args) {
|
283 | 288 | // Read FNC file information table
|
284 | 289 |
|
285 | 290 | x68k_fnc_info_t *info = (x68k_fnc_info_t *)blocktop;
|
| 291 | + const char *tokentbl; |
| 292 | + size_t tokentbl_len; |
| 293 | + bool loaded = false; |
| 294 | + |
| 295 | + // Get the size of token table |
| 296 | + tokentbl = info->tokentbl; |
| 297 | + while (*tokentbl != '\0') { |
| 298 | + tokentbl = tokentbl + strlen(tokentbl) + 1; |
| 299 | + } |
| 300 | + tokentbl_len = tokentbl - info->tokentbl + 1; |
| 301 | + |
| 302 | + // Confirm whether the token table already exists |
| 303 | + x68k_fnc_info_t *ninfo; |
| 304 | + for (ninfo = xfnc_list; ninfo != NULL; ninfo = ninfo->next) { |
| 305 | + if (memcmp(info->tokentbl, ninfo->tokentbl, tokentbl_len) == 0) { |
| 306 | + // Free FNC file and use existing file on the memory |
| 307 | + _dos_mfree(blocktop); |
| 308 | + info = ninfo; |
| 309 | + loaded = true; |
| 310 | + break; |
| 311 | + } |
| 312 | + } |
| 313 | + |
286 | 314 | int nfnc = 0;
|
287 |
| - const char *tokentbl = info->tokentbl; |
| 315 | + tokentbl = info->tokentbl; |
288 | 316 |
|
| 317 | + // Register functions in the FNC file |
289 | 318 | while (*tokentbl != '\0') {
|
290 | 319 | #ifdef XFNC_DEBUG
|
291 | 320 | const uint16_t *pp = info->parmtbl[nfnc];
|
@@ -331,6 +360,35 @@ STATIC mp_obj_t x68k_loadfnc(size_t n_args, const mp_obj_t *args) {
|
331 | 360 | nfnc++;
|
332 | 361 | }
|
333 | 362 |
|
| 363 | + if (!loaded) { |
| 364 | + // Call start entries only once |
| 365 | + info->entry_boot(); |
| 366 | + info->entry_run(); |
| 367 | + |
| 368 | + info->next = xfnc_list; |
| 369 | + xfnc_list = info; |
| 370 | + } |
| 371 | + |
334 | 372 | return mp_const_none;
|
335 | 373 | }
|
336 | 374 | MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(x68k_loadfnc_obj, 1, 2, x68k_loadfnc);
|
| 375 | + |
| 376 | +void x68k_freefnc(void) |
| 377 | +{ |
| 378 | + x68k_fnc_info_t *info; |
| 379 | + x68k_fnc_info_t *next; |
| 380 | + |
| 381 | + // Call all end entries |
| 382 | + for (info = xfnc_list; info != NULL; info = next) { |
| 383 | + next = info->next; |
| 384 | + info->entry_end(); |
| 385 | + } |
| 386 | + |
| 387 | + // Call all exit entries |
| 388 | + for (info = xfnc_list; info != NULL; info = next) { |
| 389 | + next = info->next; |
| 390 | + info->entry_exit(); |
| 391 | + _dos_mfree(info); |
| 392 | + } |
| 393 | + xfnc_list = NULL; |
| 394 | +} |
0 commit comments