From 164d090a43711ff984107e5c669f25d0511ee059 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 2 Jul 2020 17:24:34 +0200 Subject: [PATCH 001/130] some preparations for string variables, added BASIC command COLD --- doc/Extended-BASIC.md | 4 + src/aliases/,aliases_ram_lowmem.s | 8 +- src/basic/,imports.s | 1 + .../basic_commands_CC/cmd__jumptable_CC.s | 3 +- src/basic/basic_commands_CC/cmd_cold.s | 12 ++ .../basic_commands_CC/helper_ask_if_sure.s | 65 +++++++++++ src/basic/basic_operators/oper_add.s | 2 +- src/basic/editor/shell.s | 5 + src/basic/engine/alloc_temp_string.s | 26 ----- src/basic/engine/varstr_alloc.s | 106 ++++++++++++++++++ src/basic/engine/varstr_dealloc.s | 9 ++ src/basic/engine/varstr_garbage_collect.s | 8 ++ src/basic/memory/shift_mem_adapt_pointers.s | 6 +- src/basic/memory/shift_mem_aliases.s | 9 ++ src/basic/memory/shift_mem_down.s | 2 +- src/basic/memory/shift_mem_up.s | 2 +- src/kernal/init/fffc.vector_reset.s | 2 + src/kernal/interrupts/fffa.vector_nmi.s | 2 + src/kernal/interrupts/fffe.vector_irq.s | 2 + testsuite/testdisk.d64 | Bin 174848 -> 174848 bytes tools/generate_strings.cc | 8 +- 21 files changed, 240 insertions(+), 42 deletions(-) create mode 100644 src/basic/basic_commands_CC/cmd_cold.s create mode 100644 src/basic/basic_commands_CC/helper_ask_if_sure.s delete mode 100644 src/basic/engine/alloc_temp_string.s create mode 100644 src/basic/engine/varstr_alloc.s create mode 100644 src/basic/engine/varstr_dealloc.s create mode 100644 src/basic/engine/varstr_garbage_collect.s create mode 100644 src/basic/memory/shift_mem_aliases.s diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index dd48b323..5837fe4c 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -41,6 +41,10 @@ Launches a built-in tape head alignment tool. Destorys program in memory. Press ## Additional BASIC commands +### `COLD` + +Resets the machine. In direct mode asks for confirmation firsts. + ### `FAST` Tries to switch the machine to turbo mode - details differ depending on the configured machine / motherboard. diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index eb492b70..6468f572 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -52,7 +52,7 @@ .label OPPTR = $4B // $4B-$4C helper variable for expression computation, [!] our usage details are different .label OPMASK = $4D // -- NOT IMPLEMENTED -- .label DEFPNT = $4E // $4E-$4F -- NOT IMPLEMENTED -- - .label DSCPNT = $50 // $50-$52 -- NOT IMPLEMENTED -- + .label DSCPNT = $50 // $50-$52 temporary area fro string handling, [!] our usage might differ .label FOUR6 = $53 // -- NOT IMPLEMENTED -- .label JMPER = $54 // $54-$56 -- NOT IMPLEMENTED -- .label TEMPF1 = $57 // $57-$5B BASIC numeric work area @@ -71,12 +71,6 @@ .label FAC2_mantissa = $6A // $6A - $6D .label FAC2_sign = $6E - // We re-use FAC2 for memory move pointers, since we cannot be doing calculations while moving memory - .label memmove__src = $69 - .label memmove__dst = $6B - .label memmove__size = $6D - - .label ARISGN = $6F // -- NOT IMPLEMENTED -- .label FACOV = $70 // FAC1 low order mantissa .label FBUFPT = $71 // $71-$72 -- NOT IMPLEMENTED -- diff --git a/src/basic/,imports.s b/src/basic/,imports.s index 8b3c1e45..cbe1dc6f 100644 --- a/src/basic/,imports.s +++ b/src/basic/,imports.s @@ -32,6 +32,7 @@ .label panic = KERNAL().panic #endif +.label vector_reset = KERNAL().vector_reset .label hw_entry_reset = KERNAL().hw_entry_reset #if CONFIG_DBG_PRINTF diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s index 52a9cb50..cc85d4f9 100644 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ b/src/basic/basic_commands_CC/cmd__jumptable_CC.s @@ -15,7 +15,8 @@ cmd_bsave, cmd_bverify, - cmd_old + cmd_old, + cmd_cold ) diff --git a/src/basic/basic_commands_CC/cmd_cold.s b/src/basic/basic_commands_CC/cmd_cold.s new file mode 100644 index 00000000..fe197941 --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_cold.s @@ -0,0 +1,12 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_cold: + + jsr helper_ask_if_sure + bcs_16 execute_statements + + jsr JCLALL // for extra safety + jmp (vector_reset) // hardware CPU vector diff --git a/src/basic/basic_commands_CC/helper_ask_if_sure.s b/src/basic/basic_commands_CC/helper_ask_if_sure.s new file mode 100644 index 00000000..f68a92f9 --- /dev/null +++ b/src/basic/basic_commands_CC/helper_ask_if_sure.s @@ -0,0 +1,65 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// For direct mode, asks the user if he is sure (sets Carry if not); +// otherwise returns with Carry clear +// + + +helper_ask_if_sure: + + // First check, if we are in direct mode,; if not, do not ask + + ldx CURLIN+1 + inx + bne helper_ask_if_sure_ok // branch if not direct mode + + // Not direct mode - display the question + + ldx #IDX__STR_IF_SURE + jsr print_packed_misc_str + + // Clear the keyboard queue + + lda #$00 + sta NDX + + // Enable cursor, fetch the answer + + lda #$00 + sta BLNSW +!: + jsr JGETIN + cmp #$00 + beq !- + + // Check if 'Y' + + cmp #$59 + beq !+ + + lda #$4E // 'N' + jsr JCHROUT + + sec + rts +!: + // Display 'Y' and wait a short moment for a better user experience + + jsr JCHROUT + + clc + lda TIME+0 + adc #$0C +!: + cmp TIME+0 + bne !- + + // FALLTROUGH + +helper_ask_if_sure_ok: + + clc + rts diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index 2670de2e..2b3a0632 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -58,7 +58,7 @@ oper_add_strings: adc __FAC2+0 bcs_16 do_STRING_TOO_LONG_error - jsr alloc_temp_string + // jsr alloc_temp_string .break diff --git a/src/basic/editor/shell.s b/src/basic/editor/shell.s index 94e093c5..5d66c48b 100644 --- a/src/basic/editor/shell.s +++ b/src/basic/editor/shell.s @@ -9,6 +9,11 @@ shell_main_loop: ldx #IDX__STR_READY jsr print_packed_misc_str + // Mark mode as direct + + lda #$FF + sta CURLIN+1 + // Enable Kernal messages lda #$80 jsr JSETMSG diff --git a/src/basic/engine/alloc_temp_string.s b/src/basic/engine/alloc_temp_string.s deleted file mode 100644 index 1701c78d..00000000 --- a/src/basic/engine/alloc_temp_string.s +++ /dev/null @@ -1,26 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Allocates area for a temporary string -// -// Input: -// - .A - string length -// - - -// XXX - finish the implementation once string memory handling is done - - -alloc_temp_string: - - // Check if temporary descriptor stack has a free slot - - ldx LASTPT - cpx #$1F - bcs_16 do_FORMULA_TOO_COMPLEX_error - - // XXX - - jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/varstr_alloc.s b/src/basic/engine/varstr_alloc.s new file mode 100644 index 00000000..b44efd1e --- /dev/null +++ b/src/basic/engine/varstr_alloc.s @@ -0,0 +1,106 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Allocates memory for string - lowers FRETOP (but not below STREND) +// +// Note: We are not going to use the C64-style memory management here, as it implies +// a very slow garbage collector. Instead, we are using a scheme similar to used in +// BASIC V3.5 and later, with 'back-pointers' after each string, telling about the +// location of the string descriptor. +// +// See: +// - https://www.c64-wiki.com/wiki/Memory_(BASIC) +// - https://sites.google.com/site/h2obsession/CBM/basic/variable-format +// +// Input: +// - DSCPNT+0, DSCPNT+1 - pointer to string descriptor, first pointed byte should contain desired length +// + +varstr_alloc: + + // Mark garbage collector as not run yet + + lda #$00 + + // FALLTROUGH + +varstr_alloc_retry: + + sta GARBFL // Computes Mapping the Commodore 64, page 10 + + // Backup FRETOP in case of alocation problems + + lda FRETOP+0 + sta INDEX+0 + lda FRETOP+1 + sta INDEX+1 + + // Lower FRETOP to make space for string descriptor + +#if !HAS_OPCODES_65CE02 + + lda #$02 + jsr varstr_FRETOP_down + +#else // HAS_OPCODES_65CE02 + + dew FRETOP + dew FRETOP + +#endif + + jsr varstr_FRETOP_check + bcs varstr_alloc_fail + + // XXX finish this + + + + + +varstr_alloc_fail: + + // Unable to alocate memory - restore FRETOP value + + lda INDEX+0 + sta FRETOP+0 + lda INDEX+1 + sta FRETOP+1 + + // Check if it is worth to perform garbage collection and retry + + bit GARBFL + + // XXX finish this + + + + +// XXX move these helper routines to a better place + + +varstr_FRETOP_down: // memmove__tmp - length to lower FRETOP + + sec + lda FRETOP+0 + sbc memmove__tmp + sta FRETOP+0 + bcs !+ + dec FRETOP+1 +!: + rts + +varstr_FRETOP_check: + + // Check if FRETOP > STREND, Carry set if not + + lda STREND+1 + cmp FRETOP+1 + beq !+ + rts +!: + lda STREND+0 + cmp FRETOP+0 + rts diff --git a/src/basic/engine/varstr_dealloc.s b/src/basic/engine/varstr_dealloc.s new file mode 100644 index 00000000..a3912f4b --- /dev/null +++ b/src/basic/engine/varstr_dealloc.s @@ -0,0 +1,9 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +varstr_dealloc: + + rts // XXX implement this + \ No newline at end of file diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s new file mode 100644 index 00000000..7683d587 --- /dev/null +++ b/src/basic/engine/varstr_garbage_collect.s @@ -0,0 +1,8 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +varstr_garbage_collect: + + rts // XXX implement this diff --git a/src/basic/memory/shift_mem_adapt_pointers.s b/src/basic/memory/shift_mem_adapt_pointers.s index 072615a3..497b66bb 100644 --- a/src/basic/memory/shift_mem_adapt_pointers.s +++ b/src/basic/memory/shift_mem_adapt_pointers.s @@ -9,13 +9,13 @@ shift_mem_adapt_pointers: - sty RESHO+4 + sty memmove__tmp // Adapt source pointer sec lda memmove__src+0 - sbc RESHO+4 + sbc memmove__tmp sta memmove__src+0 bcs !+ dec memmove__src+1 @@ -24,7 +24,7 @@ shift_mem_adapt_pointers: sec lda memmove__dst+0 - sbc RESHO+4 + sbc memmove__tmp sta memmove__dst+0 bcs !+ dec memmove__dst+1 diff --git a/src/basic/memory/shift_mem_aliases.s b/src/basic/memory/shift_mem_aliases.s new file mode 100644 index 00000000..6acd142f --- /dev/null +++ b/src/basic/memory/shift_mem_aliases.s @@ -0,0 +1,9 @@ + +// +// Aliases for memory locations for memory block copy routines +// + +.label memmove__src = INDEX+2 +.label memmove__dst = RESHO+0 +.label memmove__size = RESHO+2 +.label memmove__tmp = RESHO+4 diff --git a/src/basic/memory/shift_mem_down.s b/src/basic/memory/shift_mem_down.s index 7a6e41df..7e5c4c02 100644 --- a/src/basic/memory/shift_mem_down.s +++ b/src/basic/memory/shift_mem_down.s @@ -11,7 +11,7 @@ // - memmove__dst - pointer to the first byte of destination // - memmove__size - number of bytes to copy // -// All the input variables, .A, and .Y register, are destroyed. Also uses RESHO+4 variable. +// All the input variables, .A, and .Y register, are destroyed. Also uses memmove__tmp variable. // diff --git a/src/basic/memory/shift_mem_up.s b/src/basic/memory/shift_mem_up.s index 320c01db..7af21766 100644 --- a/src/basic/memory/shift_mem_up.s +++ b/src/basic/memory/shift_mem_up.s @@ -11,7 +11,7 @@ // - memmove__dst - pointer to the last byte of destination // - memmove__size - number of bytes to copy // -// All the input variables, .A, and .Y register, are destroyed. Also uses RESHO+4 variable. +// All the input variables, .A, and .Y register, are destroyed. Also uses memmove__tmp variable. // diff --git a/src/kernal/init/fffc.vector_reset.s b/src/kernal/init/fffc.vector_reset.s index c8322445..32fb6c03 100644 --- a/src/kernal/init/fffc.vector_reset.s +++ b/src/kernal/init/fffc.vector_reset.s @@ -6,4 +6,6 @@ // $FFFC - CPU Reset Vector // Uncontrovertial, as it is a CPU requirement, and nothing else. +vector_reset: + .word hw_entry_reset diff --git a/src/kernal/interrupts/fffa.vector_nmi.s b/src/kernal/interrupts/fffa.vector_nmi.s index c33c2602..16089345 100644 --- a/src/kernal/interrupts/fffa.vector_nmi.s +++ b/src/kernal/interrupts/fffa.vector_nmi.s @@ -6,4 +6,6 @@ // $FFFA - CPU NMI Hanlder // Uncontrovertial as this is also a CPU requirement. +vector_nmi: + .word hw_entry_nmi diff --git a/src/kernal/interrupts/fffe.vector_irq.s b/src/kernal/interrupts/fffe.vector_irq.s index 755e9c57..ba5a1f6f 100644 --- a/src/kernal/interrupts/fffe.vector_irq.s +++ b/src/kernal/interrupts/fffe.vector_irq.s @@ -7,4 +7,6 @@ // This is non-controvertial, as it is a 6502 CPU requirement, and we just have to point // it to whatever IRQ routine we make. +vector_irq: + .word hw_entry_irq diff --git a/testsuite/testdisk.d64 b/testsuite/testdisk.d64 index a455d2ee8fc3863fbc0022af6383ad7b1d85193c..5cb877cf82a0d821e7743b9efdb8672310be58bf 100644 GIT binary patch delta 98 zcmZp;#?=5sTNoJw#ibZI#5lMZ7#yuYKw+kmBM2yMWPHJ~EsD{Fn@#Y~Z+^i))BREz g#il2uG9Hp`5@ZZ<4Gvj=1Q=j|v5|2rBjZ6A0GI_Gs{jB1 delta 44 zcmZp;#?=5sTNoJwH!}a{*cQd;!p$c1?>E2TpXq+7jAGLhQW+05vTS8xyypS{ei{&Q diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index bfbd08e0..2bddb6e7 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -178,11 +178,14 @@ const StringEntryList GLOBAL_Keywords_V2 = { ListType::KEYWORDS, "keywords_V2", const StringEntryList GLOBAL_Keywords_CC = { ListType::KEYWORDS, "keywords_CC", { // STD M65 U64 X16 - { true, true, true, true, "KCC_01", "MERGE", }, // OpenROMs specific, not present in CBM BASIC dialects + { true, true, true, true, "KCC_01", "MERGE", }, // Not present in CBM BASIC dialects, but common to some extensions (*) { true, true, true, true, "KCC_02", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html { true, true, true, true, "KCC_03", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html { true, true, true, true, "KCC_04", "BVERIFY", }, - { true, true, true, true, "KCC_05", "OLD", }, // OpenROMs specific, not present in CBM BASIC dialects + { true, true, true, true, "KCC_05", "OLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { true, true, true, true, "KCC_06", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + + // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c } }; // extended BASIC keywords - reserved for BASIC commands likely making sense on most C64-compatible machines @@ -310,6 +313,7 @@ const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", { true, true, true, true, "STR_READY", "\rREADY.\r" }, // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html { true, true, true, true, "STR_IN", " IN " }, + { true, true, true, true, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm // STD M65 U64 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, // Note: depending on configuration, additional strings will be added here From 940470e84d9b84007e7aba6ba6719c22ec9dc5d4 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 2 Jul 2020 17:35:00 +0200 Subject: [PATCH 002/130] spelling fixes --- doc/Extended-BASIC.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 5837fe4c..10fbb59a 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -37,13 +37,13 @@ Like above, but merges a BASIC program to the one already stored in memory. ### `←H` -Launches a built-in tape head alignment tool. Destorys program in memory. Press `RUN/STOP` to terminate the tool. +Launches a built-in tape head alignment tool. Destroys program in memory. Press `RUN/STOP` to terminate the tool. ## Additional BASIC commands ### `COLD` -Resets the machine. In direct mode asks for confirmation firsts. +Resets the machine. In direct mode asks for confirmation first. ### `FAST` From 116c6734e69436cd29f06d74c29b896b99ce5425 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 2 Jul 2020 22:02:39 +0200 Subject: [PATCH 003/130] string allocation routine complete, dealloc and garbage collection still to do --- src/basic/engine/varstr_alloc.s | 70 ++++++++++++++------------ src/basic/engine/varstr_alloc_fretop.s | 31 ++++++++++++ 2 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 src/basic/engine/varstr_alloc_fretop.s diff --git a/src/basic/engine/varstr_alloc.s b/src/basic/engine/varstr_alloc.s index b44efd1e..35880328 100644 --- a/src/basic/engine/varstr_alloc.s +++ b/src/basic/engine/varstr_alloc.s @@ -18,6 +18,8 @@ // - DSCPNT+0, DSCPNT+1 - pointer to string descriptor, first pointed byte should contain desired length // +// XXX test this routine + varstr_alloc: // Mark garbage collector as not run yet @@ -44,21 +46,45 @@ varstr_alloc_retry: lda #$02 jsr varstr_FRETOP_down -#else // HAS_OPCODES_65CE02 +#else // HAS_OPCODES_65CE02 - this time code is slightly longer, but faster dew FRETOP dew FRETOP + jsr varstr_FRETOP_check + #endif - jsr varstr_FRETOP_check bcs varstr_alloc_fail - // XXX finish this + // Create the back-pointer to the string descriptor + ldy #$00 + lda DSCPNT+0 + sta (FRETOP), y + iny + lda DSCPNT+1 + sta (FRETOP), y + // Now lower FRETOP again to make space for the string content + dey // $01 -> $00 + lda (DSCPNT), y + jsr varstr_FRETOP_down + bcs varstr_alloc_fail + // Success - fill in the string descriptor + + iny // $00 -> $01 + lda FRETOP+0 + sta (DSCPNT), y + iny + lda FRETOP+1 + sta (DSCPNT), y + + // The end + + rts varstr_alloc_fail: @@ -72,35 +98,13 @@ varstr_alloc_fail: // Check if it is worth to perform garbage collection and retry bit GARBFL + bpl_16 do_OUT_OF_MEMORY_error - // XXX finish this + dec GARBFL // $00 -> $FF + jsr varstr_garbage_collect - - - -// XXX move these helper routines to a better place - - -varstr_FRETOP_down: // memmove__tmp - length to lower FRETOP - - sec - lda FRETOP+0 - sbc memmove__tmp - sta FRETOP+0 - bcs !+ - dec FRETOP+1 -!: - rts - -varstr_FRETOP_check: - - // Check if FRETOP > STREND, Carry set if not - - lda STREND+1 - cmp FRETOP+1 - beq !+ - rts -!: - lda STREND+0 - cmp FRETOP+0 - rts +#if HAS_OPCODES_65C02 + bra varstr_alloc_retry +#else + jmp varstr_alloc_retry +#endif diff --git a/src/basic/engine/varstr_alloc_fretop.s b/src/basic/engine/varstr_alloc_fretop.s new file mode 100644 index 00000000..09f033bc --- /dev/null +++ b/src/basic/engine/varstr_alloc_fretop.s @@ -0,0 +1,31 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routines for 'varstr_alloc' +// + +varstr_FRETOP_down: // .A - bytes to lower FRETOP, uses memmove__tmp + + sta memmove__tmp + + sec + lda FRETOP+0 + sbc memmove__tmp + sta FRETOP+0 + bcs !+ + dec FRETOP+1 +!: + // FALLTROUGH + +varstr_FRETOP_check: // check if FRETOP > STREND, Carry set if not + + lda STREND+1 + cmp FRETOP+1 + beq !+ + rts +!: + lda STREND+0 + cmp FRETOP+0 + rts From 2c86c577bc73345c5190816d4f851c75d2790f9f Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 2 Jul 2020 22:51:48 +0200 Subject: [PATCH 004/130] work towards string deallocation --- src/basic/engine/varstr_alloc.s | 38 +++++++- src/basic/engine/varstr_dealloc.s | 9 -- src/basic/engine/varstr_free.s | 75 ++++++++++++++++ ...der_rom_routines_60k.s => under_rom_60k.s} | 0 .../memory/under_rom_peek_poke_46k_50k.s | 89 +++++++++++++++++++ ...es_46k_50k.s => under_rom_shift_46k_50k.s} | 62 ------------- ...routines_46k_50k.s => under_rom_46k_50k.s} | 0 ...der_rom_routines_60k.s => under_rom_60k.s} | 0 8 files changed, 200 insertions(+), 73 deletions(-) delete mode 100644 src/basic/engine/varstr_dealloc.s create mode 100644 src/basic/engine/varstr_free.s rename src/basic/memory/{under_rom_routines_60k.s => under_rom_60k.s} (100%) create mode 100644 src/basic/memory/under_rom_peek_poke_46k_50k.s rename src/basic/memory/{under_rom_routines_46k_50k.s => under_rom_shift_46k_50k.s} (67%) rename src/kernal/memory/{under_rom_routines_46k_50k.s => under_rom_46k_50k.s} (100%) rename src/kernal/memory/{under_rom_routines_60k.s => under_rom_60k.s} (100%) diff --git a/src/basic/engine/varstr_alloc.s b/src/basic/engine/varstr_alloc.s index 35880328..8a24fec7 100644 --- a/src/basic/engine/varstr_alloc.s +++ b/src/basic/engine/varstr_alloc.s @@ -19,6 +19,7 @@ // // XXX test this routine +// XXX make it compatible with under-ROM routines varstr_alloc: @@ -61,15 +62,36 @@ varstr_alloc_retry: ldy #$00 lda DSCPNT+0 + +#if CONFIG_MEMORY_MODEL_60K + ldx # $00 - lda (DSCPNT), y + +#if CONFIG_MEMORY_MODEL_60K + ldx # $01 lda FRETOP+0 - sta (DSCPNT), y + +#if CONFIG_MEMORY_MODEL_60K + ldx # memmove__src diff --git a/src/kernal/memory/under_rom_routines_46k_50k.s b/src/kernal/memory/under_rom_46k_50k.s similarity index 100% rename from src/kernal/memory/under_rom_routines_46k_50k.s rename to src/kernal/memory/under_rom_46k_50k.s diff --git a/src/kernal/memory/under_rom_routines_60k.s b/src/kernal/memory/under_rom_60k.s similarity index 100% rename from src/kernal/memory/under_rom_routines_60k.s rename to src/kernal/memory/under_rom_60k.s From aa101f79c63fda046a2494311012d477061f7a1c Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 3 Jul 2020 16:47:23 +0200 Subject: [PATCH 005/130] added routine to free string memory --- src/basic/engine/varstr_alloc.s | 4 +- src/basic/engine/varstr_alloc_fretop.s | 6 +-- src/basic/engine/varstr_free.s | 61 ++++++++++++++++++++++++-- src/basic/engine/varstr_free_fretop.s | 18 ++++++++ 4 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 src/basic/engine/varstr_free_fretop.s diff --git a/src/basic/engine/varstr_alloc.s b/src/basic/engine/varstr_alloc.s index 8a24fec7..dd1e0d88 100644 --- a/src/basic/engine/varstr_alloc.s +++ b/src/basic/engine/varstr_alloc.s @@ -45,7 +45,7 @@ varstr_alloc_retry: #if !HAS_OPCODES_65CE02 lda #$02 - jsr varstr_FRETOP_down + jsr varstr_FRETOP_down_A #else // HAS_OPCODES_65CE02 - this time code is slightly longer, but faster @@ -92,7 +92,7 @@ varstr_alloc_retry: lda (DSCPNT),y #endif - jsr varstr_FRETOP_down + jsr varstr_FRETOP_down_A bcs varstr_alloc_fail // Success - fill in the string descriptor diff --git a/src/basic/engine/varstr_alloc_fretop.s b/src/basic/engine/varstr_alloc_fretop.s index 09f033bc..b00d2cb3 100644 --- a/src/basic/engine/varstr_alloc_fretop.s +++ b/src/basic/engine/varstr_alloc_fretop.s @@ -6,13 +6,13 @@ // Helper routines for 'varstr_alloc' // -varstr_FRETOP_down: // .A - bytes to lower FRETOP, uses memmove__tmp +varstr_FRETOP_down_A: // .A - bytes to lower FRETOP, uses DSCPNT+2 - sta memmove__tmp + sta DSCPNT+2 sec lda FRETOP+0 - sbc memmove__tmp + sbc DSCPNT+2 sta FRETOP+0 bcs !+ dec FRETOP+1 diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index 448c161f..c61aae3a 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -61,15 +61,68 @@ varstr_free: cmp FRETOP+1 bne varstr_free_inside - // This is the lowest string - increase FRETOP, this way + // This is the lowest string - so just increase FRETOP, this way // the garbage collector will not be needed that quickly - // XXX implement this + jsr varstr_FRETOP_up // free the string data + +#if !HAS_OPCODES_65CE02 + + lda #$02 // free the back-pointer + sta DSCPNT+2 + jmp varstr_FRETOP_up + +#else // HAS_OPCODES_65CE02 + + inw FRETOP // free the back-pointer + inw FRETOP + + rts + +#endif varstr_free_inside: - // THis is not the lowest string; mark it as free + // This is not the lowest string; mark it as free + // First preserve the string size, it will make it easier for the garbage collector - // XXX implement this + lda DSCPNT+2 + tay + dey +#if CONFIG_MEMORY_MODEL_60K + ldx # $01 + +#if CONFIG_MEMORY_MODEL_60K + jmp poke_under_roms +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + sta (DSCPNT), y rts +#endif diff --git a/src/basic/engine/varstr_free_fretop.s b/src/basic/engine/varstr_free_fretop.s new file mode 100644 index 00000000..a9fec660 --- /dev/null +++ b/src/basic/engine/varstr_free_fretop.s @@ -0,0 +1,18 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routines for 'varstr_free' +// + +varstr_FRETOP_up: // DSCPNT+2 - bytes to increment FRETO, uses DSCPNT+2 + + clc + lda FRETOP+0 + adc DSCPNT+2 + sta FRETOP+0 + bcc !+ + inc FRETOP+1 +!: + rts From 86c61c88f47675241d00ba1b13bded03801f26bb Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 7 Jul 2020 18:24:27 +0200 Subject: [PATCH 006/130] more work on garbage collector --- src/basic/engine/varstr_garbage_collect.s | 128 +++++++++++++++++++++- 1 file changed, 127 insertions(+), 1 deletion(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 7683d587..1285b288 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -2,7 +2,133 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE +// XXX test this routine varstr_garbage_collect: - rts // XXX implement this + // The routine utilizes the 'shift_mem_up' - which leaves INDEX+0 and INDEX+1 + // free to be used, but INDEX+2 and beyond would be overwritten + + // We will reuse TXTPTR as the moving pointer, so store it on the stack + + lda TXTPTR+0 + pha + lda TXTPTR+1 + pha + + // INDEX+0 and INDEX+1 will be our cumulative shift counter + + lda #$00 + sta INDEX+0 + sta INDEX+1 + + // Start from the highest string and go downwards + + lda MEMSIZ+0 + sta TXTPTR+0 + lda MEMSIZ+1 + sta TXTPTR+1 + +varstr_garbage_collect_loop: + + // Check whether we reached FRETOP + + lda TXTPTR+0 + cmp FRETOP+0 + bne varstr_garbage_collect_check_bptr + lda TXTPTR+1 + cmp FRETOP+1 + bne varstr_garbage_collect_check_bptr + + // End of strings - nothing more to do + + // FALLTROUGH + +varstr_garbage_collect_end: + + // Restore TXTPTR and quit + + pla + sta TXTPTR+1 + pla + sta TXTPTR+0 + + rts + +varstr_garbage_collect_check_bptr: + + // Decrement TXTPTR by 2, so that it points to the back-pointer + +#if !HAS_OPCODES_65CE02 + + lda #$02 + jsr varstr_TXTPTR_down_A + +#else // HAS_OPCODES_65CE02 + + dew TXTPTR + dew TXTPTR + +#endif + + // Check whether the back-pointer is NULL + + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # Date: Tue, 7 Jul 2020 22:54:55 +0200 Subject: [PATCH 007/130] more work towards garbage collector --- src/basic/engine/varstr_garbage_collect.s | 104 ++++++++++++++++++---- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 1285b288..13520446 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -16,6 +16,13 @@ varstr_garbage_collect: lda TXTPTR+1 pha + // Similarly, we will reuse OLDTXT as the pointer to string descriptor + + lda OLDTXT+0 + pha + lda OLDTXT+1 + pha + // INDEX+0 and INDEX+1 will be our cumulative shift counter lda #$00 @@ -31,7 +38,8 @@ varstr_garbage_collect: varstr_garbage_collect_loop: - // Check whether we reached FRETOP + // Check if this was the last string + // XXX instead check if FRETOP+INDEX == TXTPTR lda TXTPTR+0 cmp FRETOP+0 @@ -46,8 +54,12 @@ varstr_garbage_collect_loop: varstr_garbage_collect_end: - // Restore TXTPTR and quit + // Restore OLDTXT and TXTPTR, and quit + pla + sta OLDTXT+1 + pla + sta OLDTXT+0 pla sta TXTPTR+1 pla @@ -60,15 +72,11 @@ varstr_garbage_collect_check_bptr: // Decrement TXTPTR by 2, so that it points to the back-pointer #if !HAS_OPCODES_65CE02 - lda #$02 jsr varstr_TXTPTR_down_A - #else // HAS_OPCODES_65CE02 - dew TXTPTR dew TXTPTR - #endif // Check whether the back-pointer is NULL @@ -78,39 +86,87 @@ varstr_garbage_collect_check_bptr: #if CONFIG_MEMORY_MODEL_60K ldx # Date: Thu, 9 Jul 2020 19:10:09 +0200 Subject: [PATCH 008/130] more work towards garbage collector --- src/basic/engine/varstr_garbage_collect.s | 28 +++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 13520446..48691435 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -38,14 +38,21 @@ varstr_garbage_collect: varstr_garbage_collect_loop: - // Check if this was the last string - // XXX instead check if FRETOP+INDEX == TXTPTR + // Check if this was the last string (if FRETOP+INDEX == TXTPTR), use OLDTXT as temporary storage + + clc + lda INDEX+0 + adc FRETOP+0 + sta OLDTXT+0 + lda INDEX+1 + adc FRETOP+1 + sta OLDTXT+1 lda TXTPTR+0 - cmp FRETOP+0 + cmp OLDTXT+0 bne varstr_garbage_collect_check_bptr lda TXTPTR+1 - cmp FRETOP+1 + cmp OLDTXT+1 bne varstr_garbage_collect_check_bptr // End of strings - nothing more to do @@ -119,7 +126,18 @@ varstr_garbage_collect_check_bptr: // Update TXTPTR - // XXX + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # Date: Thu, 9 Jul 2020 21:53:36 +0200 Subject: [PATCH 009/130] added two more BASIC commands, for testing --- doc/Extended-BASIC.md | 8 ++++++++ src/basic/,imports.s | 2 ++ src/basic/basic_commands_CC/cmd__jumptable_CC.s | 7 +++++-- src/basic/basic_commands_CC/cmd_clear.s | 10 ++++++++++ src/basic/basic_commands_CC/cmd_dispose.s | 10 ++++++++++ src/basic/engine/varstr_garbage_collect.s | 3 ++- tools/generate_strings.cc | 12 +++++++----- 7 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 src/basic/basic_commands_CC/cmd_clear.s create mode 100644 src/basic/basic_commands_CC/cmd_dispose.s diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 10fbb59a..dcb12fe6 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -57,6 +57,14 @@ Tries to switch the machine back to 1 MHz operation mode. Tries to restore program destroyed by `NEW` or a reset. +### `CLEAR` + +Clears the screen content. + +### `DISPOSE` + +Runs the garbage collector - disposes outdated strings. + ### `MERGE "file_name" [, device_number]` Appends the BASIC program from a storage medium to the one currently present in memory. diff --git a/src/basic/,imports.s b/src/basic/,imports.s index cbe1dc6f..6af1d667 100644 --- a/src/basic/,imports.s +++ b/src/basic/,imports.s @@ -35,6 +35,8 @@ .label vector_reset = KERNAL().vector_reset .label hw_entry_reset = KERNAL().hw_entry_reset +.label clear_screen = KERNAL().clear_screen + #if CONFIG_DBG_PRINTF .label printf = KERNAL().printf #endif diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s index cc85d4f9..fa795621 100644 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ b/src/basic/basic_commands_CC/cmd__jumptable_CC.s @@ -9,14 +9,17 @@ .const command_CC_list = List().add( + cmd_old, + cmd_merge, cmd_bload, cmd_bsave, cmd_bverify, - cmd_old, - cmd_cold + cmd_cold, + cmd_clear, + cmd_dispose ) diff --git a/src/basic/basic_commands_CC/cmd_clear.s b/src/basic/basic_commands_CC/cmd_clear.s new file mode 100644 index 00000000..fc2a2ee8 --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_clear.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_clear: + + jsr clear_screen + + jmp execute_statements diff --git a/src/basic/basic_commands_CC/cmd_dispose.s b/src/basic/basic_commands_CC/cmd_dispose.s new file mode 100644 index 00000000..f2adb22e --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_dispose.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_dispose: + + jsr varstr_garbage_collect + + jmp execute_statements diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 48691435..5d5b3adf 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -122,7 +122,8 @@ varstr_garbage_collect_check_bptr: // Move string memory up by INDEX - // XXX + // XXX: set memmove__src (last byte of source), memmove__dst (last byte of destination), memmove__size (bytes to copy) + jsr shift_mem_up // Update TXTPTR diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index 2bddb6e7..dc308b79 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -178,12 +178,14 @@ const StringEntryList GLOBAL_Keywords_V2 = { ListType::KEYWORDS, "keywords_V2", const StringEntryList GLOBAL_Keywords_CC = { ListType::KEYWORDS, "keywords_CC", { // STD M65 U64 X16 - { true, true, true, true, "KCC_01", "MERGE", }, // Not present in CBM BASIC dialects, but common to some extensions (*) - { true, true, true, true, "KCC_02", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html - { true, true, true, true, "KCC_03", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html - { true, true, true, true, "KCC_04", "BVERIFY", }, - { true, true, true, true, "KCC_05", "OLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { true, true, true, true, "KCC_01", "OLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { true, true, true, true, "KCC_02", "MERGE", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { true, true, true, true, "KCC_03", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html + { true, true, true, true, "KCC_04", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html + { true, true, true, true, "KCC_05", "BVERIFY", }, { true, true, true, true, "KCC_06", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { true, true, true, true, "KCC_07", "CLEAR", }, // Not present in CBM BASIC dialects, OpenROMs specific + { true, true, true, true, "KCC_08", "DISPOSE", }, // Not present in CBM BASIC dialects, OpenROMs specific // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c } }; From defd079b2e54a291612fe7a2f3e5cdd40573c38c Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 9 Jul 2020 22:23:04 +0200 Subject: [PATCH 010/130] improved syntax checking in BASIC --- src/basic/basic_commands/cmd_clr.s | 2 +- src/basic/basic_commands/cmd_load_verify.s | 2 +- src/basic/basic_commands/cmd_print.s | 4 ++- src/basic/basic_commands/cmd_restore.s | 2 +- src/basic/basic_commands/cmd_save.s | 4 +-- src/basic/basic_commands/cmd_sys.s | 2 +- .../basic_commands_CC/cmd_bload_bverify.s | 4 +-- src/basic/basic_commands_CC/cmd_clear.s | 5 ++- src/basic/basic_commands_CC/cmd_cold.s | 2 +- src/basic/basic_commands_CC/cmd_dispose.s | 5 ++- src/basic/basic_commands_CC/cmd_merge.s | 4 +-- src/basic/basic_commands_CD/cmd_fast_slow.s | 9 +++--- src/basic/engine/end_of_statement.s | 32 +++++++++++++++++++ src/basic/engine/end_of_statement_check.s | 2 -- 14 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 src/basic/engine/end_of_statement.s diff --git a/src/basic/basic_commands/cmd_clr.s b/src/basic/basic_commands/cmd_clr.s index f944eacc..1204fca6 100644 --- a/src/basic/basic_commands/cmd_clr.s +++ b/src/basic/basic_commands/cmd_clr.s @@ -9,4 +9,4 @@ cmd_clr: // CLR command does not stop execution (confirmed on a C64) - jmp execute_statements + jmp end_of_statement diff --git a/src/basic/basic_commands/cmd_load_verify.s b/src/basic/basic_commands/cmd_load_verify.s index 9a0d59fd..dc1c6058 100644 --- a/src/basic/basic_commands/cmd_load_verify.s +++ b/src/basic/basic_commands/cmd_load_verify.s @@ -52,7 +52,7 @@ cmd_load_no_error: // For VERIFY - this is it lda VERCKB - bne_16 execute_statements + bne_16 end_of_statement // C64 BASIC apparently does not clear variables after a LOAD in the // middle of a program. For safety, we do. diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index 66443f4c..d5126f6f 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -89,4 +89,6 @@ cmd_print_new_line_done: cmd_print_done: - jmp execute_statements + // Execute next statement + + jmp end_of_statement diff --git a/src/basic/basic_commands/cmd_restore.s b/src/basic/basic_commands/cmd_restore.s index 034db54e..62d40846 100644 --- a/src/basic/basic_commands/cmd_restore.s +++ b/src/basic/basic_commands/cmd_restore.s @@ -9,4 +9,4 @@ cmd_restore: // RESTORE command does not stop execution (confirmed on a C64) - jmp execute_statements + jmp end_of_statement diff --git a/src/basic/basic_commands/cmd_save.s b/src/basic/basic_commands/cmd_save.s index 5ced4b27..5a944582 100644 --- a/src/basic/basic_commands/cmd_save.s +++ b/src/basic/basic_commands/cmd_save.s @@ -38,6 +38,6 @@ cmd_save_do: // entry point for BSAVE jsr JSAVE bcs_16 do_kernal_error - // The end + // Execute next statement - jmp execute_statements + jmp end_of_statement \ No newline at end of file diff --git a/src/basic/basic_commands/cmd_sys.s b/src/basic/basic_commands/cmd_sys.s index 8dd3f5a7..16b5fbba 100644 --- a/src/basic/basic_commands/cmd_sys.s +++ b/src/basic/basic_commands/cmd_sys.s @@ -62,7 +62,7 @@ cmd_sys_setup_call: // Call the routine. jsr USRPOK - jmp execute_statements + jmp end_of_statement // diff --git a/src/basic/basic_commands_CC/cmd_bload_bverify.s b/src/basic/basic_commands_CC/cmd_bload_bverify.s index 2b6db9fb..615f3901 100644 --- a/src/basic/basic_commands_CC/cmd_bload_bverify.s +++ b/src/basic/basic_commands_CC/cmd_bload_bverify.s @@ -37,6 +37,6 @@ cmd_bload: jsr JLOAD bcs_16 do_kernal_error - // XXX when number parsing is done, change to continue execution + // Execute next statement - jmp shell_main_loop + jmp end_of_statement diff --git a/src/basic/basic_commands_CC/cmd_clear.s b/src/basic/basic_commands_CC/cmd_clear.s index fc2a2ee8..76cf9f83 100644 --- a/src/basic/basic_commands_CC/cmd_clear.s +++ b/src/basic/basic_commands_CC/cmd_clear.s @@ -7,4 +7,7 @@ cmd_clear: jsr clear_screen - jmp execute_statements + // Execute next statement + + jmp end_of_statement + diff --git a/src/basic/basic_commands_CC/cmd_cold.s b/src/basic/basic_commands_CC/cmd_cold.s index fe197941..345d26c6 100644 --- a/src/basic/basic_commands_CC/cmd_cold.s +++ b/src/basic/basic_commands_CC/cmd_cold.s @@ -6,7 +6,7 @@ cmd_cold: jsr helper_ask_if_sure - bcs_16 execute_statements + bcs_16 end_of_statement jsr JCLALL // for extra safety jmp (vector_reset) // hardware CPU vector diff --git a/src/basic/basic_commands_CC/cmd_dispose.s b/src/basic/basic_commands_CC/cmd_dispose.s index f2adb22e..51b88bfa 100644 --- a/src/basic/basic_commands_CC/cmd_dispose.s +++ b/src/basic/basic_commands_CC/cmd_dispose.s @@ -7,4 +7,7 @@ cmd_dispose: jsr varstr_garbage_collect - jmp execute_statements + // Execute next statement + + jmp end_of_statement + diff --git a/src/basic/basic_commands_CC/cmd_merge.s b/src/basic/basic_commands_CC/cmd_merge.s index 42f3b1ed..376e19a8 100644 --- a/src/basic/basic_commands_CC/cmd_merge.s +++ b/src/basic/basic_commands_CC/cmd_merge.s @@ -46,6 +46,6 @@ cmd_merge_no_error: jsr update_LINKPRG_VARTAB_do_clr - // XXX when number parsing is done, change to continue execution + // Execute next statement - jmp shell_main_loop + jmp end_of_statement diff --git a/src/basic/basic_commands_CD/cmd_fast_slow.s b/src/basic/basic_commands_CD/cmd_fast_slow.s index 79fcb6ae..ddc8ce70 100644 --- a/src/basic/basic_commands_CD/cmd_fast_slow.s +++ b/src/basic/basic_commands_CD/cmd_fast_slow.s @@ -20,8 +20,8 @@ cmd_fast: lda #$41 sta CPU_D6510 + jmp end_of_statement - jmp execute_statements #elif CONFIG_MB_ULTIMATE_64 @@ -30,12 +30,12 @@ cmd_fast: cmd_slow: sta SCPU_SPEED_NORMAL - jmp execute_statements + jmp end_of_statement cmd_fast: sta SCPU_SPEED_TURBO - jmp execute_statements + jmp end_of_statement #elif CONFIG_PLATFORM_COMMODORE_64 @@ -60,8 +60,7 @@ cmd_fast: lda #$01 !: sta VIC_CLKRATE - - jmp execute_statements + jmp end_of_statement #else diff --git a/src/basic/engine/end_of_statement.s b/src/basic/engine/end_of_statement.s new file mode 100644 index 00000000..e6d2442c --- /dev/null +++ b/src/basic/engine/end_of_statement.s @@ -0,0 +1,32 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Executes the next command - after previous got finished +// + + +end_of_statement: + jsr fetch_character + + cmp #$3A // check for colon + beq end_of_statement_next + + cmp #$00 // check for end of the line + beq_16 execute_statements_end_of_line + + cmp #$20 // check for space + beq end_of_statement + + // Unexpectyed character + + jmp do_SYNTAX_error + +end_of_statement_next: + + // Go to next statement + + // XXX this should be speed-optimized, so that no unconsume is necessary + jsr unconsume_character + jmp execute_statements diff --git a/src/basic/engine/end_of_statement_check.s b/src/basic/engine/end_of_statement_check.s index 2c7a7271..8a4c7011 100644 --- a/src/basic/engine/end_of_statement_check.s +++ b/src/basic/engine/end_of_statement_check.s @@ -9,8 +9,6 @@ end_of_statement_check: - // XXX this can probably be size-optimized - ldy #$00 #if CONFIG_MEMORY_MODEL_60K From 4871abd79b2ef08caab39249c6dfe2604f819ce5 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 9 Jul 2020 22:27:04 +0200 Subject: [PATCH 011/130] small code optimization --- src/basic/engine/end_of_statement.s | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/basic/engine/end_of_statement.s b/src/basic/engine/end_of_statement.s index e6d2442c..197ada21 100644 --- a/src/basic/engine/end_of_statement.s +++ b/src/basic/engine/end_of_statement.s @@ -8,25 +8,18 @@ end_of_statement: + jsr fetch_character - cmp #$3A // check for colon - beq end_of_statement_next - - cmp #$00 // check for end of the line - beq_16 execute_statements_end_of_line - cmp #$20 // check for space beq end_of_statement - // Unexpectyed character + cmp #$3A // check for colon + beq_16 execute_statements + + cmp #$00 // check for end of the line + beq_16 execute_statements_end_of_line + + // Unexpected character jmp do_SYNTAX_error - -end_of_statement_next: - - // Go to next statement - - // XXX this should be speed-optimized, so that no unconsume is necessary - jsr unconsume_character - jmp execute_statements From dbd8c777516fa9f549aeccd9f7b82da9c4198f26 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 9 Jul 2020 22:58:15 +0200 Subject: [PATCH 012/130] more size optimizations in BASIC interpreter --- src/basic/basic_commands/cmd__jumptable.s | 4 ++-- src/basic/basic_commands/cmd_clr.s | 8 ++----- src/basic/basic_commands/cmd_list.s | 2 +- src/basic/basic_commands/cmd_load_verify.s | 9 ++++---- src/basic/basic_commands/cmd_new.s | 2 +- src/basic/basic_commands/cmd_print.s | 2 +- src/basic/basic_commands/cmd_rem.s | 2 ++ src/basic/basic_commands/cmd_restore.s | 8 ++----- src/basic/basic_commands/cmd_run_goto.s | 9 ++++++++ src/basic/basic_commands/cmd_save.s | 2 +- src/basic/basic_commands/cmd_stop_end.s | 2 +- src/basic/basic_commands/cmd_sys.s | 5 +---- .../basic_commands_CC/cmd__jumptable_CC.s | 2 +- .../basic_commands_CC/cmd_bload_bverify.s | 2 +- src/basic/basic_commands_CC/cmd_clear.s | 7 ++----- src/basic/basic_commands_CC/cmd_cold.s | 4 +++- src/basic/basic_commands_CC/cmd_dispose.s | 9 +------- src/basic/basic_commands_CC/cmd_merge.s | 8 ++----- src/basic/basic_commands_CC/cmd_old.s | 2 +- src/basic/basic_commands_CD/cmd_fast_slow.s | 10 ++++----- src/basic/editor/shell.s | 8 +++++++ src/basic/engine/execute_line_statements.s | 21 ++++++++++++++----- 22 files changed, 67 insertions(+), 61 deletions(-) diff --git a/src/basic/basic_commands/cmd__jumptable.s b/src/basic/basic_commands/cmd__jumptable.s index d5f8e1ff..0a677b14 100644 --- a/src/basic/basic_commands/cmd__jumptable.s +++ b/src/basic/basic_commands/cmd__jumptable.s @@ -23,7 +23,7 @@ cmd_goto, cmd_run, cmd_if, - cmd_restore, + do_restore, // cmd_restore cmd_gosub, cmd_return, cmd_rem, @@ -42,7 +42,7 @@ cmd_print, cmd_cont, cmd_list, - cmd_clr, + do_clr, // cmd_clr cmd_cmd, cmd_sys, cmd_open, diff --git a/src/basic/basic_commands/cmd_clr.s b/src/basic/basic_commands/cmd_clr.s index 1204fca6..9305ec00 100644 --- a/src/basic/basic_commands/cmd_clr.s +++ b/src/basic/basic_commands/cmd_clr.s @@ -3,10 +3,6 @@ // #LAYOUT# * * #IGNORE -cmd_clr: +// PLACEHOLDER for completeness - jumptable contains direct address - jsr do_clr - - // CLR command does not stop execution (confirmed on a C64) - - jmp end_of_statement +// CLR command does not stop execution (confirmed on a C64) diff --git a/src/basic/basic_commands/cmd_list.s b/src/basic/basic_commands/cmd_list.s index 3da8ca4f..6d7eecc3 100644 --- a/src/basic/basic_commands/cmd_list.s +++ b/src/basic/basic_commands/cmd_list.s @@ -31,7 +31,7 @@ list_loop: // LIST terminates any running program, // because it has fiddled with the current line pointer. // (Confirmed by testing on a C64) - jmp shell_main_loop + jmp end_of_program list_more_lines: diff --git a/src/basic/basic_commands/cmd_load_verify.s b/src/basic/basic_commands/cmd_load_verify.s index dc1c6058..d9fdcda8 100644 --- a/src/basic/basic_commands/cmd_load_verify.s +++ b/src/basic/basic_commands/cmd_load_verify.s @@ -74,10 +74,9 @@ cmd_load_no_error: ldx CURLIN+1 inx - beq cmd_load_end // branch if direct mode + beq_16 end_of_program // branch if direct mode + + pha + pha jmp execute_line - -cmd_load_end: - - jmp shell_main_loop diff --git a/src/basic/basic_commands/cmd_new.s b/src/basic/basic_commands/cmd_new.s index e7d7189f..c726b527 100644 --- a/src/basic/basic_commands/cmd_new.s +++ b/src/basic/basic_commands/cmd_new.s @@ -9,4 +9,4 @@ cmd_new: // NEW command terminates execution (confirmed on a C64) - jmp shell_main_loop + jmp end_of_program diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index d5126f6f..f26eee42 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -91,4 +91,4 @@ cmd_print_done: // Execute next statement - jmp end_of_statement + rts diff --git a/src/basic/basic_commands/cmd_rem.s b/src/basic/basic_commands/cmd_rem.s index 1e5c113d..3247ab0f 100644 --- a/src/basic/basic_commands/cmd_rem.s +++ b/src/basic/basic_commands/cmd_rem.s @@ -7,4 +7,6 @@ cmd_rem: + pha + pha jmp execute_statements_end_of_line diff --git a/src/basic/basic_commands/cmd_restore.s b/src/basic/basic_commands/cmd_restore.s index 62d40846..6e67271e 100644 --- a/src/basic/basic_commands/cmd_restore.s +++ b/src/basic/basic_commands/cmd_restore.s @@ -3,10 +3,6 @@ // #LAYOUT# * * #IGNORE -cmd_restore: +// PLACEHOLDER for completeness - jumptable contains direct address - jsr do_restore - - // RESTORE command does not stop execution (confirmed on a C64) - - jmp end_of_statement +// RESTORE command does not stop execution (confirmed on a C64) diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index 4282ca1c..a960d05c 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -4,9 +4,15 @@ cmd_run: + // RUN clears all variables jsr do_clr + cmd_goto: + + // XXX optimize this: deduplicate last part (and init_oldtxt) with load/verify, + // if line number greater than current line - find line backwards + // Disable Kernal messages lda #$00 jsr JSETMSG @@ -24,4 +30,7 @@ cmd_goto: jmp do_UNDEFD_STATEMENT_error !: // Run it! + + pha + pha jmp execute_line diff --git a/src/basic/basic_commands/cmd_save.s b/src/basic/basic_commands/cmd_save.s index 5a944582..faee06a5 100644 --- a/src/basic/basic_commands/cmd_save.s +++ b/src/basic/basic_commands/cmd_save.s @@ -40,4 +40,4 @@ cmd_save_do: // entry point for BSAVE // Execute next statement - jmp end_of_statement \ No newline at end of file + rts diff --git a/src/basic/basic_commands/cmd_stop_end.s b/src/basic/basic_commands/cmd_stop_end.s index 3cf6f64c..2c87a33a 100644 --- a/src/basic/basic_commands/cmd_stop_end.s +++ b/src/basic/basic_commands/cmd_stop_end.s @@ -27,4 +27,4 @@ cmd_stop: cmd_end: - jmp shell_main_loop + jmp end_of_program diff --git a/src/basic/basic_commands/cmd_sys.s b/src/basic/basic_commands/cmd_sys.s index 16b5fbba..e1f7c001 100644 --- a/src/basic/basic_commands/cmd_sys.s +++ b/src/basic/basic_commands/cmd_sys.s @@ -60,10 +60,7 @@ cmd_sys_setup_call: plp // Call the routine. - jsr USRPOK - - jmp end_of_statement - + jmp USRPOK // // XXX Temporary ugly hack to support 'SYS PI*656' diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s index fa795621..6df67cdc 100644 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ b/src/basic/basic_commands_CC/cmd__jumptable_CC.s @@ -19,7 +19,7 @@ cmd_cold, cmd_clear, - cmd_dispose + varstr_garbage_collect // cmd_dispose ) diff --git a/src/basic/basic_commands_CC/cmd_bload_bverify.s b/src/basic/basic_commands_CC/cmd_bload_bverify.s index 615f3901..149e7caa 100644 --- a/src/basic/basic_commands_CC/cmd_bload_bverify.s +++ b/src/basic/basic_commands_CC/cmd_bload_bverify.s @@ -39,4 +39,4 @@ cmd_bload: // Execute next statement - jmp end_of_statement + rts diff --git a/src/basic/basic_commands_CC/cmd_clear.s b/src/basic/basic_commands_CC/cmd_clear.s index 76cf9f83..ef71e4ff 100644 --- a/src/basic/basic_commands_CC/cmd_clear.s +++ b/src/basic/basic_commands_CC/cmd_clear.s @@ -5,9 +5,6 @@ cmd_clear: - jsr clear_screen - - // Execute next statement - - jmp end_of_statement + // XXX in the future add separate implementation for graphics screen + jmp clear_screen diff --git a/src/basic/basic_commands_CC/cmd_cold.s b/src/basic/basic_commands_CC/cmd_cold.s index 345d26c6..be21a689 100644 --- a/src/basic/basic_commands_CC/cmd_cold.s +++ b/src/basic/basic_commands_CC/cmd_cold.s @@ -6,7 +6,9 @@ cmd_cold: jsr helper_ask_if_sure - bcs_16 end_of_statement + bcs !+ jsr JCLALL // for extra safety jmp (vector_reset) // hardware CPU vector +!: + rts \ No newline at end of file diff --git a/src/basic/basic_commands_CC/cmd_dispose.s b/src/basic/basic_commands_CC/cmd_dispose.s index 51b88bfa..cccb47e2 100644 --- a/src/basic/basic_commands_CC/cmd_dispose.s +++ b/src/basic/basic_commands_CC/cmd_dispose.s @@ -3,11 +3,4 @@ // #LAYOUT# * * #IGNORE -cmd_dispose: - - jsr varstr_garbage_collect - - // Execute next statement - - jmp end_of_statement - +// PLACEHOLDER for completeness - jumptable contains direct address diff --git a/src/basic/basic_commands_CC/cmd_merge.s b/src/basic/basic_commands_CC/cmd_merge.s index 376e19a8..dab2f34f 100644 --- a/src/basic/basic_commands_CC/cmd_merge.s +++ b/src/basic/basic_commands_CC/cmd_merge.s @@ -42,10 +42,6 @@ cmd_merge_got_params: cmd_merge_no_error: - // Relink loaded program, clear variables + // Relink loaded program, clear variables, execute next statement - jsr update_LINKPRG_VARTAB_do_clr - - // Execute next statement - - jmp end_of_statement + jmp update_LINKPRG_VARTAB_do_clr diff --git a/src/basic/basic_commands_CC/cmd_old.s b/src/basic/basic_commands_CC/cmd_old.s index 9b816edf..1eeca8e9 100644 --- a/src/basic/basic_commands_CC/cmd_old.s +++ b/src/basic/basic_commands_CC/cmd_old.s @@ -21,4 +21,4 @@ cmd_old: // Quit - jmp shell_main_loop + jmp end_of_program diff --git a/src/basic/basic_commands_CD/cmd_fast_slow.s b/src/basic/basic_commands_CD/cmd_fast_slow.s index ddc8ce70..e8b9ed5d 100644 --- a/src/basic/basic_commands_CD/cmd_fast_slow.s +++ b/src/basic/basic_commands_CD/cmd_fast_slow.s @@ -20,7 +20,7 @@ cmd_fast: lda #$41 sta CPU_D6510 - jmp end_of_statement + rts #elif CONFIG_MB_ULTIMATE_64 @@ -30,12 +30,12 @@ cmd_fast: cmd_slow: sta SCPU_SPEED_NORMAL - jmp end_of_statement + rts cmd_fast: sta SCPU_SPEED_TURBO - jmp end_of_statement + rts #elif CONFIG_PLATFORM_COMMODORE_64 @@ -60,13 +60,13 @@ cmd_fast: lda #$01 !: sta VIC_CLKRATE - jmp end_of_statement + rts #else cmd_slow: - nop // to prevent double label + nop // just to prevent double label // FALLTROUGH diff --git a/src/basic/editor/shell.s b/src/basic/editor/shell.s index 5d66c48b..d8482a9c 100644 --- a/src/basic/editor/shell.s +++ b/src/basic/editor/shell.s @@ -3,6 +3,14 @@ // #LAYOUT# * * #IGNORE +end_of_program: + + // Entry point for commands not wishing to continue + pha + pha + + // FALLTROUGH + shell_main_loop: // Tell user we are ready diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine/execute_line_statements.s index 51f34df4..fa8a23be 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine/execute_line_statements.s @@ -42,14 +42,24 @@ execute_statements: cmp #$7F bcc_16 execute_statements_var_assign // not a token - try variable assign - cmp #$A6 + // Move token code to .X + + tax + + // A token - first push the 'end_of_statement' address for RTS + + lda #>(end_of_statement - 1) + pha + lda #<(end_of_statement - 1) + pha + + cpx #$A6 bcs execute_statements_extended #if !HAS_OPCODES_65C02 // Get the jump table entry for it, push it on the stack, and then RTS to start it. - tax lda command_jumptable_hi - $80, x pha lda command_jumptable_lo - $80, x @@ -61,6 +71,7 @@ execute_statements: // Use jumptable to go to the command routine + txa asl tax jmp (command_jumptable, x) @@ -72,14 +83,14 @@ execute_statements_extended: // Support for extended BASIC commands - cmp #$CC + cpx #$CC beq execute_statements_CC - cmp #$CD + cpx #$CD beq execute_statements_CD // 'GO' command has a strange token, it is placed after function tokens - cmp #$CB + cpx #$CB beq_16 cmd_go jmp do_SYNTAX_error From d4d656add670c08856debdb98119f3a79e2f7ffd Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 10 Jul 2020 15:35:05 +0200 Subject: [PATCH 013/130] more work on garbage collector --- src/basic/engine/varstr_garbage_collect.s | 125 +++++++++++++++++++++- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 5d5b3adf..e1e5c1a5 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -116,13 +116,130 @@ varstr_garbage_collect_check_bptr: beq varstr_garbage_collect_unused // The back-pointer is not NULL - string is used - // Increase the string descriptor pointer by INDEX - // XXX implement this + // Setup 'memmove__size' - number of bytes to copy - // Move string memory up by INDEX + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # Date: Fri, 10 Jul 2020 17:01:04 +0200 Subject: [PATCH 014/130] started work on LET command --- src/aliases/,aliases_ram_lowmem.s | 2 +- src/basic/basic_commands/cmd__unimplemented.s | 2 - src/basic/basic_commands/cmd_let.s | 17 ++++ src/basic/engine/execute_line_statements.s | 23 ++--- src/basic/engine/fetch_variable.s | 84 +++++++++++++++++++ src/basic/engine/fetch_variable_is_09_AZ.s | 35 ++++++++ src/basic/engine/injest_assign.s | 27 ++++++ 7 files changed, 176 insertions(+), 14 deletions(-) create mode 100644 src/basic/basic_commands/cmd_let.s create mode 100644 src/basic/engine/fetch_variable.s create mode 100644 src/basic/engine/fetch_variable_is_09_AZ.s create mode 100644 src/basic/engine/injest_assign.s diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index 6468f572..5cdbda36 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -46,7 +46,7 @@ .label DATLIN = $3F // $3F-$40 -- NOT IMPLEMENTED -- .label DATPTR = $41 // $41-$42 pointer for READ/DATA copmmands .label INPPTR = $43 // $43-$44 -- NOT IMPLEMENTED -- - .label VARNAM = $45 // $45-$46 -- NOT IMPLEMENTED -- + .label VARNAM = $45 // $45-$46 current variable name .label VARPNT = $47 // $47-$48 -- NOT IMPLEMENTED -- .label FORPNT = $49 // $49-$4A -- NOT IMPLEMENTED -- .label OPPTR = $4B // $4B-$4C helper variable for expression computation, [!] our usage details are different diff --git a/src/basic/basic_commands/cmd__unimplemented.s b/src/basic/basic_commands/cmd__unimplemented.s index 6495feb6..ffa3d866 100644 --- a/src/basic/basic_commands/cmd__unimplemented.s +++ b/src/basic/basic_commands/cmd__unimplemented.s @@ -23,8 +23,6 @@ cmd_dim: nop cmd_read: nop -cmd_let: - nop cmd_if: nop cmd_gosub: diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s new file mode 100644 index 00000000..7150e9af --- /dev/null +++ b/src/basic/basic_commands/cmd_let.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + + +cmd_let: + + // Fetch variable name, should be followed by assign operator + + jsr fetch_variable + jsr injest_assign + bcs_16 do_SYNTAX_error + + // XXX finish the implementation + + jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine/execute_line_statements.s index fa8a23be..e63e952c 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine/execute_line_statements.s @@ -37,22 +37,22 @@ execute_statements: ldx #$19 stx TEMPPT - // Check if token is valid for execution - - cmp #$7F - bcc_16 execute_statements_var_assign // not a token - try variable assign - // Move token code to .X tax - // A token - first push the 'end_of_statement' address for RTS + // Push the 'end_of_statement' address for RTS lda #>(end_of_statement - 1) pha lda #<(end_of_statement - 1) pha + // Check if token is valid for execution + + cpx #$7F + bcc_16 execute_statements_var_assign // not a token - try variable assign + cpx #$A6 bcs execute_statements_extended @@ -243,17 +243,18 @@ execute_line: execute_statements_var_assign: - // XXX here we should handle variable assignments, probably in a separate file - // Prevent wedges from being executed within a program #if CONFIG_TAPE_WEDGE - cmp #$40 + cpx #$40 beq_16 do_DIRECT_MODE_ONLY_error #endif #if CONFIG_DOS_WEDGE - cmp #$5F + cpx #$5F beq_16 do_DIRECT_MODE_ONLY_error #endif - jmp do_SYNTAX_error + // Try variable assignment - execute as LET command + + jsr unconsume_character + jmp cmd_let diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s new file mode 100644 index 00000000..ce3e2430 --- /dev/null +++ b/src/basic/engine/fetch_variable.s @@ -0,0 +1,84 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +fetch_variable: + + // Fetch variable name + + lda #$00 + sta VARNAM+1 + + // Fetch the first character +!: + jsr fetch_character + cmp #$20 // ignore all the spaces + beq !- + + jsr fetch_variable_is_AZ + bcs_16 do_SYNTAX_error + + sta VARNAM+0 + + // Fetch the (optional) second character + + jsr fetch_character + jsr fetch_variable_is_09_AZ + bcs fetch_variable_check_type + + sta VARNAM+1 + + // Fetch the remaining variable characters - ignore them +!: + jsr fetch_character + jsr fetch_variable_is_09_AZ + bcc !- + + // FALLTROUGH + +fetch_variable_check_type: + + // Encode variable type within name, as documented in: + // - https://sites.google.com/site/h2obsession/CBM/basic/variable-format + + cmp #$24 // '$' + beq fetch_variable_type_string + cmp #$25 // '%' + beq fetch_variable_type_integer + + // FALLTORUGH + +fetch_variable_type_float: + + jsr unconsume_character + +#if HAS_OPCODES_65C02 + bra fetch_variable_find_addr +#else + jmp fetch_variable_find_addr +#endif + +fetch_variable_type_integer: + + lda VARNAM+0 + ora #$80 + sta VARNAM+0 + + // FALLTROUGH + +fetch_variable_type_string: + + lda VARNAM+1 + ora #$80 + sta VARNAM+1 + + // FALLTROUGH + +fetch_variable_find_addr: + + // Now try to find variable address + + // XXX + + rts diff --git a/src/basic/engine/fetch_variable_is_09_AZ.s b/src/basic/engine/fetch_variable_is_09_AZ.s new file mode 100644 index 00000000..9c1b1188 --- /dev/null +++ b/src/basic/engine/fetch_variable_is_09_AZ.s @@ -0,0 +1,35 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Check .A content, if within 0-9, A-Z ranges, sets Carry if check fails +// + +fetch_variable_is_09_AZ: + + cmp #$41 // fail if below '0' + bcc fetch_variable_cmp_fail + + cmp #$3A // continue checking if above '9' + bcc fetch_variable_cmp_rts + + // FALLTROUGH + +fetch_variable_is_AZ: + + cmp #$41 // fail if below 'A' + bcc fetch_variable_cmp_fail + + cmp #$7B // fail if above 'Z' + + // FALLTROUGH + +fetch_variable_cmp_rts: + + rts + +fetch_variable_cmp_fail: + + sec + rts diff --git a/src/basic/engine/injest_assign.s b/src/basic/engine/injest_assign.s new file mode 100644 index 00000000..c07898a7 --- /dev/null +++ b/src/basic/engine/injest_assign.s @@ -0,0 +1,27 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Consummes assign operator in a BASIC code, Carry set if not found. Injests all spaces. +// + + +injest_assign: + + jsr fetch_character + cmp #$B2 // assign operator character + beq injest_assign_found + cmp #$20 // space, can always be skipped + beq injest_assign + + // Not found + jsr unconsume_character + + sec + rts + +injest_assign_found: + + clc + rts From 50da40a4f1cf82ef8c9cc86206c5ad46345d3ac6 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 10 Jul 2020 20:34:52 +0200 Subject: [PATCH 015/130] documentation update --- doc/Extended-BASIC.md | 65 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index dcb12fe6..020c007f 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -80,3 +80,68 @@ Verify operation for the binary data starting from a given addres. NOTE: for now ### `BSAVE "file_name", device_number, start_address, end_address` Saves the binary data from the given memory area. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. + +# Planned BASIC features, when V2 compatibility is reached + +Ideas for the future, most of them suitable for Mega65 or other power machines only + +* sound support +* 2D graphics support +* turtle graphics +* sprite support, including collision callback +* custom character set support +* sprite/character design within program, in a way similar to Simons BASIC +* joystick/mouse/lightpen/paddle commands/functions +* matrix operations +* `DISPOSE` with variable/array as parameter should remove the variable/array from memory +* `BLOAD`, `BVERIFY` and `BSAVE` should have syntax compatible with BASIC V7/V10 +* it should be possible to intercept Kernal errors from BASIC (prevent `?FILE NOT FOUND ERROR IN ...`, etc.); `ON ERROR GOTO` ? +* support for numbers in hexadecimal and binary formats +* `CGOTO` and `CGOSUB` - computatiuonal versions, should accept expressions +* `LABEL`, `LGOTO` and `LGOSUB` - jump to label +* some kind of subroutines with local variable namespace, possibly loaded from disc (like in Warsaw Basic 3.2) +* for Mega65 mode, move variables to a separate memory area, consider extending variable name length +* DOS Wedge should ask (`ARE YOU SURE?`) before removing a file or formating the disc +* `←V` (verify from tape) - if Kernal is extended to offer this feature +* modulo function or opeerator +* `DPEEK`, `DPOKE`, `QPEEK`, `QPOKE` - 2/4 byte `PEEK` and `POKE` variants +* all the functions/commands accepting memory addresses should be able to access the whole Mega65 memory +* ability to limit memory used by basic to standard 38K or to 46K (memory model switch) +* `XOR` operator +* `AUTO` - line auto numbering +* `RENUMBER` for chanign the line numbers +* `IF ... THEN ... ELSE`, `BEGIN ... BEND` +* consider `BOOT` command +* possibly some commands for creating menus and dialog boxes +* more configurable `INPUT` +* `PRINT USING`, `PRINT AT(x, y)`, `PRINT CENTRE` +* `CURSOR` command from BASIC V10 +* `RESTORE` should accept lline number as argument +* hex/dec conversion functions +* `DELETE` command to delete several BASIC lines, as in BASIC V10 +* `FOR` loop should accept integer variable as index +* `FETCH`, `STASH`, `SWAP` - REU support +* `DMA` command for Mega65 +* geoRAM support +* `GO 64` / `GO 65` should enable/disable C64 compatibility mode on Mega65 +* `NSYS` for Mega65 - native `SYS` for Mega65, should not switch to C64 compatibilty mode +* `DO ... LOOP`, `DO ... UNTIL`, `DO ... WHILE`, `EXIT` +* `SEEK#` to read-and-forget n bytes +* `RECORD#` command from BASIC V10 +* `GETKEY` from BASIC V10 +* `HELP` command from BASIC V7/V10 +* function to find substring position +* `WINDOW` command from BASIC V7 +* functions to return cursor position +* `TRAP` and `RESUME` +* `SET DEF` and `SET DISK` from BASIC V10 +* `SLEEP` from BASIC V10 +* `TRON` / `TROFF` - program tracing +* `TYPE` command from BASIC V10 +* `RUN` should be able to run program from device, as in BASIC V10 +* `PAGE` and `DELAY` commands from Simons BASIC, or something similar +* `DUMP` command from Simons BASIC, or something similar +* function to insert a substring starting from given position +* function to generate string of n duplicated characters +* function to retrieve fractional part of a number +* command to fill text screen area with a character, inverse screen area, scroll, or change fg/bg color of screen area From 6e90102f76d11e81371705e7c2c121107bd5a2d8 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 11 Jul 2020 20:08:36 +0200 Subject: [PATCH 016/130] more work on variables support --- src/aliases/,aliases_ram_lowmem.s | 2 +- src/basic/basic_commands/cmd_let.s | 67 +++++++++ src/basic/engine/fetch_variable.s | 131 +++++++++++++++++- src/basic/engine/varstr_garbage_collect.s | 8 -- .../memory/under_rom_peek_poke_46k_50k.s | 17 +++ 5 files changed, 214 insertions(+), 11 deletions(-) diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index 5cdbda36..d673f7bc 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -47,7 +47,7 @@ .label DATPTR = $41 // $41-$42 pointer for READ/DATA copmmands .label INPPTR = $43 // $43-$44 -- NOT IMPLEMENTED -- .label VARNAM = $45 // $45-$46 current variable name - .label VARPNT = $47 // $47-$48 -- NOT IMPLEMENTED -- + .label VARPNT = $47 // $47-$48 current variable/descriptor pointer .label FORPNT = $49 // $49-$4A -- NOT IMPLEMENTED -- .label OPPTR = $4B // $4B-$4C helper variable for expression computation, [!] our usage details are different .label OPMASK = $4D // -- NOT IMPLEMENTED -- diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 7150e9af..2482dfdb 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -12,6 +12,73 @@ cmd_let: jsr injest_assign bcs_16 do_SYNTAX_error + // Determine variable type and push it to the stack + + lda #$00 + clc + bit VARNAM+0 + bpl !+ + adc #$01 +!: + bit VARNAM+1 + bpl !+ + adc #$80 +!: + pha + + // Push the VARPNT to the stack - it might get overridden + + lda VARPNT+0 + pha + lda VARPNT+1 + pha + + // Evaluate the expression + + jsr FRMEVL + + // Restore VARPNT + + pla + sta VARPNT+1 + pla + sta VARPNT+0 + + // Determine what to assign + + pla + bmi cmd_let_assign_string + beq cmd_let_assign_float + + // FALLTROUGH + + // XXX integer and float probably have much in common + +cmd_let_assign_integer: + + lda VALTYP + bmi_16 do_TYPE_MISMATCH_error + + // XXX finish the implementation + + jmp do_NOT_IMPLEMENTED_error + +cmd_let_assign_float: + + lda VALTYP + bmi_16 do_TYPE_MISMATCH_error + + // XXX finish the implementation + + jmp do_NOT_IMPLEMENTED_error + +cmd_let_assign_string: + + // Check if value type matches + + lda VALTYP + bpl_16 do_TYPE_MISMATCH_error + // XXX finish the implementation jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index ce3e2430..9397711d 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -77,8 +77,135 @@ fetch_variable_type_string: fetch_variable_find_addr: - // Now try to find variable address + // Now try to find variable address between VARTAB and ARYTAB, see + // - https://www.c64-wiki.com/wiki/Memory_(BASIC) + + lda VARTAB+0 + sta VARPNT+0 + lda VARTAB+1 + sta VARPNT+1 + + // FALLTROUGH + +fetch_variable_find_addr_loop: + + // Check if end of search loop + + lda VARPNT+1 + cmp ARYTAB+1 + bne !+ + lda VARPNT+0 + cmp VARPNT+0 + beq fetch_variable_alocate +!: + // Compare current variable name with searched one + // XXX consider creating optimized version for 46K/50K memory models + + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # Date: Sun, 12 Jul 2020 06:13:04 +0200 Subject: [PATCH 017/130] added test command to display memory information --- doc/Extended-BASIC.md | 61 +++++++----- .../basic_commands_CC/cmd__jumptable_CC.s | 3 +- src/basic/basic_commands_CC/cmd_mem.s | 98 +++++++++++++++++++ .../basic_commands_CC/helper_mem_tab_str.s | 17 ++++ .../basic_commands_CC/helper_mem_tab_x.s | 17 ++++ .../basic_commands_CC/helper_mem_tab_y.s | 17 ++++ .../board_m65/4000.mega65_vectable_basic_1.s | 2 + src/basic/board_m65/mega65_imports.s | 3 +- src/basic/engine/do_error.s | 22 +++++ tools/generate_strings.cc | 21 ++-- 10 files changed, 227 insertions(+), 34 deletions(-) create mode 100644 src/basic/basic_commands_CC/cmd_mem.s create mode 100644 src/basic/basic_commands_CC/helper_mem_tab_str.s create mode 100644 src/basic/basic_commands_CC/helper_mem_tab_x.s create mode 100644 src/basic/basic_commands_CC/helper_mem_tab_y.s diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 020c007f..29f27e61 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -39,31 +39,7 @@ Like above, but merges a BASIC program to the one already stored in memory. Launches a built-in tape head alignment tool. Destroys program in memory. Press `RUN/STOP` to terminate the tool. -## Additional BASIC commands - -### `COLD` - -Resets the machine. In direct mode asks for confirmation first. - -### `FAST` - -Tries to switch the machine to turbo mode - details differ depending on the configured machine / motherboard. - -### `SLOW` - -Tries to switch the machine back to 1 MHz operation mode. - -### `OLD` - -Tries to restore program destroyed by `NEW` or a reset. - -### `CLEAR` - -Clears the screen content. - -### `DISPOSE` - -Runs the garbage collector - disposes outdated strings. +## Additional BASIC commands - I/O ### `MERGE "file_name" [, device_number]` @@ -81,6 +57,41 @@ Verify operation for the binary data starting from a given addres. NOTE: for now Saves the binary data from the given memory area. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. +## Additional BASIC commands - misc + +### `COLD` + +Resets the machine. In direct mode asks for confirmation first. + +### `FAST` + +Tries to switch the machine to turbo mode - details differ depending on the configured machine / motherboard. + +### `SLOW` + +Tries to switch the machine back to 1 MHz operation mode. + +### `OLD` + +Tries to restore program destroyed by the `NEW` command or a reset. + +### `MEM` + +Displays BASIC memory usage information: +* `TXT` - size of BASIC program text, always at least 2 bytes are used +* `VAR` - bytes occupied by float and integer variables, string variable descriptors, and function descriptors +* `ARR` - bytes occupied by arrays (note: for string arrays only descriptors are stored here) +* `STR` - bytes occupied by strings, also the ones belonging to arrays +* `SPC` - unused space + +### `CLEAR` + +Clears the screen content. + +### `DISPOSE` + +Runs the garbage collector - disposes outdated strings. + # Planned BASIC features, when V2 compatibility is reached Ideas for the future, most of them suitable for Mega65 or other power machines only diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s index 6df67cdc..68245e36 100644 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ b/src/basic/basic_commands_CC/cmd__jumptable_CC.s @@ -19,7 +19,8 @@ cmd_cold, cmd_clear, - varstr_garbage_collect // cmd_dispose + varstr_garbage_collect, // cmd_dispose + cmd_mem ) diff --git a/src/basic/basic_commands_CC/cmd_mem.s b/src/basic/basic_commands_CC/cmd_mem.s new file mode 100644 index 00000000..1a1fe5be --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_mem.s @@ -0,0 +1,98 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + + +#if (!ROM_LAYOUT_M65 || SEGMENT_BASIC_0) + +cmd_mem: + + // First perform the garbage collection - to be able to determine real values + + jsr varstr_garbage_collect + +#endif // ROM layout + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__cmd_mem_cont + jmp map_NORMAL + +#else + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_1) + +cmd_mem_cont: + +#endif + + // Print all the information, in a loop, in reverse order + + ldy #$04 +!: + // First print the information string + + ldx helper_mem_tab_str, y + phy_trash_a + jsr print_packed_misc_str + + // Fetch addresses of zeropage variables + +#if HAS_OPCODES_65C02 + ply + phy +#else + pla + pha + tay +#endif + + ldx helper_mem_tab_x, y + lda helper_mem_tab_y, y + tay + + // Print difference between two zeropage variables + + sec + lda $00, x + sbc $0000, y + pha + inx + iny + lda $00, x + sbc $0000, y + +#if HAS_OPCODES_65C02 + plx +#else + tay + pla + tax + tya +#endif + + // Before printing, make sure the result is not negative + + bcc cmd_mem_error + jsr print_integer + + // Check if more iterations needed + + ply_trash_a + dey + bpl !- + + // Finish + + jmp print_return + + +cmd_mem_error: + + jsr print_return + jmp do_MEMORY_CORRUPT_error + +#endif // ROM layout diff --git a/src/basic/basic_commands_CC/helper_mem_tab_str.s b/src/basic/basic_commands_CC/helper_mem_tab_str.s new file mode 100644 index 00000000..816add66 --- /dev/null +++ b/src/basic/basic_commands_CC/helper_mem_tab_str.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper table for 'MEM' command - list of strings to print +// + + +helper_mem_tab_str: + + .byte IDX__STR_MEM_FREE + .byte IDX__STR_MEM_STRS + .byte IDX__STR_MEM_ARRS + .byte IDX__STR_MEM_VARS + .byte IDX__STR_MEM_TEXT diff --git a/src/basic/basic_commands_CC/helper_mem_tab_x.s b/src/basic/basic_commands_CC/helper_mem_tab_x.s new file mode 100644 index 00000000..2df7e5f9 --- /dev/null +++ b/src/basic/basic_commands_CC/helper_mem_tab_x.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper table for 'MEM' command - list of minuend zeropage variables +// + + +helper_mem_tab_x: + + .byte FRETOP + .byte MEMSIZ + .byte STREND + .byte ARYTAB + .byte VARTAB diff --git a/src/basic/basic_commands_CC/helper_mem_tab_y.s b/src/basic/basic_commands_CC/helper_mem_tab_y.s new file mode 100644 index 00000000..74861e4a --- /dev/null +++ b/src/basic/basic_commands_CC/helper_mem_tab_y.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper table for 'MEM' command - list of subtrahend zeropage variables +// + + +helper_mem_tab_y: + + .byte STREND + .byte FRETOP + .byte ARYTAB + .byte VARTAB + .byte TXTTAB diff --git a/src/basic/board_m65/4000.mega65_vectable_basic_1.s b/src/basic/board_m65/4000.mega65_vectable_basic_1.s index d83bbfdd..2f116b08 100644 --- a/src/basic/board_m65/4000.mega65_vectable_basic_1.s +++ b/src/basic/board_m65/4000.mega65_vectable_basic_1.s @@ -20,6 +20,7 @@ .label VB1__do_new = $4000 + 2 * 6 .label VB1__do_clr = $4000 + 2 * 7 .label VB1__do_restore = $4000 + 2 * 8 + .label VB1__cmd_mem_cont = $4000 + 2 * 9 #else @@ -34,5 +35,6 @@ .word do_new .word do_clr .word do_restore + .word cmd_mem_cont #endif diff --git a/src/basic/board_m65/mega65_imports.s b/src/basic/board_m65/mega65_imports.s index 210dac22..ac3d8582 100644 --- a/src/basic/board_m65/mega65_imports.s +++ b/src/basic/board_m65/mega65_imports.s @@ -22,5 +22,6 @@ #if CONFIG_SHOW_FEATURES .label print_features = BASIC_0.proxy_B1_print_features #endif -.label do_STRING_TOO_LONG_error = BASIC_0.do_STRING_TOO_LONG_error +.label do_error_fetch = BASIC_0.do_error_fetch +.label do_basic_error = BASIC_0.do_basic_error .label str_rev_question = BASIC_0.str_rev_question diff --git a/src/basic/engine/do_error.s b/src/basic/engine/do_error.s index e4979e86..c8d51e0a 100644 --- a/src/basic/engine/do_error.s +++ b/src/basic/engine/do_error.s @@ -1,4 +1,5 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -43,7 +44,11 @@ do_kernal_error: // .A = KERNAL error code, also almost ma beq do_BREAK_error // XXX is 0 really a proper error code? dex +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_1) + jmp do_basic_error +#else bpl do_basic_error // branch always +#endif // Error messages specific to OpenROMs BASIC dialect @@ -138,6 +143,16 @@ do_FILE_OPEN_error: do_TO_MANY_FILES_error: .byte $EA +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_1) + + jmp do_error_fetch + +#else + + // FALLTROUGH + +do_error_fetch: + // Now get the error id and restore $E6 to its correct value lda $E6 @@ -162,6 +177,11 @@ do_TO_MANY_FILES_error: do_basic_error: // error code in .X +#if ROM_LAYOUT_M65 + // Make sure we are back with normal memory map + jsr map_NORMAL +#endif + // "?" phx_trash_a @@ -197,3 +217,5 @@ do_basic_error: // error code in .X txs jmp shell_main_loop + +#endif // ROM layout diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index dc308b79..62075488 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -186,6 +186,7 @@ const StringEntryList GLOBAL_Keywords_CC = { ListType::KEYWORDS, "keywords_CC", { true, true, true, true, "KCC_06", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) { true, true, true, true, "KCC_07", "CLEAR", }, // Not present in CBM BASIC dialects, OpenROMs specific { true, true, true, true, "KCC_08", "DISPOSE", }, // Not present in CBM BASIC dialects, OpenROMs specific + { true, true, true, true, "KCC_09", "MEM", }, // Not present in CBM BASIC dialects, OpenROMs specific // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c } }; @@ -310,14 +311,20 @@ const StringEntryList GLOBAL_Errors = { ListType::STRINGS_BASIC, "errors", const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", { // STD M65 U64 X16 --- misc strings as on CBM machines - { true, true, true, true, "STR_RET_QM", "\r?" }, - { true, true, true, true, "STR_BYTES", " BASIC BYTES FREE" }, // https://github.com/stefanhaustein/expressionparser - { true, true, true, true, "STR_READY", "\rREADY.\r" }, // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser - { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html - { true, true, true, true, "STR_IN", " IN " }, - { true, true, true, true, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm + { true, true, true, true, "STR_RET_QM", "\r?" }, + { true, true, true, true, "STR_BYTES", " BASIC BYTES FREE" }, // https://github.com/stefanhaustein/expressionparser + { true, true, true, true, "STR_READY", "\rREADY.\r" }, // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser + { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html + { true, true, true, true, "STR_IN", " IN " }, + { true, true, true, true, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm // STD M65 U64 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs - { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, + { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, + { true, true, true, true, "STR_MEM_TEXT", "\rTXT: " }, + { true, true, true, true, "STR_MEM_VARS", "\rVAR: " }, + { true, true, true, true, "STR_MEM_ARRS", "\rARR: " }, + { true, true, true, true, "STR_MEM_STRS", "\rSTR: " }, + { true, true, true, true, "STR_MEM_FREE", "\r\rSPC: " }, + // Note: depending on configuration, additional strings will be added here } }; From 2b5c01d3bb7385658a721fd0cc53b266a8f66f75 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 08:44:08 +0200 Subject: [PATCH 018/130] new 'print_integer' routine, nearly 120 bytes shorter --- src/basic/print/print_integer.s | 182 +++++++----------------- src/basic/print/print_integer_compare.s | 18 +++ src/basic/print/print_integer_tab_hi.s | 15 ++ src/basic/print/print_integer_tab_lo.s | 15 ++ 4 files changed, 103 insertions(+), 127 deletions(-) create mode 100644 src/basic/print/print_integer_compare.s create mode 100644 src/basic/print/print_integer_tab_hi.s create mode 100644 src/basic/print/print_integer_tab_lo.s diff --git a/src/basic/print/print_integer.s b/src/basic/print/print_integer.s index 72c0f68a..ba317081 100644 --- a/src/basic/print/print_integer.s +++ b/src/basic/print/print_integer.s @@ -2,147 +2,75 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE +// // Works similar to $BDCD in original C64 BASIC -// XXX Should eventually get replaced by a more flexible and optimal routine. -// Temp result gets written to $0100-$0104 +// print_integer: - pha - phx_trash_a + // Tested with original C64 ROMs, that it trashes FAC1 too - // Clear temporary output - lda #$00 - ldy #5 -!: sta $0100,y - dey - bpl !- - - pla - ldy #23 // 8 x 3 - 1 = offset of last digit of 128 -lo_loop: - cmp #$7f - bcc bit_clear + sta FAC1_exponent+1 + stx FAC1_exponent+0 - // Bit set, so add the digits - pha - ldx #2 - clc -lo_add_loop: - lda $0102,x - adc number_table_lo,y - sta $0102,x + // Check for 0 + + ora FAC1_exponent+0 + bne print_integer_not_0 + + // Just print '0' and quit + + lda #$30 + jmp JCHROUT + +print_integer_not_0: + + // Try to find the index of the first digit + + ldy #$04 +!: + jsr print_integer_compare + bcs print_integer_digit dey - dex - bpl lo_add_loop - pla - jmp next_lo_bit - -bit_clear: - dey - dey - dey -next_lo_bit: - asl - cpy #$7f - bcc lo_loop + bpl !- // branch always +print_integer_digit: - // Now do the same for upper byte - pla - - ldy #39 // 8 x 5 - 1 = offset of last digit of 32768 -hi_loop: - cmp #$7f - bcc bit_clear_hi + // Determine digit to print - - // Bit set, so add the digits - pha - ldx #4 - clc -hi_add_loop: - lda $0100,x - adc number_table_hi,y - sta $0100,x - - dey - dex - bpl hi_add_loop - pla - jmp next_hi_bit - -bit_clear_hi: - dey - dey - dey - dey - dey -next_hi_bit: - asl - cpy #$7f - bcc hi_loop - -fix_carry: - - // Deal with any carries - ldx #3 -carry_fix_loop: - lda $0101,x - cmp #10 + ldx #$00 +!: + jsr print_integer_compare bcc !+ - inc $0100,x + + // Raise digit, lower the integer + + inx + sec - sbc #10 - sta $0101,x + lda FAC1_exponent+0 + sbc print_integer_tab_lo, y + sta FAC1_exponent+0 + lda FAC1_exponent+1 + sbc print_integer_tab_hi, y + sta FAC1_exponent+1 + + bcs !- // branch always +!: + // Convert digit in .X to PETSCII in .A and print it out - jmp carry_fix_loop + txa + clc + adc #$30 -!: dex - bpl carry_fix_loop - -post_carry: - - // Got digits. - // Skip leading zeros, and print the resulting number - - // Skip leading zeros - ldy #0 -!: lda $0100,y - bne found_start_of_number - iny - cpy #4 - bne !- - -found_start_of_number: - // Print digits -!: lda $0100,y - ora #$30 jsr JCHROUT - iny - cpy #5 - bne !- - - + + // Check if next iteration is needed + + dey + bpl print_integer_digit + + // The end + rts - - -number_table_lo: - .byte 0,0,1 - .byte 0,0,2 - .byte 0,0,4 - .byte 0,0,8 - .byte 0,1,6 - .byte 0,3,2 - .byte 0,6,4 - .byte 1,2,8 -number_table_hi: - .byte 0,0,2,5,6 - .byte 0,0,5,1,2 - .byte 0,1,0,2,4 - .byte 0,2,0,4,8 - .byte 0,4,0,9,6 - .byte 0,8,1,9,2 - .byte 1,6,3,8,4 - .byte 3,2,7,6,8 diff --git a/src/basic/print/print_integer_compare.s b/src/basic/print/print_integer_compare.s new file mode 100644 index 00000000..42abd51b --- /dev/null +++ b/src/basic/print/print_integer_compare.s @@ -0,0 +1,18 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper compare subroutine for 'print_integer' +// + +print_integer_compare: + + lda FAC1_exponent+1 + cmp print_integer_tab_hi, y + bne !+ + + lda FAC1_exponent+0 + cmp print_integer_tab_lo, y +!: + rts diff --git a/src/basic/print/print_integer_tab_hi.s b/src/basic/print/print_integer_tab_hi.s new file mode 100644 index 00000000..dc36bd01 --- /dev/null +++ b/src/basic/print/print_integer_tab_hi.s @@ -0,0 +1,15 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper power of 10s table (high buytes) for 'print_integer' +// + +print_integer_tab_hi: + + .byte >1 + .byte >10 + .byte >100 + .byte >1000 + .byte >10000 diff --git a/src/basic/print/print_integer_tab_lo.s b/src/basic/print/print_integer_tab_lo.s new file mode 100644 index 00000000..47fef0ec --- /dev/null +++ b/src/basic/print/print_integer_tab_lo.s @@ -0,0 +1,15 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper power of 10s table (low buytes) for 'print_integer' +// + +print_integer_tab_lo: + + .byte <1 + .byte <10 + .byte <100 + .byte <1000 + .byte <10000 From d1ac8ac371083193934095c6a75b460c8de1a5f9 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 10:22:32 +0200 Subject: [PATCH 019/130] new line number parser, saved over 150 bytes --- src/basic/basic_commands/cmd_run_goto.s | 2 +- src/basic/basic_commands/cmd_sys.s | 2 +- .../helper_bload_fetch_address.s | 2 +- src/basic/basic_parse_line_number.s | 31 ---- src/basic/editor/shell.s | 2 +- src/basic/engine/convert_PETSCII_to_digit.s | 21 +++ src/basic/engine/fetch_line_number.s | 99 +++++++++++ src/basic/engine/fetch_uint8.s | 2 +- src/basic/engine/fetch_variable.s | 6 +- src/basic/engine/fetch_variable_is_09_AZ.s | 35 ---- src/basic/engine/is_alphanumeric.s | 38 +++++ src/basic/fac1_mul.s | 101 ------------ src/basic/injest_number.s | 156 ------------------ src/basic/wedge/wedge_dos.s | 2 +- 14 files changed, 167 insertions(+), 332 deletions(-) delete mode 100644 src/basic/basic_parse_line_number.s create mode 100644 src/basic/engine/convert_PETSCII_to_digit.s create mode 100644 src/basic/engine/fetch_line_number.s delete mode 100644 src/basic/engine/fetch_variable_is_09_AZ.s create mode 100644 src/basic/engine/is_alphanumeric.s delete mode 100644 src/basic/fac1_mul.s delete mode 100644 src/basic/injest_number.s diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index a960d05c..a2f0bb10 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -23,7 +23,7 @@ cmd_goto: jsr end_of_statement_check bcs !+ - jsr basic_parse_line_number + jsr fetch_line_number jsr find_line bcc !+ // Line does not exist, so report error diff --git a/src/basic/basic_commands/cmd_sys.s b/src/basic/basic_commands/cmd_sys.s index e1f7c001..258e1c25 100644 --- a/src/basic/basic_commands/cmd_sys.s +++ b/src/basic/basic_commands/cmd_sys.s @@ -41,7 +41,7 @@ cmd_sys_hack_not_needed: // XXX End of hack // - jsr basic_parse_line_number + jsr fetch_line_number cmd_sys_setup_call: lda #$4C // JMP opcode diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_address.s b/src/basic/basic_commands_CC/helper_bload_fetch_address.s index f5fca8f6..a470e974 100644 --- a/src/basic/basic_commands_CC/helper_bload_fetch_address.s +++ b/src/basic/basic_commands_CC/helper_bload_fetch_address.s @@ -12,7 +12,7 @@ helper_bload_fetch_address: jsr injest_comma bcs_16 do_SYNTAX_error - jsr basic_parse_line_number // XXX detect errors here + jsr fetch_line_number // XXX detect errors here ldx LINNUM+0 ldy LINNUM+1 diff --git a/src/basic/basic_parse_line_number.s b/src/basic/basic_parse_line_number.s deleted file mode 100644 index 3e8b8ce7..00000000 --- a/src/basic/basic_parse_line_number.s +++ /dev/null @@ -1,31 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - - -basic_parse_line_number: - - jsr injest_number - - // Check if the number is a valid line number - // i.e., 16 bits, no exponent, no decimal - lda FAC1_mantissa+2 - ora FAC1_mantissa+3 - ora FAC1_exponent - beq !+ -ml_bad_line_number: - // Invalid line number - jmp do_ILLEGAL_QUANTITY_error -!: - // Line number are not allowed to have decimal points in them - lda __tokenise_work4 - cmp #$FF - bne ml_bad_line_number - - // Got a valid line number. - lda FAC1_mantissa+0 - sta LINNUM+0 - lda FAC1_mantissa+1 - sta LINNUM+1 - clc - rts diff --git a/src/basic/editor/shell.s b/src/basic/editor/shell.s index d8482a9c..3634e177 100644 --- a/src/basic/editor/shell.s +++ b/src/basic/editor/shell.s @@ -142,7 +142,7 @@ shell_process_line: lda #>BUF sta TXTPTR+1 - jsr basic_parse_line_number + jsr fetch_line_number // Get pointer to next char lda TXTPTR+0 diff --git a/src/basic/engine/convert_PETSCII_to_digit.s b/src/basic/engine/convert_PETSCII_to_digit.s new file mode 100644 index 00000000..97f7c335 --- /dev/null +++ b/src/basic/engine/convert_PETSCII_to_digit.s @@ -0,0 +1,21 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tries to convert PETSCII in .A to a digit (0-9 values), sets Carry to indicate failure +// + +convert_PETSCII_to_digit: + + sec + sbc #$30 + bcc convert_PETSCII_to_digit_fail + + cmp #$0A + rts + +convert_PETSCII_to_digit_fail: + + sec + rts diff --git a/src/basic/engine/fetch_line_number.s b/src/basic/engine/fetch_line_number.s new file mode 100644 index 00000000..21e998fa --- /dev/null +++ b/src/basic/engine/fetch_line_number.s @@ -0,0 +1,99 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches line number, stores it in LINNUM, sets Carry to indicate failure (not a number), prints SYNTAX ERROR if above 65535 +// +// Preserves both .X and .Y +// + +fetch_line_number: + + // Fetch the first character (skip spaces), check if 0-9 + + jsr fetch_character + cmp #$20 + beq fetch_line_number + + jsr convert_PETSCII_to_digit + bcs fetch_line_number_rts + + // First character seems to be correct - store it + + sta LINNUM+0 + lda #$00 + sta LINNUM+1 + + // FALLTROUGH + +fetch_line_number_loop: + + // Try to fetch another digit + + jsr fetch_character + jsr convert_PETSCII_to_digit + bcs fetch_line_number_end + + // We got another digit - store it + + pha + + // Multiply current LINNUM by 10 (x * 10 = (x * 2) + (x * 2) * 4) + + jsr fetch_line_number_mul_LINNUM_2 + + lda LINNUM+1 + pha + lda LINNUM+0 + pha + + jsr fetch_line_number_mul_LINNUM_2 + jsr fetch_line_number_mul_LINNUM_2 + + clc + pla + adc LINNUM+0 + sta LINNUM+0 + pla + adc LINNUM+1 + sta LINNUM+1 + bcs_16 do_SYNTAX_error + + // Add the new digit to LINNUM + + pla + clc + adc LINNUM+0 + sta LINNUM+0 + lda LINNUM+1 + adc #$00 + sta LINNUM+1 + bcs_16 do_SYNTAX_error + + // Next iteration + +#if HAS_OPCODES_65C02 + bra fetch_line_number_loop +#else + jmp fetch_line_number_loop +#endif + +fetch_line_number_end: + + jsr unconsume_character + clc + + // FALLTROUGH + +fetch_line_number_rts: + + rts + +fetch_line_number_mul_LINNUM_2: + + asl LINNUM+0 + rol LINNUM+1 + bcs_16 do_SYNTAX_error + + rts diff --git a/src/basic/engine/fetch_uint8.s b/src/basic/engine/fetch_uint8.s index 1637b056..3d92fa6b 100644 --- a/src/basic/engine/fetch_uint8.s +++ b/src/basic/engine/fetch_uint8.s @@ -17,7 +17,7 @@ fetch_coma_uint8: fetch_uint8: jsr injest_spaces - jsr basic_parse_line_number // XXX detect errors here + jsr fetch_line_number // XXX detect errors here lda LINNUM+1 bne_16 do_ILLEGAL_QUANTITY_error lda LINNUM+0 diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index 9397711d..9dc6438a 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -16,7 +16,7 @@ fetch_variable: cmp #$20 // ignore all the spaces beq !- - jsr fetch_variable_is_AZ + jsr is_AZ bcs_16 do_SYNTAX_error sta VARNAM+0 @@ -24,7 +24,7 @@ fetch_variable: // Fetch the (optional) second character jsr fetch_character - jsr fetch_variable_is_09_AZ + jsr is_09_AZ bcs fetch_variable_check_type sta VARNAM+1 @@ -32,7 +32,7 @@ fetch_variable: // Fetch the remaining variable characters - ignore them !: jsr fetch_character - jsr fetch_variable_is_09_AZ + jsr is_09_AZ bcc !- // FALLTROUGH diff --git a/src/basic/engine/fetch_variable_is_09_AZ.s b/src/basic/engine/fetch_variable_is_09_AZ.s deleted file mode 100644 index 9c1b1188..00000000 --- a/src/basic/engine/fetch_variable_is_09_AZ.s +++ /dev/null @@ -1,35 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Check .A content, if within 0-9, A-Z ranges, sets Carry if check fails -// - -fetch_variable_is_09_AZ: - - cmp #$41 // fail if below '0' - bcc fetch_variable_cmp_fail - - cmp #$3A // continue checking if above '9' - bcc fetch_variable_cmp_rts - - // FALLTROUGH - -fetch_variable_is_AZ: - - cmp #$41 // fail if below 'A' - bcc fetch_variable_cmp_fail - - cmp #$7B // fail if above 'Z' - - // FALLTROUGH - -fetch_variable_cmp_rts: - - rts - -fetch_variable_cmp_fail: - - sec - rts diff --git a/src/basic/engine/is_alphanumeric.s b/src/basic/engine/is_alphanumeric.s new file mode 100644 index 00000000..44c61a46 --- /dev/null +++ b/src/basic/engine/is_alphanumeric.s @@ -0,0 +1,38 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Check .A content, if within 0-9, A-Z ranges, sets Carry if check fails +// + + +is_09_AZ: + + jsr is_AZ + bcs is_09 + rts + + +is_09: + + cmp #$30 // if below '0' - check failed + bcc is_alphanumeric_fail + + cmp #$3A // if above '9' - check failed + rts + + +is_AZ: + + cmp #$41 // if below 'A' - check failed + bcc is_alphanumeric_fail + + cmp #$7B // if above 'Z' - check failed + rts + + +is_alphanumeric_fail: + + sec + rts diff --git a/src/basic/fac1_mul.s b/src/basic/fac1_mul.s deleted file mode 100644 index b69f9714..00000000 --- a/src/basic/fac1_mul.s +++ /dev/null @@ -1,101 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// Multiply Floating Point Accumulator by 10 -// = 8x + 2x -// Implement by shifting MAC left one bit, -// and then keeping that value to add on after -// shifting two more bits left. -// This should be done using BITS to -// hold the overflow bits, so that the result can -// be exponent adjusted after, if required. - -fac1_mul10: - lda #$00 - sta BITS - - // Multiply mantissa by 2 - jsr fac1_mantissa_mul2 - - // copy down to BASIC numeric work area at $57 - // (TEMPF1) - // (We copy all 7 bytes off the FAC1, so that we have - // the overflow bits, and the copy is as small as possible) - ldx #7 -f1m10_l1: - lda FAC1_mantissa,x - sta TEMPF1,x - dex - bpl f1m10_l1 - - // Multiply mantissa by 4, so it is now 8x original - jsr fac1_mantissa_mul2 - jsr fac1_mantissa_mul2 - - // Now add stored value of 2x to it, to get the total x10 - ldy #3 - ldx #0 - clc -f1m10_l2: - lda FAC1_mantissa,x - adc TEMPF1,x - sta FAC1_mantissa,x - inx - dey - bpl f1m10_l2 - lda BITS - adc TEMPF1+7 - sta BITS - - // Now shift right and increase exponent until overflow - // bits = $00 -f1m10_l3: - lda BITS - bne !+ - // All done, return - clc - rts -!: - // Divide mantissa by two, and increment exponent - jsr fac1_mantissa_div2 - inc FAC1_exponent - lda FAC1_exponent - bpl f1m10_l3 - // Exponent has bit 7 set, so has wrapped. - // = OVERFLOW ERROR - jmp do_OVERFLOW_error - -fac1_mantissa_mul2: - ldy #3 - ldx #0 - clc -f1m1_l1: - // Multiply mantissa by 2, and store overflow - // in FAC1_bits - lda FAC1_mantissa,x - rol - sta FAC1_mantissa,x - inx - dey - bpl f1m1_l1 - lda BITS - rol - sta BITS - - rts - -fac1_mantissa_div2: - // Divide mantissa by 2, including using overflow bits - clc - lda BITS - ror - sta BITS - ldy #3 -f1md2_l1: - lda FAC1_mantissa,y - ror - sta FAC1_mantissa,y - dey - bpl f1md2_l1 - rts diff --git a/src/basic/injest_number.s b/src/basic/injest_number.s deleted file mode 100644 index 7cd5ff02..00000000 --- a/src/basic/injest_number.s +++ /dev/null @@ -1,156 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - - -// Parse a number from the input buffer at (TXTPTR) -// Result is put into FAC1. -// TXTPTR is updated with first position after the number. - -// XXX - Remember decimal position and exponent, and apply them -// after to produce normalised floating point number. - -// XXX - Does not use routines to access memory under ROMs etc. -// This is important, because this routine operates on numbers in BASIC text. - -ij_not_a_digit: - // XXX check for "." or "E" - // Other chars terminate the accumulation. - - // Look for exponentiation marker - // XXX - Implement me! - // Probably should have a flag so that we know if we are accumulating - // exponent or mantissa digits - - // Look for decimal point - cmp #$2e - bne ij_not_decimal - lda __tokenise_work4 - cmp #$ff - beq ij_found_decimal - // More than one decimal point in a number means we have reached the end of the number - clc - rts - -ij_found_decimal: - // Found decimal. - // Thus start counting digits after the decimal, so that we - // can do the necessary number of divide by 10s on the final - // number. - lda #$00 - sta __tokenise_work4 - - jmp ij_consider_next_digit - -ij_not_decimal: - - clc - rts - -injest_number: - // Clear FAC1 - jsr erase_fac1 - - // Clear decimal position flag - lda #$ff - sta __tokenise_work4 - - // Check if leading char is a - sign - // Note: the - will have been tokenised to $AB - // XXX - implement - ldy #$00 - lda (TXTPTR),y - cmp #$AB - bne ij_loop1 // not minus - - // Set sign to negative - lda #$ff - sta FAC1_sign - - // Skip over the minus sign - jsr consume_character - -ij_loop1: - ldy #$00 - lda (TXTPTR),y - cmp #$30 - bcc ij_not_a_digit - cmp #$3a - bcs ij_not_a_digit - - // It is a digit - - // Only add digit if we have not overflowed the accuracy of - // the mantissa - lda FAC1_exponent - beq ij_accept_precision - - // We have an extra digit after saturating our precision. - // Thus we should ignore the digit, and just multiply the FAC - // by 10, but only if we have not seen a decimal point. - // If we have seen a decimal point, then we can completely ignore - // the digit, as it is contributing not recordable information - - lda __tokenise_work4 - cmp #$ff - bne ij_seen_decimal_point - - jsr fac1_mul10 - // Fall through -ij_seen_decimal_point: - jmp ij_consider_next_digit - -ij_accept_precision: - // We can accept more precision, so multiply the mantissa by 10, so that - // we can add the new digit in - jsr fac1_mul10 - - lda FAC1_exponent - bne ij_consider_next_digit - - // Get digit - ldy #$00 - lda (TXTPTR),y - sec - sbc #$30 - - // Add to FAC1 mantissa - clc - adc FAC1_mantissa+0 - sta FAC1_mantissa+0 - ldx #1 - ldy #3 -ij_loop2: - lda FAC1_mantissa,x - adc #$00 - sta FAC1_mantissa,x - inx - dey - bne ij_loop2 - - bcc !+ - // Carry set, so we have overflowed. - // We should shift everything right one digit, and increase - // the exponent by one. The non-zero exponent tells us that we - // can not fit any more precision in. - jsr fac1_mantissa_div2 -!: - -ij_consider_next_digit: - // Consider next digit - jsr consume_character - jmp ij_loop1 - - rts - - -erase_fac1: - lda #$00 - ldx #8 -!: - sta FAC1_exponent,x - dex - bpl !- - sta FACOV - - rts diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index c8fb1a48..6e587554 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -84,7 +84,7 @@ wedge_dos_command: wedge_dos_change_drive: // Reuse the line number parser for device number retrieval - jsr basic_parse_line_number + jsr fetch_line_number lda LINNUM+1 beq !+ jmp do_ILLEGAL_QUANTITY_error From 8b629816d7a660dcda07bdf0351afc27f4755c46 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 11:04:45 +0200 Subject: [PATCH 020/130] improved error handling in BASIC --- src/basic/basic_commands/cmd_run_goto.s | 1 + src/basic/basic_commands/cmd_sys.s | 4 +- .../helper_bload_fetch_address.s | 4 +- src/basic/engine/fetch_line_number.s | 90 +------------ src/basic/engine/fetch_uint16.s | 126 ++++++++++++++++++ src/basic/engine/fetch_uint8.s | 4 +- src/basic/wedge/wedge_dos.s | 8 +- tools/generate_strings.cc | 2 +- 8 files changed, 144 insertions(+), 95 deletions(-) create mode 100644 src/basic/engine/fetch_uint16.s diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index a2f0bb10..4ef839a0 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -24,6 +24,7 @@ cmd_goto: bcs !+ jsr fetch_line_number + bcs_16 do_SYNTAX_error jsr find_line bcc !+ // Line does not exist, so report error diff --git a/src/basic/basic_commands/cmd_sys.s b/src/basic/basic_commands/cmd_sys.s index 258e1c25..fc326360 100644 --- a/src/basic/basic_commands/cmd_sys.s +++ b/src/basic/basic_commands/cmd_sys.s @@ -41,7 +41,9 @@ cmd_sys_hack_not_needed: // XXX End of hack // - jsr fetch_line_number + lda #IDX__EV2_0B // 'SYNTAX ERROR' + jsr fetch_uint16 + bcs_16 do_SYNTAX_error cmd_sys_setup_call: lda #$4C // JMP opcode diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_address.s b/src/basic/basic_commands_CC/helper_bload_fetch_address.s index a470e974..e4a28e6d 100644 --- a/src/basic/basic_commands_CC/helper_bload_fetch_address.s +++ b/src/basic/basic_commands_CC/helper_bload_fetch_address.s @@ -12,7 +12,9 @@ helper_bload_fetch_address: jsr injest_comma bcs_16 do_SYNTAX_error - jsr fetch_line_number // XXX detect errors here + lda #IDX__EV2_0B // 'SYNTAX ERROR' + jsr fetch_uint16 + bcs_16 do_SYNTAX_error ldx LINNUM+0 ldy LINNUM+1 diff --git a/src/basic/engine/fetch_line_number.s b/src/basic/engine/fetch_line_number.s index 21e998fa..2078f296 100644 --- a/src/basic/engine/fetch_line_number.s +++ b/src/basic/engine/fetch_line_number.s @@ -3,97 +3,19 @@ // #LAYOUT# * * #IGNORE // -// Fetches line number, stores it in LINNUM, sets Carry to indicate failure (not a number), prints SYNTAX ERROR if above 65535 +// Fetches line number, stores it in LINNUM, sets Carry to indicate failure (not a number) // // Preserves both .X and .Y // fetch_line_number: - // Fetch the first character (skip spaces), check if 0-9 - - jsr fetch_character - cmp #$20 - beq fetch_line_number - - jsr convert_PETSCII_to_digit - bcs fetch_line_number_rts - - // First character seems to be correct - store it - - sta LINNUM+0 - lda #$00 - sta LINNUM+1 - - // FALLTROUGH - -fetch_line_number_loop: - - // Try to fetch another digit - - jsr fetch_character - jsr convert_PETSCII_to_digit - bcs fetch_line_number_end - - // We got another digit - store it - - pha - - // Multiply current LINNUM by 10 (x * 10 = (x * 2) + (x * 2) * 4) - - jsr fetch_line_number_mul_LINNUM_2 + lda #IDX__EV7_26 // 'LINE NUMBER TOO LARGE' + jsr fetch_uint16 + bcs_16 do_SYNTAX_error lda LINNUM+1 - pha - lda LINNUM+0 - pha - - jsr fetch_line_number_mul_LINNUM_2 - jsr fetch_line_number_mul_LINNUM_2 - - clc - pla - adc LINNUM+0 - sta LINNUM+0 - pla - adc LINNUM+1 - sta LINNUM+1 - bcs_16 do_SYNTAX_error - - // Add the new digit to LINNUM - - pla - clc - adc LINNUM+0 - sta LINNUM+0 - lda LINNUM+1 - adc #$00 - sta LINNUM+1 - bcs_16 do_SYNTAX_error - - // Next iteration - -#if HAS_OPCODES_65C02 - bra fetch_line_number_loop -#else - jmp fetch_line_number_loop -#endif - -fetch_line_number_end: - - jsr unconsume_character - clc - - // FALLTROUGH - -fetch_line_number_rts: - - rts - -fetch_line_number_mul_LINNUM_2: - - asl LINNUM+0 - rol LINNUM+1 - bcs_16 do_SYNTAX_error + cmp #$FF + beq_16 do_LINE_NUMBER_TOO_LARGE_error rts diff --git a/src/basic/engine/fetch_uint16.s b/src/basic/engine/fetch_uint16.s new file mode 100644 index 00000000..d6bd568a --- /dev/null +++ b/src/basic/engine/fetch_uint16.s @@ -0,0 +1,126 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches unsigned 16-bit integer, stores it in LINNUM, sets Carry to indicate failure (not a number) +// +// If value above 65535, error depends on .A opn entry +// +// Preserves both .X and .Y +// + +fetch_uint16: + + // Push the error code to stack + + pha + + // Fetch the first character (skip spaces), check if 0-9 + + jsr fetch_character + cmp #$20 + beq fetch_uint16 + + jsr convert_PETSCII_to_digit + bcs fetch_uint16_rts + + // First character seems to be correct - store it + + sta LINNUM+0 + lda #$00 + sta LINNUM+1 + + // FALLTROUGH + +fetch_uint16_loop: + + // Try to fetch another digit + + jsr fetch_character + jsr convert_PETSCII_to_digit + bcs fetch_uint16_end + + // We got another digit - store it + + pha + + // Multiply current LINNUM by 10 (x * 10 = (x * 2) + (x * 2) * 4) + + jsr fetch_uint16_mul_LINNUM_2 + bcs fetch_uint16_1PLA_error + + lda LINNUM+1 + pha + lda LINNUM+0 + pha + + jsr fetch_uint16_mul_LINNUM_2 + bcs fetch_uint16_3PLA_error + jsr fetch_uint16_mul_LINNUM_2 + bcs fetch_uint16_3PLA_error + + clc + pla + adc LINNUM+0 + sta LINNUM+0 + pla + adc LINNUM+1 + sta LINNUM+1 + bcs fetch_uint16_1PLA_error + + // Add the new digit to LINNUM + + pla + clc + adc LINNUM+0 + sta LINNUM+0 + lda LINNUM+1 + adc #$00 + sta LINNUM+1 + bcs fetch_uint16_error + + // Next iteration + +#if HAS_OPCODES_65C02 + bra fetch_uint16_loop +#else + jmp fetch_uint16_loop +#endif + +fetch_uint16_end: + + jsr unconsume_character + clc + + // FALLTROUGH + +fetch_uint16_rts: + + pla + rts + +fetch_uint16_mul_LINNUM_2: + + asl LINNUM+0 + rol LINNUM+1 + + rts + +fetch_uint16_3PLA_error: + + pla + pla + + // FALLTROUGH + +fetch_uint16_1PLA_error: + + pla + + // FALLTROUGH + +fetch_uint16_error: + + plx_trash_a + jmp do_basic_error diff --git a/src/basic/engine/fetch_uint8.s b/src/basic/engine/fetch_uint8.s index 3d92fa6b..2660ea0f 100644 --- a/src/basic/engine/fetch_uint8.s +++ b/src/basic/engine/fetch_uint8.s @@ -17,7 +17,9 @@ fetch_coma_uint8: fetch_uint8: jsr injest_spaces - jsr fetch_line_number // XXX detect errors here + lda #IDX__EV2_0E // 'ILLEGAL QUANTITY ERROR' + jsr fetch_uint16 + bcs !+ lda LINNUM+1 bne_16 do_ILLEGAL_QUANTITY_error lda LINNUM+0 diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index 6e587554..5a9eea52 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -83,13 +83,7 @@ wedge_dos_command: wedge_dos_change_drive: - // Reuse the line number parser for device number retrieval - jsr fetch_line_number - lda LINNUM+1 - beq !+ - jmp do_ILLEGAL_QUANTITY_error -!: - lda LINNUM+0 + jsr fetch_uint8 cmp #$08 bpl !+ bcs !+ diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index 62075488..c7b83226 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -298,7 +298,7 @@ const StringEntryList GLOBAL_Errors = { ListType::STRINGS_BASIC, "errors", { false, false, false, false, "EV7_23", "NO GRAPHICS AREA" }, // not used for now { false, false, false, false, "EV7_24", "BAD DISK" }, // not used for now { false, false, false, false, "EV7_25", "BEND NOT FOUND" }, // not used for now - { false, false, false, false, "EV7_26", "LINE NUMBER TOO LARGE" }, // not used for now + { true, true, true, true, "EV7_26", "LINE NUMBER TOO LARGE" }, { false, false, false, false, "EV7_27", "UNRESOLVED REFERENCE" }, // not used for now { true, true, true, true, "EV7_28", "NOT IMPLEMENTED" }, // this message actually differs from the CBM one { false, false, false, false, "EV7_29", "FILE READ" }, // not used for now From 7edf26fbb62cde5443de9d2c3fc76a9c5bb673d0 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 11:45:54 +0200 Subject: [PATCH 021/130] code size optimization in BASIC --- src/basic/engine/end_of_statement.s | 5 +---- src/basic/engine/end_of_statement_check.s | 2 ++ src/basic/engine/execute_line_statements.s | 4 +--- src/basic/engine/fetch_character_skip_spaces.s | 15 +++++++++++++++ src/basic/engine/fetch_uint16.s | 4 +--- src/basic/engine/fetch_uint8.s | 1 - src/basic/engine/fetch_variable.s | 5 +---- src/basic/engine/injest_assign.s | 4 +--- src/basic/engine/injest_spaces.s | 18 ------------------ src/basic/wedge/wedge_tape.s | 3 +-- src/basic/wedge/wedge_tape_prepare_load.s | 5 ++--- 11 files changed, 25 insertions(+), 41 deletions(-) create mode 100644 src/basic/engine/fetch_character_skip_spaces.s delete mode 100644 src/basic/engine/injest_spaces.s diff --git a/src/basic/engine/end_of_statement.s b/src/basic/engine/end_of_statement.s index 197ada21..3e3ca00d 100644 --- a/src/basic/engine/end_of_statement.s +++ b/src/basic/engine/end_of_statement.s @@ -9,10 +9,7 @@ end_of_statement: - jsr fetch_character - - cmp #$20 // check for space - beq end_of_statement + jsr fetch_character_skip_spaces cmp #$3A // check for colon beq_16 execute_statements diff --git a/src/basic/engine/end_of_statement_check.s b/src/basic/engine/end_of_statement_check.s index 8a4c7011..e8b3b6ea 100644 --- a/src/basic/engine/end_of_statement_check.s +++ b/src/basic/engine/end_of_statement_check.s @@ -9,6 +9,8 @@ end_of_statement_check: + // XXX consider optimized version for 46K/56K memory models + ldy #$00 #if CONFIG_MEMORY_MODEL_60K diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine/execute_line_statements.s index e63e952c..c0da724a 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine/execute_line_statements.s @@ -16,9 +16,7 @@ execute_statements: // Skip over any white spaces and colons (':') !: - jsr fetch_character - cmp #$20 // space, can be skipped - beq !- + jsr fetch_character_skip_spaces cmp #$3A // colon, can be skipped beq !- diff --git a/src/basic/engine/fetch_character_skip_spaces.s b/src/basic/engine/fetch_character_skip_spaces.s new file mode 100644 index 00000000..c17eeab7 --- /dev/null +++ b/src/basic/engine/fetch_character_skip_spaces.s @@ -0,0 +1,15 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches a single character, but skips spaces +// + +fetch_character_skip_spaces: + + jsr fetch_character + cmp #$20 + beq fetch_character_skip_spaces + + rts diff --git a/src/basic/engine/fetch_uint16.s b/src/basic/engine/fetch_uint16.s index d6bd568a..5768588c 100644 --- a/src/basic/engine/fetch_uint16.s +++ b/src/basic/engine/fetch_uint16.s @@ -18,9 +18,7 @@ fetch_uint16: // Fetch the first character (skip spaces), check if 0-9 - jsr fetch_character - cmp #$20 - beq fetch_uint16 + jsr fetch_character_skip_spaces jsr convert_PETSCII_to_digit bcs fetch_uint16_rts diff --git a/src/basic/engine/fetch_uint8.s b/src/basic/engine/fetch_uint8.s index 2660ea0f..75d8c685 100644 --- a/src/basic/engine/fetch_uint8.s +++ b/src/basic/engine/fetch_uint8.s @@ -16,7 +16,6 @@ fetch_coma_uint8: fetch_uint8: - jsr injest_spaces lda #IDX__EV2_0E // 'ILLEGAL QUANTITY ERROR' jsr fetch_uint16 bcs !+ diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index 9dc6438a..b6ba663b 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -11,11 +11,8 @@ fetch_variable: sta VARNAM+1 // Fetch the first character -!: - jsr fetch_character - cmp #$20 // ignore all the spaces - beq !- + jsr fetch_character_skip_spaces jsr is_AZ bcs_16 do_SYNTAX_error diff --git a/src/basic/engine/injest_assign.s b/src/basic/engine/injest_assign.s index c07898a7..e9cc7330 100644 --- a/src/basic/engine/injest_assign.s +++ b/src/basic/engine/injest_assign.s @@ -9,11 +9,9 @@ injest_assign: - jsr fetch_character + jsr fetch_character_skip_spaces cmp #$B2 // assign operator character beq injest_assign_found - cmp #$20 // space, can always be skipped - beq injest_assign // Not found jsr unconsume_character diff --git a/src/basic/engine/injest_spaces.s b/src/basic/engine/injest_spaces.s deleted file mode 100644 index fb018def..00000000 --- a/src/basic/engine/injest_spaces.s +++ /dev/null @@ -1,18 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Injests all spaces -// - -// XXX get rid of this when proper number parsing is implemented - - -injest_spaces: - - jsr fetch_character - cmp #$20 // space, can be skipped - beq injest_spaces - - jmp unconsume_character diff --git a/src/basic/wedge/wedge_tape.s b/src/basic/wedge/wedge_tape.s index 951ced7e..e90c6c4e 100644 --- a/src/basic/wedge/wedge_tape.s +++ b/src/basic/wedge/wedge_tape.s @@ -37,8 +37,7 @@ wedge_arrow_H: // Make sure the syntax is correct - jsr injest_spaces - jsr fetch_character + jsr fetch_character_skip_spaces cmp #$00 bne_16 do_SYNTAX_error diff --git a/src/basic/wedge/wedge_tape_prepare_load.s b/src/basic/wedge/wedge_tape_prepare_load.s index cac50b40..b31f0aa3 100644 --- a/src/basic/wedge/wedge_tape_prepare_load.s +++ b/src/basic/wedge/wedge_tape_prepare_load.s @@ -13,9 +13,8 @@ wedge_tape_prepare_load: // Make sure the syntax is correct - jsr injest_spaces - jsr fetch_character - + jsr fetch_character_skip_spaces + cmp #$00 beq wedge_tape_prepare_load_no_filename // branch if no file name given cmp #$22 From 1432935f0327aaaf4cda72b0f082910a4435b02c Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 12:13:04 +0200 Subject: [PATCH 022/130] added some Mega65 optimizations in BASIC --- src/basic/engine/fetch_character.s | 6 +++ .../engine/fetch_character_m65_46K_50K.s | 42 +++++++++++++++++++ .../engine/fetch_character_skip_spaces.s | 7 ++++ .../fetch_character_skip_spaces_m65_46K_50K.s | 41 ++++++++++++++++++ ...oke_46k_50k.s => under_rom_peek_46k_50k.s} | 0 5 files changed, 96 insertions(+) create mode 100644 src/basic/engine/fetch_character_m65_46K_50K.s create mode 100644 src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s rename src/basic/memory/{under_rom_peek_poke_46k_50k.s => under_rom_peek_46k_50k.s} (100%) diff --git a/src/basic/engine/fetch_character.s b/src/basic/engine/fetch_character.s index 68397cc7..8c1dcc99 100644 --- a/src/basic/engine/fetch_character.s +++ b/src/basic/engine/fetch_character.s @@ -7,6 +7,9 @@ // +// For these configurations we have optimized version in another file +#if !(ROM_LAYOUT_M65 && (CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K)) + fetch_character: ldy #0 @@ -46,3 +49,6 @@ consume_character: #endif rts + + +#endif diff --git a/src/basic/engine/fetch_character_m65_46K_50K.s b/src/basic/engine/fetch_character_m65_46K_50K.s new file mode 100644 index 00000000..84363222 --- /dev/null +++ b/src/basic/engine/fetch_character_m65_46K_50K.s @@ -0,0 +1,42 @@ +// #LAYOUT# M65 BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// +// Fetches a single character - optimized version +// + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + +fetch_character: + + ldy #0 + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs + + lda (TXTPTR), y + + // Restore memory mapping + + pha + lda #$27 + sta CPU_R6510 + pla + + // FALLTROUGH + +consume_character: + + // Advance basic text pointer + + inw TXTPTR + rts + + +#endif diff --git a/src/basic/engine/fetch_character_skip_spaces.s b/src/basic/engine/fetch_character_skip_spaces.s index c17eeab7..e67ffc82 100644 --- a/src/basic/engine/fetch_character_skip_spaces.s +++ b/src/basic/engine/fetch_character_skip_spaces.s @@ -6,6 +6,10 @@ // Fetches a single character, but skips spaces // + +// For these configurations we have optimized version in another file +#if !(ROM_LAYOUT_M65 && (CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K)) + fetch_character_skip_spaces: jsr fetch_character @@ -13,3 +17,6 @@ fetch_character_skip_spaces: beq fetch_character_skip_spaces rts + + +#endif diff --git a/src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s b/src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s new file mode 100644 index 00000000..9970a5ef --- /dev/null +++ b/src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s @@ -0,0 +1,41 @@ +// #LAYOUT# M65 BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// +// Fetches a single character, but skips spaces - optimized version +// + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + +fetch_character_skip_spaces: + + ldy #0 + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs, advance text pointer +!: + lda (TXTPTR), y + inw TXTPTR + + // Skip space characters + + cmp #$20 + beq !- + + // Restore memory mapping + + pha + lda #$27 + sta CPU_R6510 + pla + + rts + + +#endif diff --git a/src/basic/memory/under_rom_peek_poke_46k_50k.s b/src/basic/memory/under_rom_peek_46k_50k.s similarity index 100% rename from src/basic/memory/under_rom_peek_poke_46k_50k.s rename to src/basic/memory/under_rom_peek_46k_50k.s From cec9adce256c346170ca789367bd65650ce42639 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 12:40:22 +0200 Subject: [PATCH 023/130] more Mega65 optimizations in BASIC --- src/basic/basic_commands/cmd_print.s | 4 ++ src/basic/engine/ad9e.frmevl.s | 4 ++ src/basic/engine/end_of_statement_check.s | 4 ++ src/basic/engine/execute_line_statements.s | 4 ++ src/basic/engine/fetch_character.s | 6 ++- .../engine/fetch_character_m65_46K_50K.s | 39 ++++++++++++++---- .../fetch_character_skip_spaces_m65_46K_50K.s | 41 ------------------- src/basic/engine/fetch_operator.s | 12 ++++++ src/basic/engine/fetch_uint16.s | 4 ++ src/basic/engine/fetch_variable.s | 4 ++ src/basic/engine/injest_assign.s | 4 ++ src/basic/engine/injest_comma.s | 9 ++-- src/basic/engine/unconsume_character.s | 3 ++ 13 files changed, 83 insertions(+), 55 deletions(-) delete mode 100644 src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index f26eee42..fe7093c5 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -19,7 +19,11 @@ cmd_print: cmd_print_loop: +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif // FALLTROUGH diff --git a/src/basic/engine/ad9e.frmevl.s b/src/basic/engine/ad9e.frmevl.s index 71b1ccb7..b1f8688e 100644 --- a/src/basic/engine/ad9e.frmevl.s +++ b/src/basic/engine/ad9e.frmevl.s @@ -178,7 +178,11 @@ FRMEVL_fetch_string: !: // No closing quote, but end of the data +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif // FALLTROUGH diff --git a/src/basic/engine/end_of_statement_check.s b/src/basic/engine/end_of_statement_check.s index e8b3b6ea..7612d433 100644 --- a/src/basic/engine/end_of_statement_check.s +++ b/src/basic/engine/end_of_statement_check.s @@ -26,7 +26,11 @@ end_of_statement_check: cmp #$20 bne !+ +#if !HAS_OPCODES_65CE02 jsr consume_character +#else + inw TXTPTR +#endif jmp end_of_statement_check !: cmp #$00 diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine/execute_line_statements.s index c0da724a..1e37e135 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine/execute_line_statements.s @@ -254,5 +254,9 @@ execute_statements_var_assign: // Try variable assignment - execute as LET command +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif jmp cmd_let diff --git a/src/basic/engine/fetch_character.s b/src/basic/engine/fetch_character.s index 8c1dcc99..231cd086 100644 --- a/src/basic/engine/fetch_character.s +++ b/src/basic/engine/fetch_character.s @@ -29,14 +29,14 @@ fetch_character: #endif +#if !HAS_OPCODES_65CE02 + // FALLTHROUGH consume_character: // Advance basic text pointer -#if !HAS_OPCODES_65CE02 - inc TXTPTR+0 bne !+ inc TXTPTR+1 @@ -44,6 +44,8 @@ consume_character: #else // HAS_OPCODES_65CE02 + // Advance basic text pointer + inw TXTPTR #endif diff --git a/src/basic/engine/fetch_character_m65_46K_50K.s b/src/basic/engine/fetch_character_m65_46K_50K.s index 84363222..78908e7a 100644 --- a/src/basic/engine/fetch_character_m65_46K_50K.s +++ b/src/basic/engine/fetch_character_m65_46K_50K.s @@ -2,7 +2,7 @@ // #LAYOUT# * * #IGNORE // -// Fetches a single character - optimized version +// Fetches a single character (depending on version - also skips spaces) - optimized version // @@ -18,9 +18,14 @@ fetch_character: lda #$26 sta CPU_R6510 - // Retrieve value from under ROMs + // Retrieve value from under ROMs, advance text pointer lda (TXTPTR), y + inw TXTPTR + + // FALLTROUGH + +fetch_character_end: // Restore memory mapping @@ -29,14 +34,30 @@ fetch_character: sta CPU_R6510 pla - // FALLTROUGH - -consume_character: - - // Advance basic text pointer - - inw TXTPTR rts +fetch_character_skip_spaces: + + ldy #0 + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs, advance text pointer +!: + lda (TXTPTR), y + inw TXTPTR + + // Skip space characters + + cmp #$20 + beq !- + + // Restore memory mapping + + bra fetch_character_end + #endif diff --git a/src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s b/src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s deleted file mode 100644 index 9970a5ef..00000000 --- a/src/basic/engine/fetch_character_skip_spaces_m65_46K_50K.s +++ /dev/null @@ -1,41 +0,0 @@ -// #LAYOUT# M65 BASIC_0 #TAKE-HIGH -// #LAYOUT# * * #IGNORE - -// -// Fetches a single character, but skips spaces - optimized version -// - - -#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - - -fetch_character_skip_spaces: - - ldy #0 - - // Unmap BASIC lower ROM - - lda #$26 - sta CPU_R6510 - - // Retrieve value from under ROMs, advance text pointer -!: - lda (TXTPTR), y - inw TXTPTR - - // Skip space characters - - cmp #$20 - beq !- - - // Restore memory mapping - - pha - lda #$27 - sta CPU_R6510 - pla - - rts - - -#endif diff --git a/src/basic/engine/fetch_operator.s b/src/basic/engine/fetch_operator.s index 26a260f6..c428ec6c 100644 --- a/src/basic/engine/fetch_operator.s +++ b/src/basic/engine/fetch_operator.s @@ -41,7 +41,11 @@ fetch_operator_success: fetch_operator_failed: +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif sec rts @@ -57,7 +61,11 @@ fetch_operator_try_gteq: // This is a '>' +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif lda #$07 bne fetch_operator_success // branch always !: @@ -79,7 +87,11 @@ fetch_operator_try_lteq_neq: // This is a '<' +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif lda #$09 bne fetch_operator_success // branch always !: diff --git a/src/basic/engine/fetch_uint16.s b/src/basic/engine/fetch_uint16.s index 5768588c..ccd0fd05 100644 --- a/src/basic/engine/fetch_uint16.s +++ b/src/basic/engine/fetch_uint16.s @@ -88,7 +88,11 @@ fetch_uint16_loop: fetch_uint16_end: +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif clc // FALLTROUGH diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index b6ba663b..0bb308cd 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -48,7 +48,11 @@ fetch_variable_check_type: fetch_variable_type_float: +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif #if HAS_OPCODES_65C02 bra fetch_variable_find_addr diff --git a/src/basic/engine/injest_assign.s b/src/basic/engine/injest_assign.s index e9cc7330..efc9bea0 100644 --- a/src/basic/engine/injest_assign.s +++ b/src/basic/engine/injest_assign.s @@ -14,7 +14,11 @@ injest_assign: beq injest_assign_found // Not found +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif sec rts diff --git a/src/basic/engine/injest_comma.s b/src/basic/engine/injest_comma.s index 8997ee2a..ff712d0e 100644 --- a/src/basic/engine/injest_comma.s +++ b/src/basic/engine/injest_comma.s @@ -9,14 +9,17 @@ injest_comma: - jsr fetch_character + jsr fetch_character_skip_spaces cmp #$2C // comma character beq injest_comma_found - cmp #$20 // space, can always be skipped - beq injest_comma // Not found + +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif sec rts diff --git a/src/basic/engine/unconsume_character.s b/src/basic/engine/unconsume_character.s index 6503a17d..73609eff 100644 --- a/src/basic/engine/unconsume_character.s +++ b/src/basic/engine/unconsume_character.s @@ -6,6 +6,7 @@ // Reverses character fetch // +#if !HAS_OPCODES_65CE02 unconsume_character: @@ -18,3 +19,5 @@ unconsume_character: sta TXTPTR+1 rts + +#endif From b9bf1251da924253cdf6c76f3834cb24146031da Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 13:03:37 +0200 Subject: [PATCH 024/130] code size optimization for Mega65 --- .../engine/fetch_character_m65_46K_50K.s | 63 ------------------- .../{engine => memory}/fetch_character.s | 0 .../fetch_character_skip_spaces.s | 0 ...k_50k.s => under_rom_peek_fetch_46k_50k.s} | 48 ++++++++++++++ 4 files changed, 48 insertions(+), 63 deletions(-) delete mode 100644 src/basic/engine/fetch_character_m65_46K_50K.s rename src/basic/{engine => memory}/fetch_character.s (100%) rename src/basic/{engine => memory}/fetch_character_skip_spaces.s (100%) rename src/basic/memory/{under_rom_peek_46k_50k.s => under_rom_peek_fetch_46k_50k.s} (72%) diff --git a/src/basic/engine/fetch_character_m65_46K_50K.s b/src/basic/engine/fetch_character_m65_46K_50K.s deleted file mode 100644 index 78908e7a..00000000 --- a/src/basic/engine/fetch_character_m65_46K_50K.s +++ /dev/null @@ -1,63 +0,0 @@ -// #LAYOUT# M65 BASIC_0 #TAKE-HIGH -// #LAYOUT# * * #IGNORE - -// -// Fetches a single character (depending on version - also skips spaces) - optimized version -// - - -#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - - -fetch_character: - - ldy #0 - - // Unmap BASIC lower ROM - - lda #$26 - sta CPU_R6510 - - // Retrieve value from under ROMs, advance text pointer - - lda (TXTPTR), y - inw TXTPTR - - // FALLTROUGH - -fetch_character_end: - - // Restore memory mapping - - pha - lda #$27 - sta CPU_R6510 - pla - - rts - -fetch_character_skip_spaces: - - ldy #0 - - // Unmap BASIC lower ROM - - lda #$26 - sta CPU_R6510 - - // Retrieve value from under ROMs, advance text pointer -!: - lda (TXTPTR), y - inw TXTPTR - - // Skip space characters - - cmp #$20 - beq !- - - // Restore memory mapping - - bra fetch_character_end - - -#endif diff --git a/src/basic/engine/fetch_character.s b/src/basic/memory/fetch_character.s similarity index 100% rename from src/basic/engine/fetch_character.s rename to src/basic/memory/fetch_character.s diff --git a/src/basic/engine/fetch_character_skip_spaces.s b/src/basic/memory/fetch_character_skip_spaces.s similarity index 100% rename from src/basic/engine/fetch_character_skip_spaces.s rename to src/basic/memory/fetch_character_skip_spaces.s diff --git a/src/basic/memory/under_rom_peek_46k_50k.s b/src/basic/memory/under_rom_peek_fetch_46k_50k.s similarity index 72% rename from src/basic/memory/under_rom_peek_46k_50k.s rename to src/basic/memory/under_rom_peek_fetch_46k_50k.s index c2a31424..43e3e7bf 100644 --- a/src/basic/memory/under_rom_peek_46k_50k.s +++ b/src/basic/memory/under_rom_peek_fetch_46k_50k.s @@ -103,4 +103,52 @@ peek_under_roms_via_FAC1_PLUS_1: #endif +#if ROM_LAYOUT_M65 + + +fetch_character: + + ldy #0 + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs, advance text pointer + + lda (TXTPTR), y + inw TXTPTR + + // Restore memory mapping + + bra peek_under_roms_finalize + + +fetch_character_skip_spaces: + + ldy #0 + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs, advance text pointer +!: + lda (TXTPTR), y + inw TXTPTR + + // Skip space characters + + cmp #$20 + beq !- + + // Restore memory mapping + + bra peek_under_roms_finalize + + +#endif + #endif From a17f810d50fb13bb7bc27fd487b7e8f5dd542b55 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 13:37:10 +0200 Subject: [PATCH 025/130] fixed end of statement check --- src/basic/basic_commands/cmd_print.s | 4 +- src/basic/basic_commands/cmd_run_goto.s | 2 +- src/basic/basic_commands/cmd_sys.s | 2 +- .../helper_load_fetch_filename.s | 2 +- src/basic/engine/ad9e.frmevl.s | 4 +- src/basic/engine/end_of_statement_check.s | 49 ------------------- src/basic/engine/is_end_of_statement.s | 39 +++++++++++++++ 7 files changed, 46 insertions(+), 56 deletions(-) delete mode 100644 src/basic/engine/end_of_statement_check.s create mode 100644 src/basic/engine/is_end_of_statement.s diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index fe7093c5..2c81a2de 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -8,7 +8,7 @@ cmd_print: // First check if we have anything to print - jsr end_of_statement_check + jsr is_end_of_statement bcs cmd_print_new_line_done jsr fetch_character @@ -76,7 +76,7 @@ cmd_print_next_arg: // Look for the next argument - jsr end_of_statement_check + jsr is_end_of_statement bcs cmd_print_new_line_done cmp #$2C // comma XXX on C64 behavior is more complicated, fix it diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index 4ef839a0..c5e88994 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -20,7 +20,7 @@ cmd_goto: // Reset line pointer to first line of program. jsr init_oldtxt - jsr end_of_statement_check + jsr is_end_of_statement bcs !+ jsr fetch_line_number diff --git a/src/basic/basic_commands/cmd_sys.s b/src/basic/basic_commands/cmd_sys.s index fc326360..01dcf833 100644 --- a/src/basic/basic_commands/cmd_sys.s +++ b/src/basic/basic_commands/cmd_sys.s @@ -5,7 +5,7 @@ cmd_sys: - jsr end_of_statement_check + jsr is_end_of_statement bcc !+ // SYS requires an argument diff --git a/src/basic/basic_commands/helper_load_fetch_filename.s b/src/basic/basic_commands/helper_load_fetch_filename.s index d93a4055..367b4cbf 100644 --- a/src/basic/basic_commands/helper_load_fetch_filename.s +++ b/src/basic/basic_commands/helper_load_fetch_filename.s @@ -11,7 +11,7 @@ helper_load_fetch_filename: // Check if end of statement - jsr end_of_statement_check + jsr is_end_of_statement bcs !+ // Call the expression parser, make sure it returned a string diff --git a/src/basic/engine/ad9e.frmevl.s b/src/basic/engine/ad9e.frmevl.s index b1f8688e..c831e153 100644 --- a/src/basic/engine/ad9e.frmevl.s +++ b/src/basic/engine/ad9e.frmevl.s @@ -41,7 +41,7 @@ FRMEVL_loop: // Check if end of statement, fetch the character - jsr end_of_statement_check + jsr is_end_of_statement bcs_16 do_SYNTAX_error jsr fetch_character @@ -200,7 +200,7 @@ FRMEVL_fetch_string: FRMEVL_got_value: - jsr end_of_statement_check + jsr is_end_of_statement bcs FRMEVL_compute_all // compute the stack if expression ended // FALLTROUGH diff --git a/src/basic/engine/end_of_statement_check.s b/src/basic/engine/end_of_statement_check.s deleted file mode 100644 index 7612d433..00000000 --- a/src/basic/engine/end_of_statement_check.s +++ /dev/null @@ -1,49 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Check for end of statement, sets Carry if so. Injests all spaces. -// - - -end_of_statement_check: - - // XXX consider optimized version for 46K/56K memory models - - ldy #$00 - -#if CONFIG_MEMORY_MODEL_60K - ldx # Date: Sun, 12 Jul 2020 14:34:17 +0200 Subject: [PATCH 026/130] GOTO command got performance optimization --- src/basic/basic_commands/cmd_run_goto.s | 77 ++++++++++++++++++++----- src/basic/editor/find_line.s | 18 ++---- src/basic/editor/insert_line.s | 2 +- src/basic/editor/shell.s | 4 +- 4 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index c5e88994..4f181c7a 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -6,32 +6,83 @@ cmd_run: // RUN clears all variables + jsr do_clr -cmd_goto: + // Initialize OLDTXT pointer, disable Kernal messages - // XXX optimize this: deduplicate last part (and init_oldtxt) with load/verify, - // if line number greater than current line - find line backwards - - // Disable Kernal messages + jsr init_oldtxt lda #$00 jsr JSETMSG - // Reset line pointer to first line of program. - jsr init_oldtxt + // Check if we have any paramenters jsr is_end_of_statement - bcs !+ + bcs cmd_run_goto_launch + + // FALLTROUGH + +cmd_goto: + + // GOTO requires line number jsr fetch_line_number bcs_16 do_SYNTAX_error - jsr find_line - bcc !+ - // Line does not exist, so report error - jmp do_UNDEFD_STATEMENT_error + + // Check for direct mode + + lda CURLIN+1 + bmi cmd_goto_direct + + // Not a direct mode - compare desired line number (LINNUM) with the current one (CURLIN) + + lda LINNUM+1 + cmp CURLIN+1 + bne !+ + lda LINNUM+0 + cmp CURLIN+0 !: + // If desired line number is lower - search line number from start + + bcc cmd_goto_from_start + + // Else - search from the current line + + jsr find_line_from_current + +#if HAS_OPCODES_65C02 + bra cmd_goto_check +#else + jmp cmd_goto_check +#endif + +cmd_goto_direct: + + // Disable Kernal messages + + lda #$00 + jsr JSETMSG + + // FALLTROUGH + +cmd_goto_from_start: + + // Direct mode - find the line from the beginning + + jsr find_line_from_start + + // FALLTROUGH + +cmd_goto_check: + + bcs_16 do_UNDEFD_STATEMENT_error + + // FALLTROUGH + +cmd_run_goto_launch: + // Run it! - + pha pha jmp execute_line diff --git a/src/basic/editor/find_line.s b/src/basic/editor/find_line.s index 47569971..9487e432 100644 --- a/src/basic/editor/find_line.s +++ b/src/basic/editor/find_line.s @@ -3,23 +3,17 @@ // #LAYOUT# * * #IGNORE -// Find the BASIC line with number LINNUM - -// XXX it should be possible to start from the current line (OLDTXT), or from the startup, -// depending on the current and target line number +// Find the BASIC line with number in LINNUM -find_line: +find_line_from_start: // Get pointer to start of BASIC text - lda TXTTAB+0 - sta OLDTXT+0 - lda TXTTAB+1 - sta OLDTXT+1 + jsr init_oldtxt // FALLTROUGH -find_line_loop: +find_line_from_current: // Check if line is not empty @@ -100,9 +94,9 @@ find_line_next: sta OLDTXT+0 #if HAS_OPCODES_65C02 - bra find_line_loop + bra find_line_from_current #else - jmp find_line_loop + jmp find_line_from_current #endif find_line_fail: diff --git a/src/basic/editor/insert_line.s b/src/basic/editor/insert_line.s index 790f9c58..a0a5bfc4 100644 --- a/src/basic/editor/insert_line.s +++ b/src/basic/editor/insert_line.s @@ -13,7 +13,7 @@ insert_line: - // ASSUMES find_line has been called to set the insert point. + // ASSUMES find_line_from_start has been called to set the insert point. // jsr printf // .text "INSERTING LINE AT $" diff --git a/src/basic/editor/shell.s b/src/basic/editor/shell.s index 3634e177..edc127b4 100644 --- a/src/basic/editor/shell.s +++ b/src/basic/editor/shell.s @@ -169,12 +169,12 @@ shell_add_delete_line: jsr update_VARTAB_do_clr // Check if line already present - jsr find_line + jsr find_line_from_start bcs !+ // Line already present - delete it jsr delete_line - jsr find_line // refresh OLDTXT + jsr find_line_from_start // refresh OLDTXT !: // Insert new line if non-zero length, i.e., that // we are not just deleting the line. From 8e65db666d6da357b25377b8b227bd8e69d4dfe6 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 16:03:31 +0200 Subject: [PATCH 027/130] cleanup in DOS Wedge, adapted to currently available helper routines --- src/basic/wedge/wedge_dos.s | 158 +++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 58 deletions(-) diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index 5a9eea52..f214d91d 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -5,6 +5,7 @@ #if CONFIG_DOS_WEDGE + // .X has to contain size of the buffer wedge_dos: @@ -23,72 +24,76 @@ wedge_dos: ldy #$0F jsr JSETFLS - // Setup necessary parts of BASIC + // Setup necessary part of BASIC - lda #<(BUF+1) - sta TXTPTR+0 - lda #>(BUF+1) - sta TXTPTR+1 - - lda #$FF - sta CURLIN+1 + jsr prepare_direct_execution + jsr fetch_character // Now we have to check what the user wants us to do // Check if user asked for a status + ldy #$00 lda (TXTPTR), y - bne !+ - jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above? -!: + beq_16 wedge_dos_status + // Check if asked for a directory + cmp #$24 - bne !+ - jmp wedge_dos_directory -!: + beq_16 wedge_dos_directory + // Check if asked to change drive number, or if it is a regular command - cmp #$30 - bcc wedge_dos_command // char code before 0 - cmp #$3A - bcs wedge_dos_command // char code after 9 - iny - lda (TXTPTR), y - beq wedge_dos_change_drive // end of buffer - cmp #$20 - beq wedge_dos_change_drive - jmp !- + + jsr is_09 + bcc wedge_dos_change_drive + + // FALLTROUGH wedge_dos_command: // Provide command name + jsr wedge_dos_setnam jsr JSETNAM jsr JOPEN - bcc !+ - jmp wedge_dos_basic_error // XXX combine with other such jumps -!: + bcs_16 wedge_dos_basic_error + // Retrieve status, print it if not OK + jsr JCLALL jsr wedge_dos_status_get + lda BUF+0 cmp #$30 // '0' bne wedge_dos_status_print + lda BUF+1 cmp #$30 // '0' bne wedge_dos_status_print // Clean-up and exit + jmp wedge_dos_clean_exit wedge_dos_change_drive: + // Fetch new drive number, make sure this is the last part of the command + jsr fetch_uint8 + pha + jsr fetch_character_skip_spaces + cmp #$00 + bne_16 do_SYNTAX_error + pla + + // Check if device number is valid for IEC drive + cmp #$08 - bpl !+ - bcs !+ - jmp do_ILLEGAL_DEVICE_NUMBER_error -!: + bcc_16 do_ILLEGAL_DEVICE_NUMBER_error + + // Store new device number and return to shell + sta FA jmp shell_main_loop @@ -102,37 +107,49 @@ wedge_dos_status_get: // https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive // Set remaining file parameters, open the channel + lda #$00 // empty file name jsr JSETNAM jsr JOPEN - bcc !+ - jmp wedge_dos_basic_error // XXX combine with other such jumps -!: + bcs_16 wedge_dos_basic_error // Set channel for input + ldx #$0F jsr JCHKIN - bcc !+ - jmp wedge_dos_basic_error // XXX combine with other such jumps -!: + bcs_16 wedge_dos_basic_error + + // Fetch the drive status ldy #$00 -!: - cpy #$50 // buffer overflow protection - beq !+ - jsr JREADST // retrieve errors - // XXX error in case of status != EOF - // Print out everything retrieved from the drive - bne !+ - jsr JCHRIN - bcc wedge_dos_x1 - jmp wedge_dos_basic_error // XXX try to optimize this -wedge_dos_x1: + // FALLTROUGH + +wedge_dos_status_get_loop: + + // Check for buffer overflow + + cpy #$50 + beq_16 do_OVERFLOW_error + + // Check for EOF + + jsr JREADST + // XXX check for transfer errors + bne wedge_dos_status_get_done + + // Retrieve a byte and put it into the buffer + + jsr JCHRIN + bcs_16 wedge_dos_basic_error + sta BUF, y iny - jmp !- -!: + + bne wedge_dos_status_get_loop // branch always + +wedge_dos_status_get_done: + // Strip ending RETURN dey @@ -141,11 +158,13 @@ wedge_dos_x1: wedge_dos_status: jsr wedge_dos_status_get + // FALLTROUGH wedge_dos_status_print: // Print buffered status + ldx #$00 !: dey @@ -156,38 +175,48 @@ wedge_dos_status_print: bne !- !: // Clean-up and exit + +#if HAS_OPCODES_65C02 + bra wedge_dos_clean_exit +#else jmp wedge_dos_clean_exit +#endif wedge_dos_directory: - // First change the secondary address to the one suitable for - // directory loading - lda #$00 // logical device number + // First change the secondary address to the one suitable for directory loading + + lda #$00 // logical device number ldx FA ldy #$60 jsr JSETFLS // Provide file name + jsr wedge_dos_setnam - // Open the file + // Open the file, set channel for reading + jsr JOPEN bcs wedge_dos_basic_error - // Set channel for file reading ldx #$00 jsr JCHKIN bcs wedge_dos_basic_error // Ignore start address (2 first bytes) - XXX check for errors + jsr JCHRIN bcs wedge_dos_basic_error jsr JCHRIN bcs wedge_dos_basic_error + // FALLTROUGH + wedge_dos_directory_line: // Load a single line, reuse BASIC input buffer + ldy #$FF !: iny @@ -195,29 +224,33 @@ wedge_dos_directory_line: bcs wedge_dos_basic_error sta BUF, y cpy #$50 - beq !+ // line too long, terminate loading file + beq_16 do_OVERFLOW_error // branch if line too long jsr JREADST bne !+ // end of file cpy #$04 // 2 bytes (pointer to next line) + 2 bytes (line number) bcc !- lda BUF, y bne !- + // End of line, but not end of file + beq wedge_dos_directory_display !: lda #K_STS_END_OF_FILE sta IOSTATUS // make sure end of file is marked + // FALLTROUGH wedge_dos_directory_display: - cpy #$05 // protection against malformed directory + cpy #$05 // protection against malformed directory bcc wedge_dos_clean_exit - lda #$00 // extra protection agains buffer overflow + lda #$00 // extra protection agains buffer overflow sta BUF, y // Display line + ldx #BUF @@ -226,22 +259,28 @@ wedge_dos_directory_display: jsr list_single_line // Read & display next line or quit + lda IOSTATUS beq wedge_dos_directory_line + // FALLTROUGH wedge_dos_clean_exit: + jsr JCLALL jmp shell_main_loop wedge_dos_basic_error: + pha jsr JCLALL pla jmp do_kernal_error wedge_dos_setnam: + // Now determine the length of the 'file' name + ldy #$FF !: iny @@ -249,9 +288,12 @@ wedge_dos_setnam: bne !- // Set the name to open + tya ldx TXTPTR+0 ldy TXTPTR+1 + jmp JSETNAM + #endif // CONFIG_DOS_WEDGE From f3803fb0dbc6b0f51d84085aa1694ed36338dfa2 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 16:48:50 +0200 Subject: [PATCH 028/130] DOS Wedge nowv asks for confirmation on dangerous commands, updated binaries --- bin/basic_generic.rom | Bin 8192 -> 8192 bytes bin/basic_ultimate64.rom | Bin 8192 -> 8192 bytes bin/kernal_generic.rom | Bin 8192 -> 8192 bytes bin/kernal_ultimate64.rom | Bin 8192 -> 8192 bytes bin/mega65.rom | Bin 131072 -> 131072 bytes bin/mega65_pxlfont.rom | Bin 131072 -> 131072 bytes doc/Extended-BASIC.md | 1 - src/basic/wedge/wedge_dos.s | 68 +++++++++++++++++++++++++++++++++--- 8 files changed, 63 insertions(+), 6 deletions(-) diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index dc9dba7bbfb39ebcbaba4cd5b72bacba3350e308..8e9caf1c002eca45c671f4250b3621c8ff6c618b 100644 GIT binary patch delta 5142 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 delta 4396 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 F{{w3zzuo`< diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 75684fcc422bb9df7b58d2ea2c882f1b19d72a78..57116e02d872973f9151e1cbd0091ae1bd0b48f7 100644 GIT binary patch delta 1004 zcmXw1UuauZ9KI(vH`dUut!pu&Y{#2FO=ugkP1kE7vEt&caM2NPJ_#p(u4HQqeZF}} z!TzLlizehnAB0QEQP0+Cf*Z0j>(fHwL%GOa=EG>Srdu}{SJ{IDp`P4OIQQfGzTbC$ z=kM~|@?4Qs@t=q6mbr;fTwfPVFCOf&@A?Y$)qO{?Pt4zY5z#U6XE)b9rohA6JSF(w zU)zHHa(mX6Fnj1D927znCUnC;;*YLtuXR@ZU&^LH(-qm4TXeA^)6XprU5pgpt#G~2 zgZUm@uJG8(5=|34d8aK{qW1hwd$}%ZTRYlIyWh_~wngn;%|zc+Ch>zGw1bVx*7@S) zJ(_{9lUevGnS)YNhpWjnT;ab^L!||k##Ne7nE*2Q=?oZDfr5|9`Wc8*zy1~^sBt%L z9jAr632P`1i9E#fP{@Npm<#Xk@?D1N%7A000IcSx{$yFSW>aCEcorQ`fU zAJ^!Zk8C4kpFAd_s0-EK+>p?e8^uOeuS)2)2StXz^`LDxB23`q87DlzgkHqE${n84 zEu{VT zA2tYMYyieBFZ1#hIvJ*wMnpPR8Wrhy=@s$Du&8bv6Mq^KZw!iIZA3iWIQ#ZlK@)aX z{2-g|h760V92PiKXWS=>>AgB4?O55{o+a(~%3`}f6hhOsN;CGWG!t3263w(d>sbov zplXPnn(&Xf$k5lMe@?!LK ZEH-oMbo7Jwqo)L+e`{;M+;dO8{y!#GoNoXC delta 942 zcmZWkZ%k8H9KEj(D6~}PA`#qhH<~z&*dPYhMV&gSie5z_`hi9BR%k;18M7=gAsR@? zHLh;i!|ucUu-TB_>P5j;vjL^0pGtTM#H-N{+Y+ONrvgzQiq874yM0}<4?B6uJLmjP zPR{Mx*0rsZ2H>qM^#`Znip#wqXo96G{U)!3yc*CIJrqplBBE}>Wy8HiLBPYvL!`Z# zMWFjHkj>gCP<@wRdCp7xNHm&=$4B70xB{4nY$2s9BBIfIs3Zh`9+WL4w)T}KqR$f) z;6bTpbXVtOm^e~yc@wK7ttpSZk(H6QlviHIEX0}e$*Wi)kA5xLh*R}pCuvi?xQ(=` z9^6VCsvA4dWEc)5bK8&O)*S-@JYIJ_`hcSdji7rgDJRm@J~YL=Z$f{=idgNwh-~$JsMlikH%2 zT*gFrCmwh!R+hpKM7}3`rLMLP1kQ@7%Q6vx*)b?TagHjoJOp)&Hvdfhh0N!nx^uoXmI9BCzxB?=Ok@yAvUx#YrS zjpRt>A(S-Kk&j%gsMF1qe%Q1UjceclwPI9>6+%MvP$h0`6vSacJ+!AXyH-}SPw)SG zPjBALyrtQt+4HP|e|yFTsuUmnW?iUy@nDzzQ@v~}S6>}-V(f$Jk2XXO#P@Hl4^#!7 ztS(T3pM2LAtV8V?%Z=9>KEjPch{A-fyn(;IslME)e1yjR_;|A|m`HuxY%kT2`op$* za0mZUFAvd1Ev9HZMH49|fFA;M z8g!~a(MSE-B*bYzI|&J@-;0|s(&D{@IaGi|0pbNH7C>{UC83fN<4?OE;Zj zd>2*OVJ>I4x_5cB5%XVltmE0oTjtYVsOMl72A52nfS$5Np)ca<>5fC+-FM#Kce30e>YTw>WkHm1 zkVf|e2>F(^pnZ^e0m5`l>Bd2((QX1FmAZJYG-q6xJN#gsTxo23YT~+wIG5PdO|e%b zIJH?DWC=)&dC=qtvq@x_fx4SE-!*)AjXyipbE`k$}un!|P7LR;p4Y!F762S!aV^YVtB z9Hy=wL3Ctw7}3$y7tr;?D0S_5bYlozA4IZx1U~Oel`^|E7iq`J z-u4V>zgXpT*yqT;XixD@P& z)E~A+us=h|tnRjyECt&p+pBO|vQlx-_*L~x(#_gdkcbNQk8w6C#bFrU=b4w6=XsyD z?QPqGN(es8D}RS?z{=hp5H5uavWn*$a(qMK0#betkJ>GKfrQJ4dy2z=HKPC#_s*7s z3ok%E&zL0{tA%n_t0*$CF5^nD2XB*blUP(#TwKCAoP{%wx6XUNJUG}m?)6-gAFTOp zd~$R&Zbr=h{=xW&uE$}mZUD+7eaL8w^61|b`aB4`2RqA1tmbo$M^jqYFbdw6|4Tl8 z^7PsBi5JZWUmkk(|0m^j>U{axbY}8{`RGJeu-;6SOq=G++qnAun5H_UsxgMmNt1E9 zs%O*@R>W0JQ&o6-Cd}KyFR@3J;Few(pHTo#hMkOHk{qH@Mdy>`o;*$ll`3SW}SB93Xxlz$Z!l)@&0#MTG1&d^)6Y&HEGDg*_D$JtB1Kc3gH)aF-nA zp>I^FmFpt{e3obIZH-M;9CZqSoDO?a&@s%|tcGLo>HsN)kH0syN4oyn!~qbx%vT0U z%hqWJZXvBqMyrTM)IX2OG7yP7S4GY&TxEIbGV26gWF4pFmWP%qZP;VEDL3Y3`JEA^ zyJc)u6B;RN;88-8a6rO-3Hx%D#7!%R54(vUdq@BuM@RZsczsOIa}9dq3?Yze{{@FO zI_rbgLrijK9(r{s#G>=zofy1j+kCB|>vM(<+vcMsKb%ME vD`CUr#wkWz??dg8wQu$v;CJq77B)9DY-!je?A{@427oDMw__mbtXusRMgYaT diff --git a/bin/mega65.rom b/bin/mega65.rom index c299e1c5727878681036b04a7b6545cfab1681ae..563284aa00fde16aadc8f3ae976b1336fdb7083f 100644 GIT binary patch delta 5510 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 diff --git a/bin/mega65_pxlfont.rom b/bin/mega65_pxlfont.rom index e496e28528bc5a14aa3afb9c46c7fcc8b568a5a1..896f68ff2ce37989bbc64da64944d15a2685174a 100644 GIT binary patch delta 5510 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 diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 29f27e61..4dd452ca 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -112,7 +112,6 @@ Ideas for the future, most of them suitable for Mega65 or other power machines o * `LABEL`, `LGOTO` and `LGOSUB` - jump to label * some kind of subroutines with local variable namespace, possibly loaded from disc (like in Warsaw Basic 3.2) * for Mega65 mode, move variables to a separate memory area, consider extending variable name length -* DOS Wedge should ask (`ARE YOU SURE?`) before removing a file or formating the disc * `←V` (verify from tape) - if Kernal is extended to offer this feature * modulo function or opeerator * `DPEEK`, `DPOKE`, `QPEEK`, `QPOKE` - 2/4 byte `PEEK` and `POKE` variants diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index f214d91d..214d6d49 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -51,6 +51,52 @@ wedge_dos: wedge_dos_command: + // Check if command needs confirmation + + ldy #$00 + lda (TXTPTR), y + + cmp #$52 // 'R' - because 'RD' is a directory removal command + bne !+ + + iny + lda (TXTPTR), y + cmp #$44 // 'D' + bne wedge_dos_command_confirmed + beq wedge_dos_command_ask +!: + cmp #$4E // 'N' - for the disk format + beq !+ + cmp #$53 // 'S' - for the file scratch + bne wedge_dos_command_confirmed +!: + // This is probably a dangerous command - check further the syntax, + // if 'N:', 'S:', 'Nx:' or 'Sx:' (where 'x' is a digit) - ask for confirmation first + + iny + lda (TXTPTR), y + cmp #$3A // ':' - colon + beq wedge_dos_command_ask + + jsr is_09 + bcs wedge_dos_command_confirmed + + iny + lda (TXTPTR), y + cmp #$3A // ':' - colon + bne wedge_dos_command_confirmed + + // FALLTROUGH + +wedge_dos_command_ask: + + jsr helper_ask_if_sure + bcs_16 wedge_dos_clean_exit + + // FALLTROUGH + +wedge_dos_command_confirmed: + // Provide command name jsr wedge_dos_setnam @@ -62,14 +108,13 @@ wedge_dos_command: // Retrieve status, print it if not OK jsr JCLALL - jsr wedge_dos_status_get + jsr wedge_dos_status_get_no_new_line lda BUF+0 cmp #$30 // '0' bne wedge_dos_status_print - lda BUF+1 - cmp #$30 // '0' + eor BUF+1 bne wedge_dos_status_print // Clean-up and exit @@ -103,6 +148,10 @@ wedge_dos_status_get: jsr print_return + // FALLTROUGH + +wedge_dos_status_get_no_new_line: + // Here the flow is mostly the same as in the example from // https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive @@ -158,10 +207,19 @@ wedge_dos_status_get_done: wedge_dos_status: jsr wedge_dos_status_get +#if HAS_OPCODES_65C02 + bra wedge_dos_status_print_no_new_line +#else + jmp wedge_dos_status_print_no_new_line +#endif + +wedge_dos_status_print: + + jsr print_return // FALLTROUGH -wedge_dos_status_print: +wedge_dos_status_print_no_new_line: // Print buffered status @@ -205,7 +263,7 @@ wedge_dos_directory: bcs wedge_dos_basic_error // Ignore start address (2 first bytes) - XXX check for errors - + jsr JCHRIN bcs wedge_dos_basic_error jsr JCHRIN From 19cb0efa3203b9af973b612351c561116152ffae Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 17:20:11 +0200 Subject: [PATCH 029/130] routine moved to Mega65 extra ROM memory --- .../board_m65/4000.mega65_vectable_basic_1.s | 22 ++++++++++--------- src/basic/engine/prepare_direct_execution.s | 11 ++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/basic/board_m65/4000.mega65_vectable_basic_1.s b/src/basic/board_m65/4000.mega65_vectable_basic_1.s index 2f116b08..70339ac0 100644 --- a/src/basic/board_m65/4000.mega65_vectable_basic_1.s +++ b/src/basic/board_m65/4000.mega65_vectable_basic_1.s @@ -11,16 +11,17 @@ // Label definitions - .label VB1__INITMSG = $4000 + 2 * 0 - .label VB1__LINKPRG = $4000 + 2 * 1 - .label VB1__tokenise_line = $4000 + 2 * 2 - .label VB1__list_single_line = $4000 + 2 * 3 - .label VB1__print_packed_error = $4000 + 2 * 4 - .label VB1__print_packed_misc_str = $4000 + 2 * 5 - .label VB1__do_new = $4000 + 2 * 6 - .label VB1__do_clr = $4000 + 2 * 7 - .label VB1__do_restore = $4000 + 2 * 8 - .label VB1__cmd_mem_cont = $4000 + 2 * 9 + .label VB1__INITMSG = $4000 + 2 * 0 + .label VB1__LINKPRG = $4000 + 2 * 1 + .label VB1__tokenise_line = $4000 + 2 * 2 + .label VB1__list_single_line = $4000 + 2 * 3 + .label VB1__print_packed_error = $4000 + 2 * 4 + .label VB1__print_packed_misc_str = $4000 + 2 * 5 + .label VB1__do_new = $4000 + 2 * 6 + .label VB1__do_clr = $4000 + 2 * 7 + .label VB1__do_restore = $4000 + 2 * 8 + .label VB1__cmd_mem_cont = $4000 + 2 * 9 + .label VB1__prepare_direct_execution = $4000 + 2 * 10 #else @@ -36,5 +37,6 @@ .word do_clr .word do_restore .word cmd_mem_cont + .word prepare_direct_execution #endif diff --git a/src/basic/engine/prepare_direct_execution.s b/src/basic/engine/prepare_direct_execution.s index 1b2b1bb0..be63db97 100644 --- a/src/basic/engine/prepare_direct_execution.s +++ b/src/basic/engine/prepare_direct_execution.s @@ -1,4 +1,5 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -8,6 +9,14 @@ prepare_direct_execution: +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__prepare_direct_execution + jmp map_NORMAL + +#else + // Setup pointer to the statement lda # Date: Sun, 12 Jul 2020 17:58:42 +0200 Subject: [PATCH 030/130] DOS Wedge moved to Mega65 extra ROM memory --- src/basic/basic_commands_CC/cmd_cold.s | 2 +- .../basic_commands_CC/helper_ask_if_sure.s | 12 ++++++ .../board_m65/4000.mega65_vectable_basic_1.s | 12 ++++++ src/basic/board_m65/mega65_imports.s | 16 +++++++ src/basic/board_m65/mega65_proxies.s | 43 +++++++++++++++++++ src/basic/engine/is_alphanumeric.s | 1 + src/basic/engine/select_device.s | 2 + src/basic/wedge/wedge_dos.s | 11 +++++ 8 files changed, 98 insertions(+), 1 deletion(-) diff --git a/src/basic/basic_commands_CC/cmd_cold.s b/src/basic/basic_commands_CC/cmd_cold.s index be21a689..e7300a4a 100644 --- a/src/basic/basic_commands_CC/cmd_cold.s +++ b/src/basic/basic_commands_CC/cmd_cold.s @@ -11,4 +11,4 @@ cmd_cold: jsr JCLALL // for extra safety jmp (vector_reset) // hardware CPU vector !: - rts \ No newline at end of file + rts diff --git a/src/basic/basic_commands_CC/helper_ask_if_sure.s b/src/basic/basic_commands_CC/helper_ask_if_sure.s index f68a92f9..92d36947 100644 --- a/src/basic/basic_commands_CC/helper_ask_if_sure.s +++ b/src/basic/basic_commands_CC/helper_ask_if_sure.s @@ -1,4 +1,5 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -10,6 +11,14 @@ helper_ask_if_sure: +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__helper_ask_if_sure + jmp map_NORMAL + +#else + // First check, if we are in direct mode,; if not, do not ask ldx CURLIN+1 @@ -63,3 +72,6 @@ helper_ask_if_sure_ok: clc rts + + +#endif // ROM layout diff --git a/src/basic/board_m65/4000.mega65_vectable_basic_1.s b/src/basic/board_m65/4000.mega65_vectable_basic_1.s index 70339ac0..d49ed0fe 100644 --- a/src/basic/board_m65/4000.mega65_vectable_basic_1.s +++ b/src/basic/board_m65/4000.mega65_vectable_basic_1.s @@ -9,6 +9,7 @@ #if SEGMENT_BASIC_0 + // Label definitions .label VB1__INITMSG = $4000 + 2 * 0 @@ -22,6 +23,11 @@ .label VB1__do_restore = $4000 + 2 * 8 .label VB1__cmd_mem_cont = $4000 + 2 * 9 .label VB1__prepare_direct_execution = $4000 + 2 * 10 + .label VB1__helper_ask_if_sure = $4000 + 2 * 11 + +#if CONFIG_DOS_WEDGE + .label VB1__wedge_dos = $4000 + 2 * 12 +#endif #else @@ -38,5 +44,11 @@ .word do_restore .word cmd_mem_cont .word prepare_direct_execution + .word helper_ask_if_sure + +#if CONFIG_DOS_WEDGE + .word wedge_dos +#endif + #endif diff --git a/src/basic/board_m65/mega65_imports.s b/src/basic/board_m65/mega65_imports.s index ac3d8582..9536789f 100644 --- a/src/basic/board_m65/mega65_imports.s +++ b/src/basic/board_m65/mega65_imports.s @@ -12,7 +12,17 @@ .label poke_via_OLDTXT = BASIC_0.proxy_B1_poke_via_OLDTXT .label JCHROUT = BASIC_0.proxy_B1_JCHROUT .label JCLALL = BASIC_0.proxy_B1_JCLALL +#if CONFIG_DOS_WEDGE +.label JCLOSE = BASIC_0.proxy_B1_JCLOSE +.label JOPEN = BASIC_0.proxy_B1_JOPEN +#endif .label JMEMTOP = KERNAL_0.JMEMTOP +.label JSETFLS = KERNAL_0.JSETFLS +.label JSETNAM = KERNAL_0.JSETNAM +.label JGETIN = KERNAL_0.JGETIN +.label JCHKIN = KERNAL_0.JCHKIN +.label JCHRIN = KERNAL_0.JCHRIN +.label JREADST = KERNAL_0.JREADST .label plot_set = KERNAL_0.plot_set .label init_oldtxt = BASIC_0.init_oldtxt .label rom_revision_basic_string = BASIC_0.rom_revision_basic_string @@ -25,3 +35,9 @@ .label do_error_fetch = BASIC_0.do_error_fetch .label do_basic_error = BASIC_0.do_basic_error .label str_rev_question = BASIC_0.str_rev_question +#if CONFIG_DOS_WEDGE +.label fetch_character = BASIC_0.proxy_B1_fetch_character +.label fetch_character_skip_spaces = BASIC_0.proxy_B1_fetch_character_skip_spaces +.label fetch_uint8 = BASIC_0.proxy_B1_fetch_uint8 +.label shell_main_loop = BASIC_0.proxy_B1_shell_main_loop +#endif diff --git a/src/basic/board_m65/mega65_proxies.s b/src/basic/board_m65/mega65_proxies.s index 191f4e81..63c91283 100644 --- a/src/basic/board_m65/mega65_proxies.s +++ b/src/basic/board_m65/mega65_proxies.s @@ -36,6 +36,22 @@ proxy_B1_JCLALL: jsr JCLALL jmp map_BASIC_1 +#if CONFIG_DOS_WEDGE + +proxy_B1_JCLOSE: + + jsr map_NORMAL + jsr JCLOSE + jmp map_BASIC_1 + + +proxy_B1_JOPEN: + + jsr map_NORMAL + jsr JOPEN + jmp map_BASIC_1 + +#endif proxy_B1_JCHROUT: @@ -74,3 +90,30 @@ proxy_B1_print_features: jmp map_BASIC_1 #endif + +#if CONFIG_DOS_WEDGE + +proxy_B1_fetch_character: + + jsr map_NORMAL + jsr fetch_character + jmp map_BASIC_1 + +proxy_B1_fetch_character_skip_spaces: + + jsr map_NORMAL + jsr fetch_character_skip_spaces + jmp map_BASIC_1 + +proxy_B1_fetch_uint8: + + jsr map_NORMAL + jsr fetch_uint8 + jmp map_BASIC_1 + +proxy_B1_shell_main_loop: + + jsr map_NORMAL + jmp shell_main_loop + +#endif diff --git a/src/basic/engine/is_alphanumeric.s b/src/basic/engine/is_alphanumeric.s index 44c61a46..fa85c4c5 100644 --- a/src/basic/engine/is_alphanumeric.s +++ b/src/basic/engine/is_alphanumeric.s @@ -1,4 +1,5 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE diff --git a/src/basic/engine/select_device.s b/src/basic/engine/select_device.s index ba23425d..20fbc6b4 100644 --- a/src/basic/engine/select_device.s +++ b/src/basic/engine/select_device.s @@ -1,7 +1,9 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE +// XXX for Mega65, it should be available in BASIC_1 segment only select_device: diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index 214d6d49..b1a1a555 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -1,4 +1,5 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -10,6 +11,14 @@ wedge_dos: +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__wedge_dos + jmp map_NORMAL + +#else + // Prepare buffer - finish it with '0' lda #$00 @@ -354,4 +363,6 @@ wedge_dos_setnam: jmp JSETNAM +#endif // ROM layout + #endif // CONFIG_DOS_WEDGE From ac7fff95e5f78d0d2d46fc08e6333987ebc18803 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 12 Jul 2020 20:07:53 +0200 Subject: [PATCH 031/130] filled-in gaps in garbage collector implementation --- src/basic/basic_commands/cmd_let.s | 63 +++++++++++++++++++++-- src/basic/engine/varstr_garbage_collect.s | 33 +++++++++--- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 2482dfdb..395d4b1c 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -59,7 +59,26 @@ cmd_let_assign_integer: lda VALTYP bmi_16 do_TYPE_MISMATCH_error - // XXX finish the implementation +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif jmp do_NOT_IMPLEMENTED_error @@ -68,7 +87,26 @@ cmd_let_assign_float: lda VALTYP bmi_16 do_TYPE_MISMATCH_error - // XXX finish the implementation +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif jmp do_NOT_IMPLEMENTED_error @@ -79,6 +117,25 @@ cmd_let_assign_string: lda VALTYP bpl_16 do_TYPE_MISMATCH_error - // XXX finish the implementation +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 389ac6f4..96b4c027 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -213,22 +213,39 @@ varstr_garbage_collect_check_bptr: ldy #$01 #if CONFIG_MEMORY_MODEL_60K - - // XXX - // XXX: implement this - // XXX + + ldx # Date: Tue, 14 Jul 2020 22:19:33 +0200 Subject: [PATCH 032/130] some more work on string assignment --- CREDITS.md | 5 ++ src/basic/basic_commands/cmd_let.s | 71 +++++++++++++++++++++++ src/basic/engine/fetch_variable.s | 59 ++++++++++++++++++- src/basic/engine/varstr_free.s | 3 + src/basic/engine/varstr_garbage_collect.s | 3 + 5 files changed, 140 insertions(+), 1 deletion(-) diff --git a/CREDITS.md b/CREDITS.md index d4bef889..c1cfb957 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -24,6 +24,11 @@ * silverdr - for the floating point routines [description](https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics) * the [C64 Wiki](https://www.c64-wiki.com) contributors +## other + +* Gábor Lénárt - for his work on [XEMU Mega65 emulator](https://github.com/lgblgblgb/xemu) +* Mads Nielsen - for the [Kick Assembler](http://www.theweb.dk/KickAssembler/Main.html#frontpage) +
* ... and all the others we forgot diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 395d4b1c..2d36d6e7 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -117,6 +117,77 @@ cmd_let_assign_string: lda VALTYP bpl_16 do_TYPE_MISMATCH_error + // Copy the string descriptor to DSCPNT + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + ldy #$00 + lda (VARPNT), y + sta DSCPNT+0 + iny + lda (VARPNT), y + sta DSCPNT+1 + iny + lda (VARPNT), y + sta DSCPNT+2 + +#endif + + // First special case - check if the new string has size 0 + + // XXX + + // Check if the source and destination strings are the same (VARPNT should now point just after variable name) + + lda VARPNT+1 + cmp __FAC1+1 + bne !+ + iny + lda VARPNT+2 + cmp __FAC1+2 + bne !+ + + // If we are here, than both source and destination strings are the same - nothing more to be done + + rts +!: + // Strings are not the same - check if the new one is located within a text area, between TXTTAB and VARTAB + + // XXX + + // Check if size of both equals and the old on is above FRETOP + + // XXX + + // Check if new one is at least 3 bytes shorter and the old one is above FRETOP + + // XXX + + // Free the memory of the old string, it is not possible to reuse it + + // XXX + + // Check if the new string is a temporary one - if so, reuse already done alocation + + // XXX + + // No special case optimization is possible - alocate new memory area and copy the string + + // XXX + #if CONFIG_MEMORY_MODEL_60K // XXX diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index 0bb308cd..a452ec9e 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -133,7 +133,7 @@ fetch_variable_find_addr_loop: fetch_variable_adjust_VARPNT: - // Adjust VARPNT to point just after variable name and quit + // Adjust VARPNT to point just after variable name (XXX is it needed?) and quit #if !HAS_OPCODES_65CE02 @@ -170,15 +170,72 @@ fetch_variable_alocate: // First check if we have enough space for a new descriptor +#if CONFIG_MEMORY_MODEL_60K + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif // If needed, move all the arrays up +#if CONFIG_MEMORY_MODEL_60K + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif // Set pointer to new variable +#if CONFIG_MEMORY_MODEL_60K + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif // Fill-in the new variable name, descriptor (it is enough to zero first 2 bytes of content) diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index c61aae3a..222385b7 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -11,6 +11,9 @@ // XXX test this routine +// XXX handle strings located in program area +// XXX change DSCPNT format to be compliant with all other descriptors + varstr_free: // First copy the string descriptor data to DSCPNT diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 96b4c027..e4ec3e8d 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -4,6 +4,9 @@ // XXX test this routine +// XXX change DSCPNT format to be compliant with all other descriptors + + varstr_garbage_collect: // The routine utilizes the 'shift_mem_up' - which leaves INDEX+0 and INDEX+1 From 26ce9d3b584b990ef0f33292331b7c7fba4ad3ea Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 14 Jul 2020 23:13:17 +0200 Subject: [PATCH 033/130] safer vector handling in some Kernal routines --- src/kernal/interrupts/hw_entry_irq.s | 4 ++-- src/kernal/keyboard/scnkey.s | 21 ++++++++++++++++----- src/kernal/keyboard/scnkey_set_keytab.s | 4 ++-- src/kernal/keyboard/scnkey_via_keylog.s | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 src/kernal/keyboard/scnkey_via_keylog.s diff --git a/src/kernal/interrupts/hw_entry_irq.s b/src/kernal/interrupts/hw_entry_irq.s index 8177de7c..0424705a 100644 --- a/src/kernal/interrupts/hw_entry_irq.s +++ b/src/kernal/interrupts/hw_entry_irq.s @@ -29,8 +29,8 @@ hw_entry_irq: bne irq_handler_brk // Not caused by BRK - call interrupt routine (only if initialised) - lda CINV - ora CINV+1 + // Routine on zeropage = assuming not initialized + lda CINV+1 beq !+ jmp (CINV) !: diff --git a/src/kernal/keyboard/scnkey.s b/src/kernal/keyboard/scnkey.s index ae1421ff..cf832bf0 100644 --- a/src/kernal/keyboard/scnkey.s +++ b/src/kernal/keyboard/scnkey.s @@ -147,7 +147,22 @@ scnkey_bucky_loop: // Set KEYTAB vector - jsr via_keylog // XXX for some CPUs we have indirect jsr + lda KEYLOG+1 + bne !+ + jsr scnkey_set_keytab // KEYLOG routine on zeropage? most likely vector not set +#if HAS_OPCODES_65C02 + bra scnkey_keytab_set_done +#else + jmp scnkey_keytab_set_done +#endif +!: +#if HAS_OPCODES_65CE02 + jsr_ind KEYLOG +#else + jsr scnkey_via_keylog +#endif + +scnkey_keytab_set_done: #if CONFIG_JOY2_CURSOR @@ -483,8 +498,4 @@ scnkey_early_repeat: rts -via_keylog: - jmp (KEYLOG) - - #endif // no CONFIG_LEGACY_SCNKEY diff --git a/src/kernal/keyboard/scnkey_set_keytab.s b/src/kernal/keyboard/scnkey_set_keytab.s index 77ad45aa..5299b0b8 100644 --- a/src/kernal/keyboard/scnkey_set_keytab.s +++ b/src/kernal/keyboard/scnkey_set_keytab.s @@ -38,8 +38,8 @@ scnkey_set_keytab: cmp #$FF bne scnkey_valid_offset - // $FF means we shouldn't decode anything, mark this by setting high byte - // of KEYTAB to 0 (I don't think anyone would put keyboard decoding table + // $FF means we should not decode anything, mark this by setting high byte + // of KEYTAB to 0 (I do not think anyone would put keyboard decoding table // at zeropage) lda #$00 beq !+ // branch always diff --git a/src/kernal/keyboard/scnkey_via_keylog.s b/src/kernal/keyboard/scnkey_via_keylog.s new file mode 100644 index 00000000..d23f27d1 --- /dev/null +++ b/src/kernal/keyboard/scnkey_via_keylog.s @@ -0,0 +1,14 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# X16 * #IGNORE +// #LAYOUT# * KERNAL_0 #TAKE +// #LAYOUT# * * #IGNORE + +// Short helper jump-via-vector routine, to set the keyboard matrix + +#if !HAS_OPCODES_65CE02 + +scnkey_via_keylog: + + jmp (KEYLOG) + +#endif From 127b71f67f4e8bc18214e73a3692f8f1f370701e Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 15 Jul 2020 19:54:22 +0200 Subject: [PATCH 034/130] string handling fixes --- src/basic/basic_commands/cmd_let.s | 25 ++++- src/basic/engine/ad9e.frmevl.s | 16 +++- src/basic/engine/fetch_variable.s | 107 +++++++++++++--------- src/basic/engine/varstr_alloc.s | 2 +- src/basic/engine/varstr_alloc_fretop.s | 2 + src/basic/engine/varstr_free.s | 3 +- src/basic/engine/varstr_free_fretop.s | 2 + src/basic/engine/varstr_garbage_collect.s | 3 +- 8 files changed, 107 insertions(+), 53 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 2d36d6e7..706ea931 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -9,6 +9,7 @@ cmd_let: // Fetch variable name, should be followed by assign operator jsr fetch_variable + bcs_16 do_SYNTAX_error jsr injest_assign bcs_16 do_SYNTAX_error @@ -148,15 +149,35 @@ cmd_let_assign_string: // First special case - check if the new string has size 0 + lda DSCPNT+0 + bne cmd_let_assign_string_not_empty + + // XXX free old string data + + // Set the new variable as size 0 + +#if CONFIG_MEMORY_MODEL_60K + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + +#endif + + rts + +cmd_let_assign_string_not_empty: // Check if the source and destination strings are the same (VARPNT should now point just after variable name) - lda VARPNT+1 + lda VARPNT+0 cmp __FAC1+1 bne !+ iny - lda VARPNT+2 + lda VARPNT+1 cmp __FAC1+2 bne !+ diff --git a/src/basic/engine/ad9e.frmevl.s b/src/basic/engine/ad9e.frmevl.s index c831e153..447f746d 100644 --- a/src/basic/engine/ad9e.frmevl.s +++ b/src/basic/engine/ad9e.frmevl.s @@ -68,9 +68,19 @@ FRMEVL_loop: // $7F has to be a function cmp #$80 // check for a token - bcc FRMEVL_execute_function + bcs FRMEVL_execute_function - // There are 2 possibilities left - a floating point value or a variable + // Check for a variable + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + jsr fetch_variable + bcc FRMEVL_got_value + + // There is one possibility left - a floating point value // XXX implement this part @@ -279,7 +289,7 @@ FRMEVL_push_operator_address: // as this is the place where unary operator support calls tsx - cpx #$40 // XXX is this a safe threshold? + cpx #$60 // XXX is this a safe threshold? bcc_16 do_FORMULA_TOO_COMPLEX_error // Push the operator address to stack, in a form diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index a452ec9e..995aaff2 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -2,6 +2,10 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE +// +// Carry set = failure, not recognized variable name +// + fetch_variable: @@ -14,8 +18,17 @@ fetch_variable: jsr fetch_character_skip_spaces jsr is_AZ - bcs_16 do_SYNTAX_error + bcc !+ +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + + sec + rts +!: sta VARNAM+0 // Fetch the (optional) second character @@ -96,7 +109,7 @@ fetch_variable_find_addr_loop: cmp ARYTAB+1 bne !+ lda VARPNT+0 - cmp VARPNT+0 + cmp ARYTAB+0 beq fetch_variable_alocate !: // Compare current variable name with searched one @@ -151,6 +164,7 @@ fetch_variable_adjust_VARPNT: #endif + clc rts fetch_variable_find_addr_next: @@ -168,82 +182,87 @@ fetch_variable_find_addr_next: fetch_variable_alocate: - // First check if we have enough space for a new descriptor + // First check if we have enough space for a new descriptor (if FRETOP - STREND >= 7) -#if CONFIG_MEMORY_MODEL_60K - - // XXX - // XXX: implement this - // XXX + sec + lda FRETOP+0 + sbc STREND+0 + pha + lda FRETOP+1 + sbc STREND+1 + bne !+ // branch if high byte of result > 0 -#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX consider optimized version without multiple JSRs + pla + cmp #$07 + bcs fetch_variable_alocate_space_OK - // XXX - // XXX: implement this - // XXX + jmp do_OUT_OF_MEMORY_error +!: + pla -#else // CONFIG_MEMORY_MODEL_38K + // FALLTROUGH - // XXX - // XXX: implement this - // XXX - -#endif +fetch_variable_alocate_space_OK: // If needed, move all the arrays up #if CONFIG_MEMORY_MODEL_60K // XXX - // XXX: implement this + // XXX: implement this for arrays // XXX #elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K // XXX consider optimized version without multiple JSRs // XXX - // XXX: implement this + // XXX: implement this for arrays // XXX #else // CONFIG_MEMORY_MODEL_38K // XXX - // XXX: implement this + // XXX: implement this for arrays // XXX #endif - // Set pointer to new variable + // Adjust ARYTAB and STREND -#if CONFIG_MEMORY_MODEL_60K - - // XXX - // XXX: implement this - // XXX + clc + lda STREND+0 + adc #$07 + sta STREND+0 + bcc !+ + inc STREND+1 +!: -#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX consider optimized version without multiple JSRs - - // XXX - // XXX: implement this - // XXX - -#else // CONFIG_MEMORY_MODEL_38K - - // XXX - // XXX: implement this - // XXX - -#endif + clc + lda ARYTAB+0 + adc #$07 + sta ARYTAB+0 + bcc !+ + inc ARYTAB+1 +!: + // VARPNT already points to the start of the variable descriptor // Fill-in the new variable name, descriptor (it is enough to zero first 2 bytes of content) ldy #$00 #if CONFIG_MEMORY_MODEL_60K - - // XXX + + ldx # Date: Wed, 15 Jul 2020 22:04:46 +0200 Subject: [PATCH 035/130] more work on string support --- src/basic/basic_commands/cmd_let.s | 100 ++++++++++++++---- src/basic/engine/varstr_alloc.s | 18 ++-- src/basic/engine/varstr_alloc_fretop.s | 8 +- src/basic/engine/varstr_free.s | 59 ++++++----- src/basic/engine/varstr_free_fretop.s | 4 +- src/basic/engine/varstr_garbage_collect.s | 13 ++- .../memory/under_rom_peek_fetch_46k_50k.s | 4 +- 7 files changed, 133 insertions(+), 73 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 706ea931..f74a7bb1 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -9,9 +9,19 @@ cmd_let: // Fetch variable name, should be followed by assign operator jsr fetch_variable + +#if HAS_OPCODES_65CE02 bcs_16 do_SYNTAX_error jsr injest_assign bcs_16 do_SYNTAX_error +#else + bcs !+ + jsr injest_assign + bcc !++ +!: + jmp do_SYNTAX_error +!: +#endif // Determine variable type and push it to the stack @@ -149,12 +159,67 @@ cmd_let_assign_string: // First special case - check if the new string has size 0 - lda DSCPNT+0 + lda __FAC1+0 bne cmd_let_assign_string_not_empty - // XXX free old string data + // Yes, it is empty - check if the old one is, free it if necessary - // Set the new variable as size 0 + lda DSCPNT+0 + bne !+ + jsr varstr_free_DSCPNT_set +!: + // Set the new variable as empty string + + ldy #$00 + lda #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # $00 #if CONFIG_MEMORY_MODEL_60K - ldx # $01 @@ -127,6 +134,6 @@ varstr_free_inside: #if CONFIG_MEMORY_MODEL_60K jmp poke_under_roms #else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - sta (DSCPNT), y + sta (DSCPNT+1), y rts #endif diff --git a/src/basic/engine/varstr_free_fretop.s b/src/basic/engine/varstr_free_fretop.s index 9f44b07c..f1abde57 100644 --- a/src/basic/engine/varstr_free_fretop.s +++ b/src/basic/engine/varstr_free_fretop.s @@ -8,11 +8,11 @@ // XXX change DSCPNT to use standard descriptor format -varstr_FRETOP_up: // DSCPNT+2 - bytes to increment FRETO, uses DSCPNT+2 +varstr_FRETOP_up: // DSCPNT+0 - bytes to increment FRETO clc lda FRETOP+0 - adc DSCPNT+2 + adc DSCPNT+0 sta FRETOP+0 bcc !+ inc FRETOP+1 diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 6d5f30bd..e13dd68c 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -4,7 +4,6 @@ // XXX test this routine -// XXX change DSCPNT to use standard descriptor format varstr_garbage_collect: @@ -323,13 +322,13 @@ varstr_garbage_collect_unused: // XXX move these routines to separate files -varstr_TXTPTR_down_A: // .A - bytes to decrease TXTPTR, uses DSCPNT+2 +varstr_TXTPTR_down_A: // .A - bytes to decrease TXTPTR, uses DSCPNT+0 - sta DSCPNT+2 + sta DSCPNT+0 sec lda TXTPTR+0 - sbc DSCPNT+2 + sbc DSCPNT+0 sta TXTPTR+0 bcs !+ dec TXTPTR+1 @@ -337,13 +336,13 @@ varstr_TXTPTR_down_A: // .A - bytes to decrease TXTPTR, uses DS rts -varstr_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+2 +varstr_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+0 - sta DSCPNT+2 + sta DSCPNT+0 clc lda INDEX+0 - adc DSCPNT+2 + adc DSCPNT+0 sta INDEX+0 bcc !+ dec INDEX+1 diff --git a/src/basic/memory/under_rom_peek_fetch_46k_50k.s b/src/basic/memory/under_rom_peek_fetch_46k_50k.s index 43e3e7bf..c1b4fc9c 100644 --- a/src/basic/memory/under_rom_peek_fetch_46k_50k.s +++ b/src/basic/memory/under_rom_peek_fetch_46k_50k.s @@ -68,7 +68,7 @@ peek_under_roms_via_VARPNT: jmp peek_under_roms_finalize #endif -peek_under_roms_via_DSCPNT: +peek_under_roms_via_DSCPNT_PLUS_1: // Unmap BASIC lower ROM @@ -77,7 +77,7 @@ peek_under_roms_via_DSCPNT: // Retrieve value from under ROMs - lda (DSCPNT), y + lda (DSCPNT+1), y #if HAS_OPCODES_65C02 bra peek_under_roms_finalize From 4a94af2fc79c7c8449cc706fb8071501aba19fc2 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 15 Jul 2020 22:59:52 +0200 Subject: [PATCH 036/130] assign string from text area to a new variable works now --- src/basic/basic_commands/cmd_let.s | 31 ++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index f74a7bb1..d212a6bd 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -175,6 +175,7 @@ cmd_let_assign_string: #if CONFIG_MEMORY_MODEL_60K ldx # Date: Thu, 16 Jul 2020 15:45:57 +0200 Subject: [PATCH 037/130] string variables can be assigned both in direct and program mode --- src/basic/basic_commands/cmd_let.s | 63 +++++++++++++------ .../helper_let_strvarcpy_46K_50K.s | 46 ++++++++++++++ src/basic/engine/ad9e.frmevl.s | 43 ++++++++++++- src/basic/engine/helper_frmevl_46K_50K.s | 40 ++++++++++++ src/basic/engine/varstr_alloc.s | 37 ++++++----- src/basic/engine/varstr_free.s | 4 +- 6 files changed, 192 insertions(+), 41 deletions(-) create mode 100644 src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s create mode 100644 src/basic/engine/helper_frmevl_46K_50K.s diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index d212a6bd..9a81e8a0 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -175,7 +175,7 @@ cmd_let_assign_string: #if CONFIG_MEMORY_MODEL_60K ldx # $00 + ldy #$00 #if CONFIG_MEMORY_MODEL_60K - ldx # $01 - lda FRETOP+0 + ldy #$01 #if CONFIG_MEMORY_MODEL_60K - ldx # Date: Thu, 16 Jul 2020 19:06:40 +0200 Subject: [PATCH 038/130] fixed comparing uninitialized streing descriptor --- src/basic/basic_commands/cmd_let.s | 50 +++++++++++++++---- .../helper_let_strdesccpy_46K_50K.s | 40 +++++++++++++++ 2 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 src/basic/basic_commands/helper_let_strdesccpy_46K_50K.s diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 9a81e8a0..580b4221 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -11,16 +11,20 @@ cmd_let: jsr fetch_variable #if HAS_OPCODES_65CE02 + bcs_16 do_SYNTAX_error jsr injest_assign bcs_16 do_SYNTAX_error + #else + bcs !+ jsr injest_assign bcc !++ !: jmp do_SYNTAX_error !: + #endif // Determine variable type and push it to the stack @@ -132,16 +136,21 @@ cmd_let_assign_string: #if CONFIG_MEMORY_MODEL_60K - // XXX - // XXX: implement this - // XXX + ldx # Date: Thu, 16 Jul 2020 19:59:16 +0200 Subject: [PATCH 039/130] fixed regression in memory allocation routine --- src/basic/basic_commands/cmd_let.s | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 580b4221..bfd8822b 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -273,8 +273,16 @@ cmd_let_assign_string_not_text_area: // XXX - // No special case optimization is possible - alocate new memory area + // No special case optimization is possible + // Free the memory belonging to the old string + // XXX + // jsr varstr_free_DSCPNT_set + + + // And allocate memory for the new string + + lda __FAC1+0 ldy #$00 #if CONFIG_MEMORY_MODEL_60K @@ -288,9 +296,6 @@ cmd_let_assign_string_not_text_area: #endif - lda __FAC1+0 - sta (VARPNT), y - jsr varstr_alloc // Copy the string @@ -344,8 +349,4 @@ cmd_let_assign_string_not_text_area: #endif - // Free the memory of the old string - - // XXX - rts From 8c70b5112312d69c873303d0122d35a3b79ab3a4 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 16 Jul 2020 21:02:06 +0200 Subject: [PATCH 040/130] removed some unneeded code --- src/basic/basic_commands/cmd_let.s | 4 +- src/basic/engine/varstr_free.s | 47 +------------------ .../memory/under_rom_peek_fetch_46k_50k.s | 17 ------- 3 files changed, 4 insertions(+), 64 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index bfd8822b..880893d8 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -175,7 +175,7 @@ cmd_let_assign_string: lda DSCPNT+0 bne !+ - jsr varstr_free_DSCPNT_set + jsr varstr_free !: // Set the new variable as empty string @@ -277,7 +277,7 @@ cmd_let_assign_string_not_text_area: // Free the memory belonging to the old string // XXX - // jsr varstr_free_DSCPNT_set + // jsr varstr_free // And allocate memory for the new string diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index 95fb88b1..a2705e8d 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -6,57 +6,14 @@ // Releases back memory used by string // // Input: -// - DSCPNT+1, DSCPNT+2 - pointer to string descriptor +// - DSCPNT+1, DSCPNT+2 - pointer to string // // XXX test this routine // XXX check if this entry point is needed -varstr_free: // XXX is it needed? if not, we do not need peek_under_roms_via_DSCPNT_PLUS_1 - // First copy the string descriptor data to DSCPNT - // XXX write optimized version for CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - - ldy #$00 - -#if CONFIG_MEMORY_MODEL_60K - ldx # Date: Thu, 16 Jul 2020 22:21:03 +0200 Subject: [PATCH 041/130] filled-in gaps in string memory release routine --- src/basic/basic_commands/cmd_let.s | 10 +++------- src/basic/engine/varstr_cmp_fretop.s | 23 +++++++++++++++++++++++ src/basic/engine/varstr_free.s | 25 +++++++++++++++---------- 3 files changed, 41 insertions(+), 17 deletions(-) create mode 100644 src/basic/engine/varstr_cmp_fretop.s diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 880893d8..02c811ae 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -171,12 +171,10 @@ cmd_let_assign_string: lda __FAC1+0 bne cmd_let_assign_string_not_empty - // Yes, it is empty - check if the old one is, free it if necessary + // Yes, it is empty - free the old one - lda DSCPNT+0 - bne !+ jsr varstr_free -!: + // Set the new variable as empty string ldy #$00 @@ -276,9 +274,7 @@ cmd_let_assign_string_not_text_area: // No special case optimization is possible // Free the memory belonging to the old string - // XXX - // jsr varstr_free - + jsr varstr_free // And allocate memory for the new string diff --git a/src/basic/engine/varstr_cmp_fretop.s b/src/basic/engine/varstr_cmp_fretop.s new file mode 100644 index 00000000..fda23d4e --- /dev/null +++ b/src/basic/engine/varstr_cmp_fretop.s @@ -0,0 +1,23 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Check string address (DSCPNT+1/+2) vs FRETOP +// +// Output: +// - Zero flag set - this is the first variable of the string area +// - Carry flag set - this string belongs to the string area + + +varstr_cmp_fretop: + + lda DSCPNT+2 + cmp FRETOP+1 + beq !+ + rts +!: + lda DSCPNT+2 + cmp FRETOP+1 + rts + diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index a2705e8d..e9a30778 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -6,27 +6,32 @@ // Releases back memory used by string // // Input: +// - DSCPNT+0 - string size // - DSCPNT+1, DSCPNT+2 - pointer to string // // XXX test this routine -// XXX check if this entry point is needed varstr_free: - // XXX consider moving size check (DSCPNT+0) here + // Check the string size - do not do anything if 0 - // XXX - // XXX check if string is located above FRETOP, handle case if it is not - // XXX + lda DSCPNT+0 + bne !+ + rts +!: + // Check if string is above FRETOP (in string area) - // Quick check - is the string the lowest one? + jsr varstr_cmp_fretop + bcs !+ + + // No, it does not belong to string area - quit + + rts +!: + // Check if this is the lowest string - cmp FRETOP+0 - bne varstr_free_inside - lda DSCPNT+2 - cmp FRETOP+1 bne varstr_free_inside // This is the lowest string - so just increase FRETOP, this way From 83ab5eb98d235c28bcc5123545699e7e9ed70815 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 16 Jul 2020 22:29:40 +0200 Subject: [PATCH 042/130] fix problem with determining string location --- src/basic/engine/varstr_cmp_fretop.s | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/basic/engine/varstr_cmp_fretop.s b/src/basic/engine/varstr_cmp_fretop.s index fda23d4e..d11540bb 100644 --- a/src/basic/engine/varstr_cmp_fretop.s +++ b/src/basic/engine/varstr_cmp_fretop.s @@ -17,7 +17,6 @@ varstr_cmp_fretop: beq !+ rts !: - lda DSCPNT+2 - cmp FRETOP+1 + lda DSCPNT+1 + cmp FRETOP+0 rts - From 6c930e8367394194572770a55cd6b4b0ae223cba Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 17 Jul 2020 18:37:22 +0200 Subject: [PATCH 043/130] fixed bug in string free preserving size in wrong place --- src/basic/engine/varstr_free.s | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index e9a30778..6eef2046 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -59,18 +59,9 @@ varstr_free_inside: // This is not the lowest string; mark it as free // First preserve the string size, it will make it easier for the garbage collector - lda DSCPNT+0 - tay - dey + // Increase DSCPNT+1/+2 to point to the back-pointer minus 1 -#if CONFIG_MEMORY_MODEL_60K - ldx # $01 + // Now fill-in the back-pointer with 0's + + tya + iny + +#if CONFIG_MEMORY_MODEL_60K + jsr poke_under_roms +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + sta (DSCPNT+1), y +#endif + + iny #if CONFIG_MEMORY_MODEL_60K jmp poke_under_roms From dafb902a44680240227e5d414a8cbe21d5a328a3 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 17 Jul 2020 21:12:17 +0200 Subject: [PATCH 044/130] saved few bytes in hariable handling code --- src/basic/engine/varstr_free.s | 3 +-- src/basic/engine/varstr_garbage_collect.s | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index 6eef2046..c86cf3f7 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -70,9 +70,8 @@ varstr_free_inside: bcc !+ inc DSCPNT+2 !: - // Put the size - this value will be used by the garbage collector // XXX maybe size-1 would be better? + // Put the size-1, garbage collector will make use of this value - inc DSCPNT+0 lda DSCPNT+0 ldy #$00 diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index e13dd68c..d68a3ca2 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -87,7 +87,7 @@ varstr_garbage_collect_check_bptr: dew TXTPTR #endif - // Check whether the back-pointer is NULL + // Copy the back-pointer to OLDTXT, check if it is NULL ldy #$00 @@ -293,11 +293,7 @@ varstr_garbage_collect_unused: ldy #$00 lda (TXTPTR), y - - // Decrement string length by 1, it will be easier to perform calculations - tax - dex // Increase INDEX (shift offset) by string length + back-pointer length From 7ad4abfcda9853e5cea04d3409e1c1cb4c1e7ee7 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 17 Jul 2020 21:27:25 +0200 Subject: [PATCH 045/130] added screenshot, small documentation update --- README.md | 2 ++ doc/Extended-BASIC-TODO.md | 64 +++++++++++++++++++++++++++++++++++++ doc/Extended-BASIC.md | 64 ------------------------------------- doc/screenshot-demo.png | Bin 0 -> 89078 bytes 4 files changed, 66 insertions(+), 64 deletions(-) create mode 100644 doc/Extended-BASIC-TODO.md create mode 100644 doc/screenshot-demo.png diff --git a/README.md b/README.md index aa1af581..6823f2fd 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ A project to create unencumbered open-source ROMs for use on selected retro comp * [license](./LICENSE) information and list of major contributors * [credits](./CREDITS.md) to people whose work was of great help to us +![screenshot demonstrating some features](./doc/screenshot-demo.png) + # Problem Statement and Motivation The copyrights of various old computer system ROMs are still alive, and together with trademarks, can present significant diff --git a/doc/Extended-BASIC-TODO.md b/doc/Extended-BASIC-TODO.md new file mode 100644 index 00000000..78194e9b --- /dev/null +++ b/doc/Extended-BASIC-TODO.md @@ -0,0 +1,64 @@ + +# Planned BASIC features, when V2 compatibility is reached + +Ideas for the future, most of them suitable for Mega65 or other power machines only + +* sound support +* 2D graphics support +* turtle graphics +* sprite support, including collision callback +* custom character set support +* sprite/character design within program, in a way similar to Simons BASIC +* joystick/mouse/lightpen/paddle commands/functions +* matrix operations +* `DISPOSE` with variable/array as parameter should remove the variable/array from memory +* `BLOAD`, `BVERIFY` and `BSAVE` should have syntax compatible with BASIC V7/V10 +* it should be possible to intercept Kernal errors from BASIC (prevent `?FILE NOT FOUND ERROR IN ...`, etc.); `ON ERROR GOTO` ? +* support for numbers in hexadecimal and binary formats +* `CGOTO` and `CGOSUB` - computatiuonal versions, should accept expressions +* `LABEL`, `LGOTO` and `LGOSUB` - jump to label +* some kind of subroutines with local variable namespace, possibly loaded from disc (like in Warsaw Basic 3.2) +* for Mega65 mode, move variables to a separate memory area, consider extending variable name length +* `←V` (verify from tape) - if Kernal is extended to offer this feature +* modulo function or opeerator +* `DPEEK`, `DPOKE`, `QPEEK`, `QPOKE` - 2/4 byte `PEEK` and `POKE` variants +* all the functions/commands accepting memory addresses should be able to access the whole Mega65 memory +* ability to limit memory used by basic to standard 38K or to 46K (memory model switch) +* `XOR` operator +* `AUTO` - line auto numbering +* `RENUMBER` for chanign the line numbers +* `IF ... THEN ... ELSE`, `BEGIN ... BEND` +* consider `BOOT` command +* possibly some commands for creating menus and dialog boxes +* more configurable `INPUT` +* `PRINT USING`, `PRINT AT(x, y)`, `PRINT CENTRE` +* `CURSOR` command from BASIC V10 +* `RESTORE` should accept lline number as argument +* hex/dec conversion functions +* `DELETE` command to delete several BASIC lines, as in BASIC V10 +* `FOR` loop should accept integer variable as index +* `FETCH`, `STASH`, `SWAP` - REU support +* `DMA` command for Mega65 +* geoRAM support +* `GO 64` / `GO 65` should enable/disable C64 compatibility mode on Mega65 +* `NSYS` for Mega65 - native `SYS` for Mega65, should not switch to C64 compatibilty mode +* `DO ... LOOP`, `DO ... UNTIL`, `DO ... WHILE`, `EXIT` +* `SEEK#` to read-and-forget n bytes +* `RECORD#` command from BASIC V10 +* `GETKEY` from BASIC V10 +* `HELP` command from BASIC V7/V10 +* function to find substring position +* `WINDOW` command from BASIC V7 +* functions to return cursor position +* `TRAP` and `RESUME` +* `SET DEF` and `SET DISK` from BASIC V10 +* `SLEEP` from BASIC V10 +* `TRON` / `TROFF` - program tracing +* `TYPE` command from BASIC V10 +* `RUN` should be able to run program from device, as in BASIC V10 +* `PAGE` and `DELAY` commands from Simons BASIC, or something similar +* `DUMP` command from Simons BASIC, or something similar +* function to insert a substring starting from given position +* function to generate string of n duplicated characters +* function to retrieve fractional part of a number +* command to fill text screen area with a character, inverse screen area, scroll, or change fg/bg color of screen area diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 4dd452ca..68f8c135 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -91,67 +91,3 @@ Clears the screen content. ### `DISPOSE` Runs the garbage collector - disposes outdated strings. - -# Planned BASIC features, when V2 compatibility is reached - -Ideas for the future, most of them suitable for Mega65 or other power machines only - -* sound support -* 2D graphics support -* turtle graphics -* sprite support, including collision callback -* custom character set support -* sprite/character design within program, in a way similar to Simons BASIC -* joystick/mouse/lightpen/paddle commands/functions -* matrix operations -* `DISPOSE` with variable/array as parameter should remove the variable/array from memory -* `BLOAD`, `BVERIFY` and `BSAVE` should have syntax compatible with BASIC V7/V10 -* it should be possible to intercept Kernal errors from BASIC (prevent `?FILE NOT FOUND ERROR IN ...`, etc.); `ON ERROR GOTO` ? -* support for numbers in hexadecimal and binary formats -* `CGOTO` and `CGOSUB` - computatiuonal versions, should accept expressions -* `LABEL`, `LGOTO` and `LGOSUB` - jump to label -* some kind of subroutines with local variable namespace, possibly loaded from disc (like in Warsaw Basic 3.2) -* for Mega65 mode, move variables to a separate memory area, consider extending variable name length -* `←V` (verify from tape) - if Kernal is extended to offer this feature -* modulo function or opeerator -* `DPEEK`, `DPOKE`, `QPEEK`, `QPOKE` - 2/4 byte `PEEK` and `POKE` variants -* all the functions/commands accepting memory addresses should be able to access the whole Mega65 memory -* ability to limit memory used by basic to standard 38K or to 46K (memory model switch) -* `XOR` operator -* `AUTO` - line auto numbering -* `RENUMBER` for chanign the line numbers -* `IF ... THEN ... ELSE`, `BEGIN ... BEND` -* consider `BOOT` command -* possibly some commands for creating menus and dialog boxes -* more configurable `INPUT` -* `PRINT USING`, `PRINT AT(x, y)`, `PRINT CENTRE` -* `CURSOR` command from BASIC V10 -* `RESTORE` should accept lline number as argument -* hex/dec conversion functions -* `DELETE` command to delete several BASIC lines, as in BASIC V10 -* `FOR` loop should accept integer variable as index -* `FETCH`, `STASH`, `SWAP` - REU support -* `DMA` command for Mega65 -* geoRAM support -* `GO 64` / `GO 65` should enable/disable C64 compatibility mode on Mega65 -* `NSYS` for Mega65 - native `SYS` for Mega65, should not switch to C64 compatibilty mode -* `DO ... LOOP`, `DO ... UNTIL`, `DO ... WHILE`, `EXIT` -* `SEEK#` to read-and-forget n bytes -* `RECORD#` command from BASIC V10 -* `GETKEY` from BASIC V10 -* `HELP` command from BASIC V7/V10 -* function to find substring position -* `WINDOW` command from BASIC V7 -* functions to return cursor position -* `TRAP` and `RESUME` -* `SET DEF` and `SET DISK` from BASIC V10 -* `SLEEP` from BASIC V10 -* `TRON` / `TROFF` - program tracing -* `TYPE` command from BASIC V10 -* `RUN` should be able to run program from device, as in BASIC V10 -* `PAGE` and `DELAY` commands from Simons BASIC, or something similar -* `DUMP` command from Simons BASIC, or something similar -* function to insert a substring starting from given position -* function to generate string of n duplicated characters -* function to retrieve fractional part of a number -* command to fill text screen area with a character, inverse screen area, scroll, or change fg/bg color of screen area diff --git a/doc/screenshot-demo.png b/doc/screenshot-demo.png new file mode 100644 index 0000000000000000000000000000000000000000..d9fec2f94a3d08e25cb23c2422f0d26cc6d4f276 GIT binary patch literal 89078 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 literal 0 HcmV?d00001 From 3b67f91c533eb7e715e1f0fb8690a6eac1bf7047 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 17 Jul 2020 21:34:18 +0200 Subject: [PATCH 046/130] small fixes to README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6823f2fd..ed96c5b8 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ # open-roms +![screenshot demonstrating some features](./doc/screenshot-demo.png) + A project to create unencumbered open-source ROMs for use on selected retro computers. Besides this manifest, the following documents are available: * [implementation status](./STATUS.md) of various APIs and functionalities * [configuration options](./CONFIG.md) for those willing to compile their own, customized ROM set * [BASIC extensions](doc/Extended-BASIC.md) -* [development guide](./doc/Development.md) for those interested in OpenROMs technical aspects +* [development guide](./doc/Development.md) for those interested in technical aspects * [license](./LICENSE) information and list of major contributors * [credits](./CREDITS.md) to people whose work was of great help to us -![screenshot demonstrating some features](./doc/screenshot-demo.png) - # Problem Statement and Motivation The copyrights of various old computer system ROMs are still alive, and together with trademarks, can present significant From 50a28c2da90e2c6f5aa344b6ce8d099a46e7fb15 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 17 Jul 2020 22:50:38 +0200 Subject: [PATCH 047/130] fixed wrong buyte transfer direction --- src/basic/engine/varstr_garbage_collect.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index d68a3ca2..a089c081 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -39,7 +39,7 @@ varstr_garbage_collect: varstr_garbage_collect_loop: - // Check if this was the last string (if FRETOP+INDEX == TXTPTR), use OLDTXT as temporary storage + // Check if this was the last (lowest) string (if FRETOP+INDEX == TXTPTR), use OLDTXT as temporary storage clc lda INDEX+0 @@ -304,7 +304,7 @@ varstr_garbage_collect_unused: // Decrease TXTPTR by unused string length-1 - tax + txa jsr varstr_TXTPTR_down_A // Next iteration From db1c658a13a1b118a02cda4b0334cae930eb3319 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 17 Jul 2020 23:34:20 +0200 Subject: [PATCH 048/130] garbage collector seems to work now --- src/basic/engine/varstr_garbage_collect.s | 43 ++++++++++++++++------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index a089c081..45b6a093 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -39,24 +39,24 @@ varstr_garbage_collect: varstr_garbage_collect_loop: - // Check if this was the last (lowest) string (if FRETOP+INDEX == TXTPTR), use OLDTXT as temporary storage + // Check if this was the last (lowest) string (if FRETOP == TXTPTR) + + lda FRETOP+1 + cmp TXTPTR+1 + bne varstr_garbage_collect_check_bptr + lda FRETOP+0 + cmp TXTPTR+0 + bne varstr_garbage_collect_check_bptr + + // End of strings - adapt FRETOP clc lda INDEX+0 adc FRETOP+0 - sta OLDTXT+0 + sta FRETOP+0 lda INDEX+1 adc FRETOP+1 - sta OLDTXT+1 - - lda TXTPTR+0 - cmp OLDTXT+0 - bne varstr_garbage_collect_check_bptr - lda TXTPTR+1 - cmp OLDTXT+1 - bne varstr_garbage_collect_check_bptr - - // End of strings - nothing more to do + sta FRETOP+1 // FALLTROUGH @@ -114,7 +114,7 @@ varstr_garbage_collect_check_bptr: #endif ora OLDTXT+0 - beq varstr_garbage_collect_unused + beq_16 varstr_garbage_collect_unused // The back-pointer is not NULL - string is used @@ -275,6 +275,23 @@ varstr_garbage_collect_check_bptr: jsr varstr_TXTPTR_down_A + // Check if variable descriptor in __FAC1 matches the previously moved string; + // if so - adapt it too + + lda __FAC1+2 + cmp TXTPTR+1 + bne !+ + lda __FAC1+1 + cmp TXTPTR+0 + bne !+ + + clc + adc INDEX+0 + sta __FAC1+1 + lda __FAC1+2 + adc INDEX+1 + sta __FAC1+2 +!: // Next iteration jmp varstr_garbage_collect_loop From 704bdfccbf2ca46bb704c1328934a3b632e45bb4 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 10:56:43 +0200 Subject: [PATCH 049/130] improved MEM command --- doc/Extended-BASIC.md | 10 ++-- src/basic/basic_commands_CC/cmd_mem.s | 68 +++++++++++++++++++++++---- src/basic/board_m65/mega65_imports.s | 1 + src/basic/board_m65/mega65_proxies.s | 5 ++ tools/generate_strings.cc | 13 +++-- 5 files changed, 79 insertions(+), 18 deletions(-) diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 68f8c135..0e0e09cf 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -78,11 +78,11 @@ Tries to restore program destroyed by the `NEW` command or a reset. ### `MEM` Displays BASIC memory usage information: -* `TXT` - size of BASIC program text, always at least 2 bytes are used -* `VAR` - bytes occupied by float and integer variables, string variable descriptors, and function descriptors -* `ARR` - bytes occupied by arrays (note: for string arrays only descriptors are stored here) -* `STR` - bytes occupied by strings, also the ones belonging to arrays -* `SPC` - unused space +* `TEXT` - size of BASIC program text, always at least 2 bytes are used +* `VARS` - bytes occupied by float and integer variables, string variable descriptors, and function descriptors +* `ARRS` - bytes occupied by arrays (note: for string arrays only descriptors are stored here) +* `STRS` - bytes occupied by strings, also the ones belonging to arrays +* `FREE` - unused space ### `CLEAR` diff --git a/src/basic/basic_commands_CC/cmd_mem.s b/src/basic/basic_commands_CC/cmd_mem.s index 1a1fe5be..ee15221c 100644 --- a/src/basic/basic_commands_CC/cmd_mem.s +++ b/src/basic/basic_commands_CC/cmd_mem.s @@ -29,16 +29,60 @@ cmd_mem_cont: #endif + // Print header + + lda #$12 + jsr JCHROUT + ldx #IDX__STR_MEM_HDR + jsr print_packed_misc_str + // Print all the information, in a loop, in reverse order ldy #$04 -!: + + // FALLTROUGH + +cmd_mem_loop: + // First print the information string ldx helper_mem_tab_str, y phy_trash_a jsr print_packed_misc_str + // Print start address + + ldx #IDX__STR_MEM_1 + jsr print_packed_misc_str + +#if HAS_OPCODES_65C02 + ply + phy +#else + pla + pha + tay +#endif + ldx helper_mem_tab_y, y + lda $01, x + jsr print_hex_byte + +#if HAS_OPCODES_65C02 + ply + phy +#else + pla + pha + tay +#endif + ldx helper_mem_tab_y, y + lda $00, x + jsr print_hex_byte + + + ldx #IDX__STR_MEM_2 + jsr print_packed_misc_str + // Fetch addresses of zeropage variables #if HAS_OPCODES_65C02 @@ -76,23 +120,31 @@ cmd_mem_cont: // Before printing, make sure the result is not negative - bcc cmd_mem_error + bcs !+ + lda #$3F + jsr JCHROUT +#if HAS_OPCODES_65C02 + bra cmd_mem_next +#else + jmp cmd_mem_next +#endif + +!: jsr print_integer + // FALLTROUGH + +cmd_mem_next: + // Check if more iterations needed ply_trash_a dey - bpl !- + bpl cmd_mem_loop // Finish jmp print_return -cmd_mem_error: - - jsr print_return - jmp do_MEMORY_CORRUPT_error - #endif // ROM layout diff --git a/src/basic/board_m65/mega65_imports.s b/src/basic/board_m65/mega65_imports.s index 9536789f..c7aa9c34 100644 --- a/src/basic/board_m65/mega65_imports.s +++ b/src/basic/board_m65/mega65_imports.s @@ -26,6 +26,7 @@ .label plot_set = KERNAL_0.plot_set .label init_oldtxt = BASIC_0.init_oldtxt .label rom_revision_basic_string = BASIC_0.rom_revision_basic_string +.label print_hex_byte = BASIC_0.proxy_B1_print_hex_byte .label print_integer = BASIC_0.proxy_B1_print_integer .label print_return = BASIC_0.proxy_B1_print_return .label print_space = BASIC_0.proxy_B1_print_space diff --git a/src/basic/board_m65/mega65_proxies.s b/src/basic/board_m65/mega65_proxies.s index 63c91283..2891b466 100644 --- a/src/basic/board_m65/mega65_proxies.s +++ b/src/basic/board_m65/mega65_proxies.s @@ -59,6 +59,11 @@ proxy_B1_JCHROUT: jsr JCHROUT jmp map_BASIC_1 +proxy_B1_print_hex_byte: + + jsr map_NORMAL + jsr print_hex_byte + jmp map_BASIC_1 proxy_B1_print_integer: diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index c7b83226..1c6da077 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -319,11 +319,14 @@ const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", { true, true, true, true, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm // STD M65 U64 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, - { true, true, true, true, "STR_MEM_TEXT", "\rTXT: " }, - { true, true, true, true, "STR_MEM_VARS", "\rVAR: " }, - { true, true, true, true, "STR_MEM_ARRS", "\rARR: " }, - { true, true, true, true, "STR_MEM_STRS", "\rSTR: " }, - { true, true, true, true, "STR_MEM_FREE", "\r\rSPC: " }, + { true, true, true, true, "STR_MEM_HDR", "\r\x12 AREA START SIZE \r" }, + { true, true, true, true, "STR_MEM_1", " $" }, + { true, true, true, true, "STR_MEM_2", " " }, + { true, true, true, true, "STR_MEM_TEXT", "\r TEXT" }, + { true, true, true, true, "STR_MEM_VARS", "\r VARS" }, + { true, true, true, true, "STR_MEM_ARRS", "\r ARRS" }, + { true, true, true, true, "STR_MEM_STRS", "\r STRS" }, + { true, true, true, true, "STR_MEM_FREE", "\r\r FREE" }, // Note: depending on configuration, additional strings will be added here } }; From e8d251eee2e53d896a44f1f300dba0e02dd59d36 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 11:26:48 +0200 Subject: [PATCH 050/130] small code cleanup --- src/basic/engine/varstr_free.s | 2 -- ..._cmp_fretop.s => varstr_free_cmp_fretop.s} | 0 src/basic/engine/varstr_free_fretop.s | 1 - src/basic/engine/varstr_garbage_collect.s | 36 ------------------- src/basic/engine/varstr_garbage_index_up_a.s | 21 +++++++++++ .../engine/varstr_garbage_txtptr_down_s.s | 21 +++++++++++ 6 files changed, 42 insertions(+), 39 deletions(-) rename src/basic/engine/{varstr_cmp_fretop.s => varstr_free_cmp_fretop.s} (100%) create mode 100644 src/basic/engine/varstr_garbage_index_up_a.s create mode 100644 src/basic/engine/varstr_garbage_txtptr_down_s.s diff --git a/src/basic/engine/varstr_free.s b/src/basic/engine/varstr_free.s index c86cf3f7..96878cc2 100644 --- a/src/basic/engine/varstr_free.s +++ b/src/basic/engine/varstr_free.s @@ -10,8 +10,6 @@ // - DSCPNT+1, DSCPNT+2 - pointer to string // -// XXX test this routine - varstr_free: diff --git a/src/basic/engine/varstr_cmp_fretop.s b/src/basic/engine/varstr_free_cmp_fretop.s similarity index 100% rename from src/basic/engine/varstr_cmp_fretop.s rename to src/basic/engine/varstr_free_cmp_fretop.s diff --git a/src/basic/engine/varstr_free_fretop.s b/src/basic/engine/varstr_free_fretop.s index f1abde57..7cf7d941 100644 --- a/src/basic/engine/varstr_free_fretop.s +++ b/src/basic/engine/varstr_free_fretop.s @@ -6,7 +6,6 @@ // Helper routines for 'varstr_free' // -// XXX change DSCPNT to use standard descriptor format varstr_FRETOP_up: // DSCPNT+0 - bytes to increment FRETO diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 45b6a093..35a739b0 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -2,8 +2,6 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE -// XXX test this routine - varstr_garbage_collect: @@ -327,37 +325,3 @@ varstr_garbage_collect_unused: // Next iteration jmp varstr_garbage_collect_loop - - - - - - - // XXX move these routines to separate files - -varstr_TXTPTR_down_A: // .A - bytes to decrease TXTPTR, uses DSCPNT+0 - - sta DSCPNT+0 - - sec - lda TXTPTR+0 - sbc DSCPNT+0 - sta TXTPTR+0 - bcs !+ - dec TXTPTR+1 -!: - rts - - -varstr_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+0 - - sta DSCPNT+0 - - clc - lda INDEX+0 - adc DSCPNT+0 - sta INDEX+0 - bcc !+ - dec INDEX+1 -!: - rts diff --git a/src/basic/engine/varstr_garbage_index_up_a.s b/src/basic/engine/varstr_garbage_index_up_a.s new file mode 100644 index 00000000..84dfed13 --- /dev/null +++ b/src/basic/engine/varstr_garbage_index_up_a.s @@ -0,0 +1,21 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine, used by garbage collector +// + + +varstr_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+0 + + sta DSCPNT+0 + + clc + lda INDEX+0 + adc DSCPNT+0 + sta INDEX+0 + bcc !+ + dec INDEX+1 +!: + rts diff --git a/src/basic/engine/varstr_garbage_txtptr_down_s.s b/src/basic/engine/varstr_garbage_txtptr_down_s.s new file mode 100644 index 00000000..c9bfefa5 --- /dev/null +++ b/src/basic/engine/varstr_garbage_txtptr_down_s.s @@ -0,0 +1,21 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine, used by garbage collector +// + + +varstr_TXTPTR_down_A: // .A - bytes to decrease TXTPTR, uses DSCPNT+0 + + sta DSCPNT+0 + + sec + lda TXTPTR+0 + sbc DSCPNT+0 + sta TXTPTR+0 + bcs !+ + dec TXTPTR+1 +!: + rts From d50b30113e1e2e2b35cfec047f68253674736220 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 11:46:19 +0200 Subject: [PATCH 051/130] fixed variable fetch bug for memory model 60K --- src/basic/engine/fetch_variable.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index 995aaff2..7c90b2fa 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -86,7 +86,7 @@ fetch_variable_type_string: lda VARNAM+1 ora #$80 sta VARNAM+1 - + // FALLTROUGH fetch_variable_find_addr: @@ -252,7 +252,7 @@ fetch_variable_alocate_space_OK: #if CONFIG_MEMORY_MODEL_60K - ldx # Date: Sat, 18 Jul 2020 13:26:03 +0200 Subject: [PATCH 052/130] another garbage collector bugfix --- src/basic/engine/varstr_garbage_collect.s | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 35a739b0..5d7ec535 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -307,7 +307,16 @@ varstr_garbage_collect_unused: #endif ldy #$00 - lda (TXTPTR), y + +#if CONFIG_MEMORY_MODEL_60K + ldx # Date: Sat, 18 Jul 2020 13:55:19 +0200 Subject: [PATCH 053/130] string assignment can sometimes reuse old string alocated memory --- src/basic/basic_commands/cmd_let.s | 86 ++++++------------- .../helper_let_strdesccpy_38K.s | 32 +++++++ .../helper_let_strdesccpy_60K.s | 37 ++++++++ src/basic/engine/varstr_free.s | 1 + 4 files changed, 97 insertions(+), 59 deletions(-) create mode 100644 src/basic/basic_commands/helper_let_strdesccpy_38K.s create mode 100644 src/basic/basic_commands/helper_let_strdesccpy_60K.s diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 02c811ae..d395e4ed 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -259,24 +259,41 @@ cmd_let_assign_string_not_same: cmd_let_assign_string_not_text_area: - // Check if size of both strings equals and the old on is above FRETOP + // Check if the new string is a temporary one - if so, reuse alocation // XXX - // Check if new one is at least 3 bytes shorter and the old one is above FRETOP + // Check if the old string belongs to the string area (is above FRETOP) - // XXX + jsr varstr_cmp_fretop + bcc cmd_let_assign_string_no_optimizations - // Check if the new string is a temporary one - if so, reuse already done alocation + // FALLTROUGH - // XXX +cmd_let_assign_string_try_reuse: - // No special case optimization is possible - // Free the memory belonging to the old string + // Check if size of both strings equals + + lda DSCPNT+0 + cmp __FAC1 + bne cmd_let_assign_string_try_reuse_unsuccesful + + // Size of both string equals, the old one belongs to the string area - simply reuse it + + jmp helper_let_strvarcpy + +cmd_let_assign_string_try_reuse_unsuccesful: + // XXX consider another optimization first: parial memory reuse + + // No special case optimization is possible - but first get rid of the old string jsr varstr_free - // And allocate memory for the new string + // FALLTROUGH + +cmd_let_assign_string_no_optimizations: + + // Allocate memory for the new string lda __FAC1+0 ldy #$00 @@ -294,55 +311,6 @@ cmd_let_assign_string_not_text_area: jsr varstr_alloc - // Copy the string + // Copy the string and quit -#if CONFIG_MEMORY_MODEL_60K - - ldx # Date: Sat, 18 Jul 2020 14:29:30 +0200 Subject: [PATCH 054/130] another string assignment bugfix --- src/basic/basic_commands/cmd_let.s | 29 +++++++++++++++---- ...sccpy_38K.s => helper_let_strvarcpy_38K.s} | 5 +++- .../helper_let_strvarcpy_46K_50K.s | 1 + ...sccpy_60K.s => helper_let_strvarcpy_60K.s} | 5 +++- 4 files changed, 32 insertions(+), 8 deletions(-) rename src/basic/basic_commands/{helper_let_strdesccpy_38K.s => helper_let_strvarcpy_38K.s} (79%) rename src/basic/basic_commands/{helper_let_strdesccpy_60K.s => helper_let_strvarcpy_60K.s} (81%) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index d395e4ed..d772c378 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -272,18 +272,35 @@ cmd_let_assign_string_not_text_area: cmd_let_assign_string_try_reuse: - // Check if size of both strings equals + // Check if we can reuse old string memory + sec lda DSCPNT+0 - cmp __FAC1 - bne cmd_let_assign_string_try_reuse_unsuccesful + sbc __FAC1+0 + bcc cmd_let_assign_string_try_reuse_unsuccesful + + // If size of both string equals - simply reuse it - // Size of both string equals, the old one belongs to the string area - simply reuse it + beq_16 helper_let_strvarcpy - jmp helper_let_strvarcpy + // Old string is longer - if difference is at least 3 bytes, we can still reuse it + + sbc #$03 + bcc cmd_let_assign_string_try_reuse_unsuccesful + + // New string is shorter - enought that we can still reuse the old one with a small trick +/* + clc + adc DSCPNT+1 + sta DSCPNT+1 + bcs !+ + inc DSCPNT+2 +*/ + // XXX + // XXX implement this part + // XXX cmd_let_assign_string_try_reuse_unsuccesful: - // XXX consider another optimization first: parial memory reuse // No special case optimization is possible - but first get rid of the old string diff --git a/src/basic/basic_commands/helper_let_strdesccpy_38K.s b/src/basic/basic_commands/helper_let_strvarcpy_38K.s similarity index 79% rename from src/basic/basic_commands/helper_let_strdesccpy_38K.s rename to src/basic/basic_commands/helper_let_strvarcpy_38K.s index 44b93ef8..99efa312 100644 --- a/src/basic/basic_commands/helper_let_strdesccpy_38K.s +++ b/src/basic/basic_commands/helper_let_strvarcpy_38K.s @@ -9,7 +9,10 @@ #if CONFIG_MEMORY_MODEL_38K -helper_let_strdesccpy: +helper_let_strvarcpy: + + // Retrieve pointer to destination + // XXX this part is probably not needed ldy #$02 lda (VARPNT), y diff --git a/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s b/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s index 538db97b..4961a806 100644 --- a/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s +++ b/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s @@ -19,6 +19,7 @@ helper_let_strvarcpy: sta CPU_R6510 // Retrieve pointer to destination + // XXX this part is probably not needed ldy #$02 lda (VARPNT), y diff --git a/src/basic/basic_commands/helper_let_strdesccpy_60K.s b/src/basic/basic_commands/helper_let_strvarcpy_60K.s similarity index 81% rename from src/basic/basic_commands/helper_let_strdesccpy_60K.s rename to src/basic/basic_commands/helper_let_strvarcpy_60K.s index 19a96e55..7a19130d 100644 --- a/src/basic/basic_commands/helper_let_strdesccpy_60K.s +++ b/src/basic/basic_commands/helper_let_strvarcpy_60K.s @@ -9,10 +9,13 @@ #if CONFIG_MEMORY_MODEL_60K -helper_let_strdesccpy: +helper_let_strvarcpy: ldx # Date: Sat, 18 Jul 2020 14:52:02 +0200 Subject: [PATCH 055/130] code cleanup --- src/basic/basic_commands/cmd_let.s | 22 ++----------------- .../basic_commands/helper_let_strvarcpy_38K.s | 1 - .../helper_let_strvarcpy_46K_50K.s | 3 +-- .../basic_commands/helper_let_strvarcpy_60K.s | 1 - 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index d772c378..10311df9 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -276,30 +276,12 @@ cmd_let_assign_string_try_reuse: sec lda DSCPNT+0 - sbc __FAC1+0 - bcc cmd_let_assign_string_try_reuse_unsuccesful - + cmp __FAC1+0 + // If size of both string equals - simply reuse it beq_16 helper_let_strvarcpy - // Old string is longer - if difference is at least 3 bytes, we can still reuse it - - sbc #$03 - bcc cmd_let_assign_string_try_reuse_unsuccesful - - // New string is shorter - enought that we can still reuse the old one with a small trick -/* - clc - adc DSCPNT+1 - sta DSCPNT+1 - bcs !+ - inc DSCPNT+2 -*/ - // XXX - // XXX implement this part - // XXX - cmd_let_assign_string_try_reuse_unsuccesful: // No special case optimization is possible - but first get rid of the old string diff --git a/src/basic/basic_commands/helper_let_strvarcpy_38K.s b/src/basic/basic_commands/helper_let_strvarcpy_38K.s index 99efa312..65854927 100644 --- a/src/basic/basic_commands/helper_let_strvarcpy_38K.s +++ b/src/basic/basic_commands/helper_let_strvarcpy_38K.s @@ -12,7 +12,6 @@ helper_let_strvarcpy: // Retrieve pointer to destination - // XXX this part is probably not needed ldy #$02 lda (VARPNT), y diff --git a/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s b/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s index 4961a806..f8c79176 100644 --- a/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s +++ b/src/basic/basic_commands/helper_let_strvarcpy_46K_50K.s @@ -19,7 +19,6 @@ helper_let_strvarcpy: sta CPU_R6510 // Retrieve pointer to destination - // XXX this part is probably not needed ldy #$02 lda (VARPNT), y @@ -29,7 +28,7 @@ helper_let_strvarcpy: sta DSCPNT+1 dey - // .Y is now 0 - copy the content + // Copy the string content !: lda (__FAC1+1),y sta (DSCPNT+1),y diff --git a/src/basic/basic_commands/helper_let_strvarcpy_60K.s b/src/basic/basic_commands/helper_let_strvarcpy_60K.s index 7a19130d..d8e6c281 100644 --- a/src/basic/basic_commands/helper_let_strvarcpy_60K.s +++ b/src/basic/basic_commands/helper_let_strvarcpy_60K.s @@ -14,7 +14,6 @@ helper_let_strvarcpy: ldx # Date: Sat, 18 Jul 2020 15:00:19 +0200 Subject: [PATCH 056/130] removed unneeded instruction --- src/basic/basic_commands/cmd_let.s | 1 - 1 file changed, 1 deletion(-) diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 10311df9..67918eb6 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -274,7 +274,6 @@ cmd_let_assign_string_try_reuse: // Check if we can reuse old string memory - sec lda DSCPNT+0 cmp __FAC1+0 From 778057e9f2373e89af3d9e75fc034ed271cde880 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 17:28:56 +0200 Subject: [PATCH 057/130] preparation towardfs string concatenation --- src/basic/basic_operators/oper_add.s | 5 +++-- src/basic/engine/do_new_clr_restore.s | 9 ++++++++- src/basic/engine/end_of_statement.s | 1 + src/basic/engine/execute_line_statements.s | 9 --------- src/basic/engine/tmpstr_alloc.s | 21 +++++++++++++++++++++ src/basic/engine/tmpstr_free_all.s | 10 ++++++++++ src/basic/engine/varstr_garbage_collect.s | 16 ++++++++++++++++ 7 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 src/basic/engine/tmpstr_alloc.s create mode 100644 src/basic/engine/tmpstr_free_all.s diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index 2b3a0632..d1f6401b 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -58,10 +58,11 @@ oper_add_strings: adc __FAC2+0 bcs_16 do_STRING_TOO_LONG_error - // jsr alloc_temp_string - .break + jsr tmpstr_alloc + + // XXX finish the implementation diff --git a/src/basic/engine/do_new_clr_restore.s b/src/basic/engine/do_new_clr_restore.s index 3a249d2a..0323e5ad 100644 --- a/src/basic/engine/do_new_clr_restore.s +++ b/src/basic/engine/do_new_clr_restore.s @@ -51,7 +51,7 @@ do_clr: // See Computes Mapping the Commodore 64 - page 96 - // XXX check on real ROMs that it is being done too when entering new line + // XXX check if original ROM does this too jsr JCLALL lda MEMSIZ+0 @@ -69,6 +69,13 @@ do_clr: sta ARYTAB+1 sta STREND+1 + // This is a good place to reset the temporary string stack + + lda #$19 + sta TEMPPT + lda #$16 + sta LASTPT + // FALLTROUGH (confirmed on real C64 that CLR indeed resets DATPTR) do_restore: diff --git a/src/basic/engine/end_of_statement.s b/src/basic/engine/end_of_statement.s index 3e3ca00d..8216d144 100644 --- a/src/basic/engine/end_of_statement.s +++ b/src/basic/engine/end_of_statement.s @@ -9,6 +9,7 @@ end_of_statement: + jsr tmpstr_free_all jsr fetch_character_skip_spaces cmp #$3A // check for colon diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine/execute_line_statements.s index 1e37e135..eb1cf0ad 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine/execute_line_statements.s @@ -27,16 +27,7 @@ execute_statements: // Not end of the line - it seems we actually have something to execute - // Initialize temporary string stack - just about any statement might need it - // XXX original C64 ROM initializes this during the startup too - not sure where to put this - - ldx #$16 - stx LASTPT - ldx #$19 - stx TEMPPT - // Move token code to .X - tax // Push the 'end_of_statement' address for RTS diff --git a/src/basic/engine/tmpstr_alloc.s b/src/basic/engine/tmpstr_alloc.s new file mode 100644 index 00000000..b5b3698e --- /dev/null +++ b/src/basic/engine/tmpstr_alloc.s @@ -0,0 +1,21 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Allocates memory for a temporary string +// +// Input: +// -.A desired string length, has to be > 0 +// +// + +tmpstr_alloc: + + // First we need to find a free temporary string descriptor + + // XXX TEMPPT-> LASTPT + + // XXX implement this + + rts diff --git a/src/basic/engine/tmpstr_free_all.s b/src/basic/engine/tmpstr_free_all.s new file mode 100644 index 00000000..5746080b --- /dev/null +++ b/src/basic/engine/tmpstr_free_all.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +tmpstr_free_all: + + // XXX implement this + + rts diff --git a/src/basic/engine/varstr_garbage_collect.s b/src/basic/engine/varstr_garbage_collect.s index 5d7ec535..ef6975c4 100644 --- a/src/basic/engine/varstr_garbage_collect.s +++ b/src/basic/engine/varstr_garbage_collect.s @@ -289,6 +289,22 @@ varstr_garbage_collect_check_bptr: lda __FAC1+2 adc INDEX+1 sta __FAC1+2 +!: + // Same for __FAC2 + + lda __FAC2+2 + cmp TXTPTR+1 + bne !+ + lda __FAC2+1 + cmp TXTPTR+0 + bne !+ + + clc + adc INDEX+0 + sta __FAC2+1 + lda __FAC2+2 + adc INDEX+1 + sta __FAC2+2 !: // Next iteration From 59af3b7e5771a5f9934d2eebd40439446c9b3c02 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 20:04:36 +0200 Subject: [PATCH 058/130] more work towards string concatenation, updated binaries and documentation --- README.md | 4 +- STATUS.md | 14 +++--- bin/basic_generic.rom | Bin 8192 -> 8192 bytes bin/basic_ultimate64.rom | Bin 8192 -> 8192 bytes bin/kernal_generic.rom | Bin 8192 -> 8192 bytes bin/kernal_ultimate64.rom | Bin 8192 -> 8192 bytes bin/mega65.rom | Bin 131072 -> 131072 bytes bin/mega65_pxlfont.rom | Bin 131072 -> 131072 bytes src/,,config_custom.s | 4 +- src/basic/basic_operators/oper_add.s | 68 +++++++++++++++++++++++++-- src/basic/engine/tmpstr_alloc.s | 30 ++++++++++-- src/basic/engine/varstr_alloc.s | 1 - 12 files changed, 103 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index ed96c5b8..2472cd42 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,13 @@ A project to create unencumbered open-source ROMs for use on selected retro comp * [implementation status](./STATUS.md) of various APIs and functionalities * [configuration options](./CONFIG.md) for those willing to compile their own, customized ROM set -* [BASIC extensions](doc/Extended-BASIC.md) +* [BASIC extensions](./doc/Extended-BASIC.md) * [development guide](./doc/Development.md) for those interested in technical aspects * [license](./LICENSE) information and list of major contributors * [credits](./CREDITS.md) to people whose work was of great help to us +To download pre-built ROM images, go [here](./bin). + # Problem Statement and Motivation The copyrights of various old computer system ROMs are still alive, and together with trademarks, can present significant diff --git a/STATUS.md b/STATUS.md index 276414db..66547f2a 100644 --- a/STATUS.md +++ b/STATUS.md @@ -11,6 +11,12 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8 * JiffyDOS and DolphinDOS protocols support * DOS wedge (direct mode only) - `@`, `@`, `@$`, `@$`, `@` * BASIC extensions, see the [documentation](doc/Extended-BASIC.md) +* extended / tweaked `LOAD` / `VERIFY` commands + * start/end addresses are displayed, in the Final cartridge style + * command with just the file name tries to use the last device if it's number seems sane; otherwise uses 8 + * command without parameters tries to load first file from drive chosen as above +* `LIST` command should never damage the screen if trying to list memory content which is not a BASIC program +* high performance garbage collector * turbo tape load support (as device 7, or using `←L` / `←M`, optionally with a file name), quite sophisticated: up to 250 blocks (can store bytes under I/O), automatically adjusts for tape speed differences * normal tape load error log is limited by free stack space only (no artificial limitation like in original ROMs) @@ -18,12 +24,6 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8 * improved support for tape adapters (for using regular casette players and other audio devices instead of Datasette) and emulators * built-in tape head align tool (only feasible to use on machines with extended memory, like Mega65) -* extended / tweaked `LOAD` / `VERIFY` commands - * start/end addresses are displayed, in the Final cartridge style - * command with just the file name tries to use the last device if it's number seems sane; otherwise uses 8 - * command without parameters tries to load first file from drive chosen as above -* `LIST` command should never damage the screen if trying to list memory content which is not a BASIC program - * uses RAM under ROM and I/O: 51199 bytes free (up to `$CFFF`) by default, but 61438 is also possible * cold/warm start silences multiple SID chips * warm start due to BRK prints out the instruction address @@ -42,7 +42,7 @@ The following ROM features are currently missing and are not planned due to spac The following ROM features are currently missing: * most BASIC commands -* BASIC variables +* BASIC variables (work in progress, strings partially work now) * BASIC expression handling * most floating point routines * RS-232 support diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 8e9caf1c002eca45c671f4250b3621c8ff6c618b..62954140c1caa0b0ab1282840747865c29cb6041 100644 GIT binary patch delta 4964 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 diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 57116e02d872973f9151e1cbd0091ae1bd0b48f7..90ede62cf09df395d9037ef1e65cf57906325ee0 100644 GIT binary patch delta 3964 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 delta 4027 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 diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index 80a270c84a6425b2bfa12308d6a876d26acaa09a..74418042803fa147ddc8095d023269e1a40a99e4 100644 GIT binary patch delta 3836 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 delta 3889 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 Sz~1X%g!ks>`)=G%QT`1z$t@HB diff --git a/bin/mega65.rom b/bin/mega65.rom index 563284aa00fde16aadc8f3ae976b1336fdb7083f..aa8a0643cf4e4250647fcdbd33f852d2432dc46c 100644 GIT binary patch delta 7630 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 T#-1vfYk8GY{Lg=ha>4%ttwJfG diff --git a/bin/mega65_pxlfont.rom b/bin/mega65_pxlfont.rom index 896f68ff2ce37989bbc64da64944d15a2685174a..cabc4485c688d7a73fad4ac75151e5a9b04fe26e 100644 GIT binary patch delta 7630 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 T#-1vfYk8GY{Lg=ha>4%ttwJfG diff --git a/src/,,config_custom.s b/src/,,config_custom.s index ad83a50a..da689381 100644 --- a/src/,,config_custom.s +++ b/src/,,config_custom.s @@ -39,9 +39,9 @@ // Memory model -// #define CONFIG_MEMORY_MODEL_38K +#define CONFIG_MEMORY_MODEL_38K // #define CONFIG_MEMORY_MODEL_46K -#define CONFIG_MEMORY_MODEL_50K +// #define CONFIG_MEMORY_MODEL_50K // #define CONFIG_MEMORY_MODEL_60K diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index d1f6401b..46d124c7 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -52,21 +52,81 @@ oper_add_strings: jmp FRMEVL_continue !: - // Allocate memory for concatenated string + // Allocate memory for the concatenated string clc adc __FAC2+0 bcs_16 do_STRING_TOO_LONG_error -.break - jsr tmpstr_alloc + // Copy the temporary string pointer to INDEX + ldy #$01 + lda (VARPNT), y + sta INDEX+0 + iny + lda (VARPNT), y + sta INDEX+1 + // Perform the concatenation - // XXX finish the implementation +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX + // XXX +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // Copy data from the first string + + ldy #$00 +!: + lda (__FAC2+1),y + sta (INDEX),y + iny + cpy __FAC2+0 + bne !- + + // Increase INDEX pointer by the size of the 1st string + + tya + jsr varstr_INDEX_up_A + + // Copy data from the second string + + ldy #$00 +!: + lda (__FAC1+1),y + sta (INDEX),y + iny + cpy __FAC1+0 + bne !- + +#endif + + // Free old strings - if they are temporary + + // XXX + // XXX + // XXX + + // Copy the descriptor to __FAC1 + + ldy #$02 +!: + lda (VARPNT), y + sta __FAC1, y + dey + bpl !- oper_add_strings_end: diff --git a/src/basic/engine/tmpstr_alloc.s b/src/basic/engine/tmpstr_alloc.s index b5b3698e..8d94899f 100644 --- a/src/basic/engine/tmpstr_alloc.s +++ b/src/basic/engine/tmpstr_alloc.s @@ -8,14 +8,38 @@ // Input: // -.A desired string length, has to be > 0 // +// Output: +// - VARPNT points to the newly alocated descriptor // tmpstr_alloc: + tax + // First we need to find a free temporary string descriptor - // XXX TEMPPT-> LASTPT + lda TEMPPT + cmp #$22 + bcs_16 do_FORMULA_TOO_COMPLEX_error - // XXX implement this + tay + sta LASTPT + clc + adc #$03 + sta TEMPPT - rts + // Store desired string length + + stx $00, y + + // Store descriptor address + + lda LASTPT + sta VARPNT+0 + lda #$00 + sta VARPNT+1 + + // Jump to alocation routine + // XXX consider falltrough + + jmp varstr_alloc diff --git a/src/basic/engine/varstr_alloc.s b/src/basic/engine/varstr_alloc.s index d5bc5e04..ee06e329 100644 --- a/src/basic/engine/varstr_alloc.s +++ b/src/basic/engine/varstr_alloc.s @@ -20,7 +20,6 @@ // - fills-in pointer in the string descriptor // -// XXX test this routine varstr_alloc: From e99bb9356a431fb4a7d3b87928bf7343d78db300 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 20:53:52 +0200 Subject: [PATCH 059/130] added hooks for ST, TI and TI$ variables --- src/basic/engine/fetch_variable.s | 30 +++++++++++++++++++-- src/basic/engine/fetch_variable_ST.s | 10 +++++++ src/basic/engine/fetch_variable_TI.s | 10 +++++++ src/basic/engine/fetch_variable_TI_string.s | 10 +++++++ src/basic/engine/varstr_alloc.s | 3 +++ 5 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/basic/engine/fetch_variable_ST.s create mode 100644 src/basic/engine/fetch_variable_TI.s create mode 100644 src/basic/engine/fetch_variable_TI_string.s diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine/fetch_variable.s index 7c90b2fa..d0f50689 100644 --- a/src/basic/engine/fetch_variable.s +++ b/src/basic/engine/fetch_variable.s @@ -68,9 +68,9 @@ fetch_variable_type_float: #endif #if HAS_OPCODES_65C02 - bra fetch_variable_find_addr + bra fetch_variable_special #else - jmp fetch_variable_find_addr + jmp fetch_variable_special #endif fetch_variable_type_integer: @@ -89,6 +89,32 @@ fetch_variable_type_string: // FALLTROUGH +fetch_variable_special: + + lda VARNAM+0 + cmp #$54 // 'T' + beq !+ + cmp #$53 // 'S' + bne fetch_variable_find_addr + + // First character is 'S', check the second one + + lda VARNAM+1 + cmp #$54 // 'T' + bne fetch_variable_find_addr + + jmp fetch_variable_ST +!: + // First character is 'T', check the second one + + lda VARNAM+1 + cmp #$49 + beq_16 fetch_variable_TI + cmp #$C9 + beq_16 fetch_variable_TI_string + + // FALLTROUGH + fetch_variable_find_addr: // Now try to find variable address between VARTAB and ARYTAB, see diff --git a/src/basic/engine/fetch_variable_ST.s b/src/basic/engine/fetch_variable_ST.s new file mode 100644 index 00000000..15f46d76 --- /dev/null +++ b/src/basic/engine/fetch_variable_ST.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +fetch_variable_ST: + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/fetch_variable_TI.s b/src/basic/engine/fetch_variable_TI.s new file mode 100644 index 00000000..c00e9012 --- /dev/null +++ b/src/basic/engine/fetch_variable_TI.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +fetch_variable_TI: + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/fetch_variable_TI_string.s b/src/basic/engine/fetch_variable_TI_string.s new file mode 100644 index 00000000..e0220720 --- /dev/null +++ b/src/basic/engine/fetch_variable_TI_string.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +fetch_variable_TI_string: + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine/varstr_alloc.s b/src/basic/engine/varstr_alloc.s index ee06e329..f429e601 100644 --- a/src/basic/engine/varstr_alloc.s +++ b/src/basic/engine/varstr_alloc.s @@ -20,6 +20,9 @@ // - fills-in pointer in the string descriptor // +// NOTE: if FAC1 or FAC2 contains a value (not a string descriptor - these are going to be updated +// if garbage collector starts), then preserve __FAC1+1/+2 and __FAC2+1/+2 somewhere, as there +// is a small chance they'll get damaged! varstr_alloc: From 080ea5dab575bf8d636b97d33b1c4fd37f3e4ad7 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 18 Jul 2020 21:20:55 +0200 Subject: [PATCH 060/130] added missing code for some meory models --- src/,,config_custom.s | 4 +- .../helper_add_concat_46K_50K.s | 53 +++++++++++++++++++ src/basic/basic_operators/oper_add.s | 36 ++++++++++--- src/basic/engine/varstr_garbage_index_up_a.s | 8 +-- 4 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 src/basic/basic_operators/helper_add_concat_46K_50K.s diff --git a/src/,,config_custom.s b/src/,,config_custom.s index da689381..ad83a50a 100644 --- a/src/,,config_custom.s +++ b/src/,,config_custom.s @@ -39,9 +39,9 @@ // Memory model -#define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_38K // #define CONFIG_MEMORY_MODEL_46K -// #define CONFIG_MEMORY_MODEL_50K +#define CONFIG_MEMORY_MODEL_50K // #define CONFIG_MEMORY_MODEL_60K diff --git a/src/basic/basic_operators/helper_add_concat_46K_50K.s b/src/basic/basic_operators/helper_add_concat_46K_50K.s new file mode 100644 index 00000000..f777a3e3 --- /dev/null +++ b/src/basic/basic_operators/helper_add_concat_46K_50K.s @@ -0,0 +1,53 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routines below banks out the main BASIC ROM! + +// +// Helper routine for string concatenation +// + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_add_concat: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Copy data from the first string + + ldy #$00 +!: + lda (__FAC2+1),y + sta (INDEX),y + iny + cpy __FAC2+0 + bne !- + + // Increase INDEX pointer by the size of the 1st string + + tya + jsr varstr_INDEX_up_A + + // Copy data from the second string + + ldy #$00 +!: + lda (__FAC1+1),y + sta (INDEX),y + iny + cpy __FAC1+0 + bne !- + + // Restore default memory mapping + + lda #$27 + sta CPU_R6510 + + rts + +#endif diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index 46d124c7..1118acbf 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -73,16 +73,38 @@ oper_add_strings: #if CONFIG_MEMORY_MODEL_60K - // XXX - // XXX - // XXX + // Copy data from the first string + + ldy #$00 +!: + ldx #<(__FAC2+1) + jsr peek_under_roms + ldx # Date: Sat, 18 Jul 2020 23:09:07 +0200 Subject: [PATCH 061/130] added fetching TI$ variable, does not fully work yet --- src/basic/assets/table_ti_hi.s | 16 ++++ src/basic/assets/table_ti_lo.s | 16 ++++ src/basic/assets/table_ti_mid.s | 16 ++++ src/basic/basic_commands/cmd_let.s | 30 ------- .../helper_let_strdesccpy_38K.s | 26 ++++++ .../helper_let_strdesccpy_46K_50K.s | 2 +- .../helper_let_strdesccpy_60K.s | 28 ++++++ src/basic/engine/fetch_variable.s | 12 ++- src/basic/engine/fetch_variable_TI_string.s | 86 ++++++++++++++++++- ...K.s => helper_frmevl_strdesccpy_46K_50K.s} | 0 10 files changed, 196 insertions(+), 36 deletions(-) create mode 100644 src/basic/assets/table_ti_hi.s create mode 100644 src/basic/assets/table_ti_lo.s create mode 100644 src/basic/assets/table_ti_mid.s create mode 100644 src/basic/basic_commands/helper_let_strdesccpy_38K.s create mode 100644 src/basic/basic_commands/helper_let_strdesccpy_60K.s rename src/basic/engine/{helper_frmevl_46K_50K.s => helper_frmevl_strdesccpy_46K_50K.s} (100%) diff --git a/src/basic/assets/table_ti_hi.s b/src/basic/assets/table_ti_hi.s new file mode 100644 index 00000000..44e3b388 --- /dev/null +++ b/src/basic/assets/table_ti_hi.s @@ -0,0 +1,16 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Table to TI$ special variable support +// + +table_TI_hi: + + .byte $36 // 10 hours = 3600000 ticks + .byte $05 // 1 hour = 360000 ticks + .byte $00 // 10 minutes = 30000 ticks + .byte $00 // 1 minute = 3000 ticks + .byte $00 // 10 seconds = 500 ticks + .byte $00 // 1 second = 50 ticks diff --git a/src/basic/assets/table_ti_lo.s b/src/basic/assets/table_ti_lo.s new file mode 100644 index 00000000..5f09b6ac --- /dev/null +++ b/src/basic/assets/table_ti_lo.s @@ -0,0 +1,16 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Table to TI$ special variable support +// + +table_TI_lo: + + .byte $80 // 10 hours = 3600000 ticks + .byte $40 // 1 hour = 360000 ticks + .byte $30 // 10 minutes = 30000 ticks + .byte $B8 // 1 minute = 3000 ticks + .byte $F4 // 10 seconds = 500 ticks + .byte $32 // 1 second = 50 ticks diff --git a/src/basic/assets/table_ti_mid.s b/src/basic/assets/table_ti_mid.s new file mode 100644 index 00000000..ccecd6ff --- /dev/null +++ b/src/basic/assets/table_ti_mid.s @@ -0,0 +1,16 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Table to TI$ special variable support +// + +table_TI_mid: + + .byte $EE // 10 hours = 3600000 ticks + .byte $7E // 1 hour = 360000 ticks + .byte $75 // 10 minutes = 30000 ticks + .byte $0B // 1 minute = 3000 ticks + .byte $01 // 10 seconds = 500 ticks + .byte $00 // 1 second = 50 ticks diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s index 67918eb6..2a03c68a 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/basic_commands/cmd_let.s @@ -134,38 +134,8 @@ cmd_let_assign_string: // Copy the string descriptor to DSCPNT -#if CONFIG_MEMORY_MODEL_60K - - ldx # Date: Sat, 18 Jul 2020 23:23:10 +0200 Subject: [PATCH 062/130] bugfix for TI$ printig --- src/basic/engine/fetch_variable_TI_string.s | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/basic/engine/fetch_variable_TI_string.s b/src/basic/engine/fetch_variable_TI_string.s index 7ff1ad97..12971013 100644 --- a/src/basic/engine/fetch_variable_TI_string.s +++ b/src/basic/engine/fetch_variable_TI_string.s @@ -3,8 +3,7 @@ // #LAYOUT# * * #IGNORE -// XXX test this - +// XXX does not fully work fetch_variable_TI_string: @@ -44,13 +43,17 @@ fetch_variable_TI_string_loop: lda INDEX+2 cmp table_TI_hi, y bcc fetch_variable_TI_string_got_digit + bne fetch_variable_TI_string_inc_digit lda INDEX+1 cmp table_TI_mid, y bcc fetch_variable_TI_string_got_digit + bne fetch_variable_TI_string_inc_digit lda INDEX+0 cmp table_TI_lo, y bcc fetch_variable_TI_string_got_digit +fetch_variable_TI_string_inc_digit: + // Increment digit and subtract the table value from the counter inc INDEX+3 From 09f85cea8ad5dae93ca1be364c791f5a520e0944 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 08:54:53 +0200 Subject: [PATCH 063/130] variable support cleanup --- Makefile | 5 +- src/aliases/,aliases_cpu.s | 14 +++ src/basic/basic_commands/cmd__jumptable.s | 2 +- src/basic/basic_operators/oper_add.s | 22 +++-- src/basic/engine/tmpstr_free_all.s | 10 -- .../{editor => engine_editor}/a533.interop | 0 .../{editor => engine_editor}/a533.linkprg.s | 0 .../{editor => engine_editor}/delete_line.s | 0 .../{editor => engine_editor}/find_line.s | 0 .../{editor => engine_editor}/insert_line.s | 0 src/basic/{editor => engine_editor}/shell.s | 0 .../shift_txt_down.s | 0 .../{editor => engine_editor}/shift_txt_up.s | 0 .../{editor => engine_editor}/tk_cut_away.s | 0 src/basic/{editor => engine_editor}/tk_pack.s | 0 .../{editor => engine_editor}/tk_search.s | 0 .../{editor => engine_editor}/tk_shorten.s | 0 .../{editor => engine_editor}/tokenise_line.s | 0 .../update_vartab_do_clr.s | 0 .../{engine => engine_runtime}/ad9e.frmevl.s | 0 .../{engine => engine_runtime}/ad9e.interop | 0 .../convert_PETSCII_to_digit.s | 0 .../{engine => engine_runtime}/do_error.s | 0 .../do_new_clr_restore.s | 0 .../end_of_statement.s | 0 .../execute_line_statements.s | 2 +- .../fetch_line_number.s | 0 .../fetch_operator.s | 0 .../{engine => engine_runtime}/fetch_uint16.s | 0 .../{engine => engine_runtime}/fetch_uint8.s | 0 .../follow_link_to_next_line.s | 0 .../helper_frmevl_strdesccpy_46K_50K.s | 0 .../{engine => engine_runtime}/init_oldtxt.s | 0 .../injest_assign.s | 0 .../{engine => engine_runtime}/injest_comma.s | 0 .../is_alphanumeric.s | 0 .../is_end_of_statement.s | 0 .../prepare_direct_execution.s | 0 .../select_device.s | 0 .../unconsume_character.s | 0 .../assign_variable.s} | 49 +++++----- .../fetch_variable.s | 0 .../fetch_variable_ST.s | 0 .../fetch_variable_TI.s | 0 .../fetch_variable_TI_string.s | 2 +- .../helper_cmp_fretop.s} | 2 +- .../helper_fretop.s} | 6 +- .../helper_fretop_up.s} | 4 +- .../helper_index_up_a_38K_60K.s | 24 +++++ .../helper_index_up_a_46K_50K.s} | 5 +- .../helper_strconcat_46K_50K.s} | 4 +- .../helper_strdesccpy_38K.s} | 4 +- .../helper_strdesccpy_46K_50K.s} | 4 +- .../helper_strdesccpy_60K.s} | 4 +- .../helper_strvarcpy_38K.s} | 4 +- .../helper_strvarcpy_46K_50K.s} | 4 +- .../helper_strvarcpy_60K.s} | 4 +- .../helper_txtptr_down.s} | 2 +- .../tmpstr_alloc.s | 33 ++++++- src/basic/engine_variables/tmpstr_free.s | 97 +++++++++++++++++++ src/basic/engine_variables/tmpstr_free_all.s | 20 ++++ .../varstr_alloc.s | 6 +- .../varstr_free.s | 8 +- .../varstr_garbage_collect.s | 12 +-- 64 files changed, 266 insertions(+), 87 deletions(-) delete mode 100644 src/basic/engine/tmpstr_free_all.s rename src/basic/{editor => engine_editor}/a533.interop (100%) rename src/basic/{editor => engine_editor}/a533.linkprg.s (100%) rename src/basic/{editor => engine_editor}/delete_line.s (100%) rename src/basic/{editor => engine_editor}/find_line.s (100%) rename src/basic/{editor => engine_editor}/insert_line.s (100%) rename src/basic/{editor => engine_editor}/shell.s (100%) rename src/basic/{editor => engine_editor}/shift_txt_down.s (100%) rename src/basic/{editor => engine_editor}/shift_txt_up.s (100%) rename src/basic/{editor => engine_editor}/tk_cut_away.s (100%) rename src/basic/{editor => engine_editor}/tk_pack.s (100%) rename src/basic/{editor => engine_editor}/tk_search.s (100%) rename src/basic/{editor => engine_editor}/tk_shorten.s (100%) rename src/basic/{editor => engine_editor}/tokenise_line.s (100%) rename src/basic/{editor => engine_editor}/update_vartab_do_clr.s (100%) rename src/basic/{engine => engine_runtime}/ad9e.frmevl.s (100%) rename src/basic/{engine => engine_runtime}/ad9e.interop (100%) rename src/basic/{engine => engine_runtime}/convert_PETSCII_to_digit.s (100%) rename src/basic/{engine => engine_runtime}/do_error.s (100%) rename src/basic/{engine => engine_runtime}/do_new_clr_restore.s (100%) rename src/basic/{engine => engine_runtime}/end_of_statement.s (100%) rename src/basic/{engine => engine_runtime}/execute_line_statements.s (99%) rename src/basic/{engine => engine_runtime}/fetch_line_number.s (100%) rename src/basic/{engine => engine_runtime}/fetch_operator.s (100%) rename src/basic/{engine => engine_runtime}/fetch_uint16.s (100%) rename src/basic/{engine => engine_runtime}/fetch_uint8.s (100%) rename src/basic/{engine => engine_runtime}/follow_link_to_next_line.s (100%) rename src/basic/{engine => engine_runtime}/helper_frmevl_strdesccpy_46K_50K.s (100%) rename src/basic/{engine => engine_runtime}/init_oldtxt.s (100%) rename src/basic/{engine => engine_runtime}/injest_assign.s (100%) rename src/basic/{engine => engine_runtime}/injest_comma.s (100%) rename src/basic/{engine => engine_runtime}/is_alphanumeric.s (100%) rename src/basic/{engine => engine_runtime}/is_end_of_statement.s (100%) rename src/basic/{engine => engine_runtime}/prepare_direct_execution.s (100%) rename src/basic/{engine => engine_runtime}/select_device.s (100%) rename src/basic/{engine => engine_runtime}/unconsume_character.s (100%) rename src/basic/{basic_commands/cmd_let.s => engine_variables/assign_variable.s} (82%) rename src/basic/{engine => engine_variables}/fetch_variable.s (100%) rename src/basic/{engine => engine_variables}/fetch_variable_ST.s (100%) rename src/basic/{engine => engine_variables}/fetch_variable_TI.s (100%) rename src/basic/{engine => engine_variables}/fetch_variable_TI_string.s (98%) rename src/basic/{engine/varstr_free_cmp_fretop.s => engine_variables/helper_cmp_fretop.s} (95%) rename src/basic/{engine/varstr_alloc_fretop.s => engine_variables/helper_fretop.s} (66%) rename src/basic/{engine/varstr_free_fretop.s => engine_variables/helper_fretop_up.s} (65%) create mode 100644 src/basic/engine_variables/helper_index_up_a_38K_60K.s rename src/basic/{engine/varstr_garbage_index_up_a.s => engine_variables/helper_index_up_a_46K_50K.s} (75%) rename src/basic/{basic_operators/helper_add_concat_46K_50K.s => engine_variables/helper_strconcat_46K_50K.s} (94%) rename src/basic/{basic_commands/helper_let_strdesccpy_38K.s => engine_variables/helper_strdesccpy_38K.s} (70%) rename src/basic/{basic_commands/helper_let_strdesccpy_46K_50K.s => engine_variables/helper_strdesccpy_46K_50K.s} (82%) rename src/basic/{basic_commands/helper_let_strdesccpy_60K.s => engine_variables/helper_strdesccpy_60K.s} (72%) rename src/basic/{basic_commands/helper_let_strvarcpy_38K.s => engine_variables/helper_strvarcpy_38K.s} (81%) rename src/basic/{basic_commands/helper_let_strvarcpy_46K_50K.s => engine_variables/helper_strvarcpy_46K_50K.s} (86%) rename src/basic/{basic_commands/helper_let_strvarcpy_60K.s => engine_variables/helper_strvarcpy_60K.s} (83%) rename src/basic/{engine/varstr_garbage_txtptr_down_s.s => engine_variables/helper_txtptr_down.s} (80%) rename src/basic/{engine => engine_variables}/tmpstr_alloc.s (56%) create mode 100644 src/basic/engine_variables/tmpstr_free.s create mode 100644 src/basic/engine_variables/tmpstr_free_all.s rename src/basic/{engine => engine_variables}/varstr_alloc.s (97%) rename src/basic/{engine => engine_variables}/varstr_free.s (91%) rename src/basic/{engine => engine_variables}/varstr_garbage_collect.s (97%) diff --git a/Makefile b/Makefile index 7dcd2041..4236d9ce 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,9 @@ SRCDIR_BASIC = $(SRCDIR_COMMON) \ src/basic/basic_functions \ src/basic/board_m65 \ src/basic/board_x16 \ - src/basic/editor \ - src/basic/engine \ + src/basic/engine_editor \ + src/basic/engine_runtime \ + src/basic/engine_variables \ src/basic/init \ src/basic/math \ src/basic/math_consts \ diff --git a/src/aliases/,aliases_cpu.s b/src/aliases/,aliases_cpu.s index d0f29fad..3cf72b6a 100644 --- a/src/aliases/,aliases_cpu.s +++ b/src/aliases/,aliases_cpu.s @@ -425,3 +425,17 @@ __l: __l: #endif } + + +// +// Near jump, on some CPUs can be substituted with shorter instruction +// + +.pseudocommand jmp_8 dst +{ +#if HAS_OPCODES_65C02 + bra dst +#else + jmp dst +#endif +} diff --git a/src/basic/basic_commands/cmd__jumptable.s b/src/basic/basic_commands/cmd__jumptable.s index 0a677b14..a23533a4 100644 --- a/src/basic/basic_commands/cmd__jumptable.s +++ b/src/basic/basic_commands/cmd__jumptable.s @@ -19,7 +19,7 @@ cmd_input, cmd_dim, cmd_read, - cmd_let, + assign_variable, // cmd_let cmd_goto, cmd_run, cmd_if, diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index 1118acbf..52124a25 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -36,13 +36,18 @@ oper_add_strings: pla sta __FAC2+0 - beq oper_add_strings_end // if string 2 is empty, we have nothing to do + + // If string 2 is empty, release it and quit + + beq oper_add_strings_end // If string 1 is empty, just copy the metadata lda __FAC1+0 bne !+ + jsr tmpstr_free_FAC1 + lda __FAC2+0 sta __FAC1+0 lda __FAC2+1 @@ -88,7 +93,7 @@ oper_add_strings: // Increase INDEX pointer by the size of the 1st string tya - jsr varstr_INDEX_up_A + jsr helper_INDEX_up_A // Copy data from the second string @@ -104,7 +109,7 @@ oper_add_strings: #elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - jsr helper_add_concat + jsr helper_strconcat #else // CONFIG_MEMORY_MODEL_38K @@ -121,7 +126,7 @@ oper_add_strings: // Increase INDEX pointer by the size of the 1st string tya - jsr varstr_INDEX_up_A + jsr helper_INDEX_up_A // Copy data from the second string @@ -135,11 +140,9 @@ oper_add_strings: #endif - // Free old strings - if they are temporary + // Free old FAC1 string - if it was temporary - // XXX - // XXX - // XXX + jsr tmpstr_free_FAC1 // Copy the descriptor to __FAC1 @@ -150,6 +153,9 @@ oper_add_strings: dey bpl !- + // FALLTROUGH + oper_add_strings_end: + jsr tmpstr_free_FAC2 jmp FRMEVL_continue diff --git a/src/basic/engine/tmpstr_free_all.s b/src/basic/engine/tmpstr_free_all.s deleted file mode 100644 index 5746080b..00000000 --- a/src/basic/engine/tmpstr_free_all.s +++ /dev/null @@ -1,10 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - - -tmpstr_free_all: - - // XXX implement this - - rts diff --git a/src/basic/editor/a533.interop b/src/basic/engine_editor/a533.interop similarity index 100% rename from src/basic/editor/a533.interop rename to src/basic/engine_editor/a533.interop diff --git a/src/basic/editor/a533.linkprg.s b/src/basic/engine_editor/a533.linkprg.s similarity index 100% rename from src/basic/editor/a533.linkprg.s rename to src/basic/engine_editor/a533.linkprg.s diff --git a/src/basic/editor/delete_line.s b/src/basic/engine_editor/delete_line.s similarity index 100% rename from src/basic/editor/delete_line.s rename to src/basic/engine_editor/delete_line.s diff --git a/src/basic/editor/find_line.s b/src/basic/engine_editor/find_line.s similarity index 100% rename from src/basic/editor/find_line.s rename to src/basic/engine_editor/find_line.s diff --git a/src/basic/editor/insert_line.s b/src/basic/engine_editor/insert_line.s similarity index 100% rename from src/basic/editor/insert_line.s rename to src/basic/engine_editor/insert_line.s diff --git a/src/basic/editor/shell.s b/src/basic/engine_editor/shell.s similarity index 100% rename from src/basic/editor/shell.s rename to src/basic/engine_editor/shell.s diff --git a/src/basic/editor/shift_txt_down.s b/src/basic/engine_editor/shift_txt_down.s similarity index 100% rename from src/basic/editor/shift_txt_down.s rename to src/basic/engine_editor/shift_txt_down.s diff --git a/src/basic/editor/shift_txt_up.s b/src/basic/engine_editor/shift_txt_up.s similarity index 100% rename from src/basic/editor/shift_txt_up.s rename to src/basic/engine_editor/shift_txt_up.s diff --git a/src/basic/editor/tk_cut_away.s b/src/basic/engine_editor/tk_cut_away.s similarity index 100% rename from src/basic/editor/tk_cut_away.s rename to src/basic/engine_editor/tk_cut_away.s diff --git a/src/basic/editor/tk_pack.s b/src/basic/engine_editor/tk_pack.s similarity index 100% rename from src/basic/editor/tk_pack.s rename to src/basic/engine_editor/tk_pack.s diff --git a/src/basic/editor/tk_search.s b/src/basic/engine_editor/tk_search.s similarity index 100% rename from src/basic/editor/tk_search.s rename to src/basic/engine_editor/tk_search.s diff --git a/src/basic/editor/tk_shorten.s b/src/basic/engine_editor/tk_shorten.s similarity index 100% rename from src/basic/editor/tk_shorten.s rename to src/basic/engine_editor/tk_shorten.s diff --git a/src/basic/editor/tokenise_line.s b/src/basic/engine_editor/tokenise_line.s similarity index 100% rename from src/basic/editor/tokenise_line.s rename to src/basic/engine_editor/tokenise_line.s diff --git a/src/basic/editor/update_vartab_do_clr.s b/src/basic/engine_editor/update_vartab_do_clr.s similarity index 100% rename from src/basic/editor/update_vartab_do_clr.s rename to src/basic/engine_editor/update_vartab_do_clr.s diff --git a/src/basic/engine/ad9e.frmevl.s b/src/basic/engine_runtime/ad9e.frmevl.s similarity index 100% rename from src/basic/engine/ad9e.frmevl.s rename to src/basic/engine_runtime/ad9e.frmevl.s diff --git a/src/basic/engine/ad9e.interop b/src/basic/engine_runtime/ad9e.interop similarity index 100% rename from src/basic/engine/ad9e.interop rename to src/basic/engine_runtime/ad9e.interop diff --git a/src/basic/engine/convert_PETSCII_to_digit.s b/src/basic/engine_runtime/convert_PETSCII_to_digit.s similarity index 100% rename from src/basic/engine/convert_PETSCII_to_digit.s rename to src/basic/engine_runtime/convert_PETSCII_to_digit.s diff --git a/src/basic/engine/do_error.s b/src/basic/engine_runtime/do_error.s similarity index 100% rename from src/basic/engine/do_error.s rename to src/basic/engine_runtime/do_error.s diff --git a/src/basic/engine/do_new_clr_restore.s b/src/basic/engine_runtime/do_new_clr_restore.s similarity index 100% rename from src/basic/engine/do_new_clr_restore.s rename to src/basic/engine_runtime/do_new_clr_restore.s diff --git a/src/basic/engine/end_of_statement.s b/src/basic/engine_runtime/end_of_statement.s similarity index 100% rename from src/basic/engine/end_of_statement.s rename to src/basic/engine_runtime/end_of_statement.s diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine_runtime/execute_line_statements.s similarity index 99% rename from src/basic/engine/execute_line_statements.s rename to src/basic/engine_runtime/execute_line_statements.s index eb1cf0ad..40ad1821 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine_runtime/execute_line_statements.s @@ -250,4 +250,4 @@ execute_statements_var_assign: #else dew TXTPTR #endif - jmp cmd_let + jmp assign_variable diff --git a/src/basic/engine/fetch_line_number.s b/src/basic/engine_runtime/fetch_line_number.s similarity index 100% rename from src/basic/engine/fetch_line_number.s rename to src/basic/engine_runtime/fetch_line_number.s diff --git a/src/basic/engine/fetch_operator.s b/src/basic/engine_runtime/fetch_operator.s similarity index 100% rename from src/basic/engine/fetch_operator.s rename to src/basic/engine_runtime/fetch_operator.s diff --git a/src/basic/engine/fetch_uint16.s b/src/basic/engine_runtime/fetch_uint16.s similarity index 100% rename from src/basic/engine/fetch_uint16.s rename to src/basic/engine_runtime/fetch_uint16.s diff --git a/src/basic/engine/fetch_uint8.s b/src/basic/engine_runtime/fetch_uint8.s similarity index 100% rename from src/basic/engine/fetch_uint8.s rename to src/basic/engine_runtime/fetch_uint8.s diff --git a/src/basic/engine/follow_link_to_next_line.s b/src/basic/engine_runtime/follow_link_to_next_line.s similarity index 100% rename from src/basic/engine/follow_link_to_next_line.s rename to src/basic/engine_runtime/follow_link_to_next_line.s diff --git a/src/basic/engine/helper_frmevl_strdesccpy_46K_50K.s b/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s similarity index 100% rename from src/basic/engine/helper_frmevl_strdesccpy_46K_50K.s rename to src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s diff --git a/src/basic/engine/init_oldtxt.s b/src/basic/engine_runtime/init_oldtxt.s similarity index 100% rename from src/basic/engine/init_oldtxt.s rename to src/basic/engine_runtime/init_oldtxt.s diff --git a/src/basic/engine/injest_assign.s b/src/basic/engine_runtime/injest_assign.s similarity index 100% rename from src/basic/engine/injest_assign.s rename to src/basic/engine_runtime/injest_assign.s diff --git a/src/basic/engine/injest_comma.s b/src/basic/engine_runtime/injest_comma.s similarity index 100% rename from src/basic/engine/injest_comma.s rename to src/basic/engine_runtime/injest_comma.s diff --git a/src/basic/engine/is_alphanumeric.s b/src/basic/engine_runtime/is_alphanumeric.s similarity index 100% rename from src/basic/engine/is_alphanumeric.s rename to src/basic/engine_runtime/is_alphanumeric.s diff --git a/src/basic/engine/is_end_of_statement.s b/src/basic/engine_runtime/is_end_of_statement.s similarity index 100% rename from src/basic/engine/is_end_of_statement.s rename to src/basic/engine_runtime/is_end_of_statement.s diff --git a/src/basic/engine/prepare_direct_execution.s b/src/basic/engine_runtime/prepare_direct_execution.s similarity index 100% rename from src/basic/engine/prepare_direct_execution.s rename to src/basic/engine_runtime/prepare_direct_execution.s diff --git a/src/basic/engine/select_device.s b/src/basic/engine_runtime/select_device.s similarity index 100% rename from src/basic/engine/select_device.s rename to src/basic/engine_runtime/select_device.s diff --git a/src/basic/engine/unconsume_character.s b/src/basic/engine_runtime/unconsume_character.s similarity index 100% rename from src/basic/engine/unconsume_character.s rename to src/basic/engine_runtime/unconsume_character.s diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/engine_variables/assign_variable.s similarity index 82% rename from src/basic/basic_commands/cmd_let.s rename to src/basic/engine_variables/assign_variable.s index 2a03c68a..d9e24960 100644 --- a/src/basic/basic_commands/cmd_let.s +++ b/src/basic/engine_variables/assign_variable.s @@ -3,8 +3,7 @@ // #LAYOUT# * * #IGNORE - -cmd_let: +assign_variable: // Fetch variable name, should be followed by assign operator @@ -62,14 +61,14 @@ cmd_let: // Determine what to assign pla - bmi cmd_let_assign_string - beq cmd_let_assign_float + bmi assign_string + beq assign_float // FALLTROUGH // XXX integer and float probably have much in common -cmd_let_assign_integer: +assign_integer: lda VALTYP bmi_16 do_TYPE_MISMATCH_error @@ -97,7 +96,7 @@ cmd_let_assign_integer: jmp do_NOT_IMPLEMENTED_error -cmd_let_assign_float: +assign_float: lda VALTYP bmi_16 do_TYPE_MISMATCH_error @@ -125,7 +124,7 @@ cmd_let_assign_float: jmp do_NOT_IMPLEMENTED_error -cmd_let_assign_string: +assign_string: // Check if value type matches @@ -134,12 +133,12 @@ cmd_let_assign_string: // Copy the string descriptor to DSCPNT - jsr helper_let_strdesccpy + jsr helper_strdesccpy // First special case - check if the new string has size 0 lda __FAC1+0 - bne cmd_let_assign_string_not_empty + bne assign_string_not_empty // Yes, it is empty - free the old one @@ -159,41 +158,41 @@ cmd_let_assign_string: rts -cmd_let_assign_string_not_empty: +assign_string_not_empty: // Check if the source and destination strings are the same lda DSCPNT+1 cmp __FAC1+1 - bne cmd_let_assign_string_not_same + bne assign_string_not_same iny lda DSCPNT+2 cmp __FAC1+2 - bne cmd_let_assign_string_not_same + bne assign_string_not_same // If we are here, than both source and destination strings are the same - nothing more to be done rts -cmd_let_assign_string_not_same: +assign_string_not_same: // Strings are not the same - check if the new one is located within the text area, between TXTTAB and VARTAB lda VARTAB+1 cmp __FAC1+2 - bcc cmd_let_assign_string_not_text_area + bcc assign_string_not_text_area bne !+ lda VARTAB+0 cmp __FAC1+1 - bcc cmd_let_assign_string_not_text_area + bcc assign_string_not_text_area !: lda __FAC1+2 cmp TXTTAB+1 - bcc cmd_let_assign_string_not_text_area + bcc assign_string_not_text_area bne !+ lda __FAC1+1 cmp TXTTAB+0 - bcc cmd_let_assign_string_not_text_area + bcc assign_string_not_text_area !: // String is located within text area - great, just copy the descriptor @@ -227,7 +226,7 @@ cmd_let_assign_string_not_same: rts -cmd_let_assign_string_not_text_area: +assign_string_not_text_area: // Check if the new string is a temporary one - if so, reuse alocation @@ -235,12 +234,12 @@ cmd_let_assign_string_not_text_area: // Check if the old string belongs to the string area (is above FRETOP) - jsr varstr_cmp_fretop - bcc cmd_let_assign_string_no_optimizations + jsr helper_cmp_fretop + bcc assign_string_no_optimizations // FALLTROUGH -cmd_let_assign_string_try_reuse: +assign_string_try_reuse: // Check if we can reuse old string memory @@ -249,9 +248,9 @@ cmd_let_assign_string_try_reuse: // If size of both string equals - simply reuse it - beq_16 helper_let_strvarcpy + beq_16 helper_strvarcpy -cmd_let_assign_string_try_reuse_unsuccesful: +assign_string_try_reuse_unsuccesful: // No special case optimization is possible - but first get rid of the old string @@ -259,7 +258,7 @@ cmd_let_assign_string_try_reuse_unsuccesful: // FALLTROUGH -cmd_let_assign_string_no_optimizations: +assign_string_no_optimizations: // Allocate memory for the new string @@ -281,4 +280,4 @@ cmd_let_assign_string_no_optimizations: // Copy the string and quit - jmp helper_let_strvarcpy + jmp helper_strvarcpy diff --git a/src/basic/engine/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s similarity index 100% rename from src/basic/engine/fetch_variable.s rename to src/basic/engine_variables/fetch_variable.s diff --git a/src/basic/engine/fetch_variable_ST.s b/src/basic/engine_variables/fetch_variable_ST.s similarity index 100% rename from src/basic/engine/fetch_variable_ST.s rename to src/basic/engine_variables/fetch_variable_ST.s diff --git a/src/basic/engine/fetch_variable_TI.s b/src/basic/engine_variables/fetch_variable_TI.s similarity index 100% rename from src/basic/engine/fetch_variable_TI.s rename to src/basic/engine_variables/fetch_variable_TI.s diff --git a/src/basic/engine/fetch_variable_TI_string.s b/src/basic/engine_variables/fetch_variable_TI_string.s similarity index 98% rename from src/basic/engine/fetch_variable_TI_string.s rename to src/basic/engine_variables/fetch_variable_TI_string.s index 12971013..753477b9 100644 --- a/src/basic/engine/fetch_variable_TI_string.s +++ b/src/basic/engine_variables/fetch_variable_TI_string.s @@ -11,7 +11,7 @@ fetch_variable_TI_string: lda #$06 jsr tmpstr_alloc - jsr helper_let_strdesccpy + jsr helper_strdesccpy // Fetch the time in a safe way, store it in temporary area diff --git a/src/basic/engine/varstr_free_cmp_fretop.s b/src/basic/engine_variables/helper_cmp_fretop.s similarity index 95% rename from src/basic/engine/varstr_free_cmp_fretop.s rename to src/basic/engine_variables/helper_cmp_fretop.s index d11540bb..2249d8c2 100644 --- a/src/basic/engine/varstr_free_cmp_fretop.s +++ b/src/basic/engine_variables/helper_cmp_fretop.s @@ -10,7 +10,7 @@ // - Carry flag set - this string belongs to the string area -varstr_cmp_fretop: +helper_cmp_fretop: lda DSCPNT+2 cmp FRETOP+1 diff --git a/src/basic/engine/varstr_alloc_fretop.s b/src/basic/engine_variables/helper_fretop.s similarity index 66% rename from src/basic/engine/varstr_alloc_fretop.s rename to src/basic/engine_variables/helper_fretop.s index b108e471..5e13331e 100644 --- a/src/basic/engine/varstr_alloc_fretop.s +++ b/src/basic/engine_variables/helper_fretop.s @@ -3,10 +3,10 @@ // #LAYOUT# * * #IGNORE // -// Helper routines for 'varstr_alloc' +// Helper routines for FRETOP handling // -varstr_FRETOP_down_A: // .A - bytes to lower FRETOP, uses DSCPNT+0 +helper_FRETOP_down_A: // .A - bytes to lower FRETOP, uses DSCPNT+0 sta DSCPNT+0 @@ -19,7 +19,7 @@ varstr_FRETOP_down_A: // .A - bytes to lower FRETOP, uses DSCPN !: // FALLTROUGH -varstr_FRETOP_check: // check if FRETOP > STREND, Carry set if not +helper_FRETOP_check: // check if FRETOP > STREND, Carry set if not lda STREND+1 cmp FRETOP+1 diff --git a/src/basic/engine/varstr_free_fretop.s b/src/basic/engine_variables/helper_fretop_up.s similarity index 65% rename from src/basic/engine/varstr_free_fretop.s rename to src/basic/engine_variables/helper_fretop_up.s index 7cf7d941..de5ee2b2 100644 --- a/src/basic/engine/varstr_free_fretop.s +++ b/src/basic/engine_variables/helper_fretop_up.s @@ -3,11 +3,11 @@ // #LAYOUT# * * #IGNORE // -// Helper routines for 'varstr_free' +// Helper routine for FRETOP handling // -varstr_FRETOP_up: // DSCPNT+0 - bytes to increment FRETO +helper_FRETOP_up: // DSCPNT+0 - bytes to increment FRETO clc lda FRETOP+0 diff --git a/src/basic/engine_variables/helper_index_up_a_38K_60K.s b/src/basic/engine_variables/helper_index_up_a_38K_60K.s new file mode 100644 index 00000000..5e318f25 --- /dev/null +++ b/src/basic/engine_variables/helper_index_up_a_38K_60K.s @@ -0,0 +1,24 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine, used by garbage collector and string concatenation +// + +#if CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K + +helper_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+0 + + sta DSCPNT+0 + + clc + lda INDEX+0 + adc DSCPNT+0 + sta INDEX+0 + bcc !+ + dec INDEX+1 +!: + rts + +#endif diff --git a/src/basic/engine/varstr_garbage_index_up_a.s b/src/basic/engine_variables/helper_index_up_a_46K_50K.s similarity index 75% rename from src/basic/engine/varstr_garbage_index_up_a.s rename to src/basic/engine_variables/helper_index_up_a_46K_50K.s index 42a661c5..2943073a 100644 --- a/src/basic/engine/varstr_garbage_index_up_a.s +++ b/src/basic/engine_variables/helper_index_up_a_46K_50K.s @@ -8,8 +8,9 @@ // Helper routine, used by garbage collector and string concatenation // +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K -varstr_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+0 +helper_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DSCPNT+0 sta DSCPNT+0 @@ -21,3 +22,5 @@ varstr_INDEX_up_A: // .A - bytes to increase TXTPTR, uses DS dec INDEX+1 !: rts + +#endif diff --git a/src/basic/basic_operators/helper_add_concat_46K_50K.s b/src/basic/engine_variables/helper_strconcat_46K_50K.s similarity index 94% rename from src/basic/basic_operators/helper_add_concat_46K_50K.s rename to src/basic/engine_variables/helper_strconcat_46K_50K.s index f777a3e3..e44ea918 100644 --- a/src/basic/basic_operators/helper_add_concat_46K_50K.s +++ b/src/basic/engine_variables/helper_strconcat_46K_50K.s @@ -11,7 +11,7 @@ #if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K -helper_add_concat: +helper_strconcat: // Unmap BASIC lower ROM @@ -31,7 +31,7 @@ helper_add_concat: // Increase INDEX pointer by the size of the 1st string tya - jsr varstr_INDEX_up_A + jsr helper_INDEX_up_A // Copy data from the second string diff --git a/src/basic/basic_commands/helper_let_strdesccpy_38K.s b/src/basic/engine_variables/helper_strdesccpy_38K.s similarity index 70% rename from src/basic/basic_commands/helper_let_strdesccpy_38K.s rename to src/basic/engine_variables/helper_strdesccpy_38K.s index 84f33d8a..04870841 100644 --- a/src/basic/basic_commands/helper_let_strdesccpy_38K.s +++ b/src/basic/engine_variables/helper_strdesccpy_38K.s @@ -3,13 +3,13 @@ // #LAYOUT# * * #IGNORE // -// Helper routine to copy string descriptor, for LET command and TI$ variable support +// Helper routine to copy string descriptor // #if CONFIG_MEMORY_MODEL_38K -helper_let_strdesccpy: +helper_strdesccpy: ldy #$00 lda (VARPNT), y diff --git a/src/basic/basic_commands/helper_let_strdesccpy_46K_50K.s b/src/basic/engine_variables/helper_strdesccpy_46K_50K.s similarity index 82% rename from src/basic/basic_commands/helper_let_strdesccpy_46K_50K.s rename to src/basic/engine_variables/helper_strdesccpy_46K_50K.s index 939da07b..2e90d6b0 100644 --- a/src/basic/basic_commands/helper_let_strdesccpy_46K_50K.s +++ b/src/basic/engine_variables/helper_strdesccpy_46K_50K.s @@ -5,13 +5,13 @@ // This has to go $E000 or above - routines below banks out the main BASIC ROM! // -// Helper routine to copy string descriptor, for LET command and TI$ variable support +// Helper routine to copy string descriptor // #if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K -helper_let_strdesccpy: +helper_strdesccpy: // Unmap BASIC lower ROM diff --git a/src/basic/basic_commands/helper_let_strdesccpy_60K.s b/src/basic/engine_variables/helper_strdesccpy_60K.s similarity index 72% rename from src/basic/basic_commands/helper_let_strdesccpy_60K.s rename to src/basic/engine_variables/helper_strdesccpy_60K.s index ea9a1c88..9e627a18 100644 --- a/src/basic/basic_commands/helper_let_strdesccpy_60K.s +++ b/src/basic/engine_variables/helper_strdesccpy_60K.s @@ -3,13 +3,13 @@ // #LAYOUT# * * #IGNORE // -// Helper routine to copy string descriptor, for LET command and TI$ variable support +// Helper routine to copy string descriptor // #if CONFIG_MEMORY_MODEL_60K -helper_let_strdesccpy: +helper_strdesccpy: ldx # Date: Sun, 19 Jul 2020 09:46:04 +0200 Subject: [PATCH 064/130] temporary strings are now freed when needed --- bin/basic_generic.rom | Bin 8192 -> 8192 bytes bin/basic_ultimate64.rom | Bin 8192 -> 8192 bytes bin/kernal_generic.rom | Bin 8192 -> 8192 bytes bin/kernal_ultimate64.rom | Bin 8192 -> 8192 bytes bin/mega65.rom | Bin 131072 -> 131072 bytes bin/mega65_pxlfont.rom | Bin 131072 -> 131072 bytes src/,,config_generic.s | 4 +-- src/,,config_ultimate64.s | 4 +-- src/basic/basic_commands/cmd_print.s | 3 +- src/basic/board_m65/mega65_imports.s | 1 + src/basic/engine_runtime/do_new_clr_restore.s | 5 +--- src/basic/engine_variables/tmpstr_free.s | 2 +- src/basic/engine_variables/tmpstr_free_all.s | 26 ++++++++++++++++-- src/basic/engine_variables/varstr_free.s | 6 ++-- 14 files changed, 36 insertions(+), 15 deletions(-) diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 62954140c1caa0b0ab1282840747865c29cb6041..217ffa26cdc08aed101d50c37eed953a3e2219ca 100644 GIT binary patch delta 4251 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 delta 4127 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 Ym{WuJ<*9gtDmN?qBm*#1Zm_Zc3%vs_P5=M^ delta 3904 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 SHyjN2o7}CwKP~=^=l=kJ_I@+~ diff --git a/bin/mega65.rom b/bin/mega65.rom index aa8a0643cf4e4250647fcdbd33f852d2432dc46c..eb0abc7e748f62683f6a1d45f7eaa77c521d854d 100644 GIT binary patch delta 3626 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 delta 3300 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 diff --git a/bin/mega65_pxlfont.rom b/bin/mega65_pxlfont.rom index cabc4485c688d7a73fad4ac75151e5a9b04fe26e..9e2a96b50c84fb3654eb7b0a1d399a0b22e76333 100644 GIT binary patch delta 3626 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 delta 3300 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 diff --git a/src/,,config_generic.s b/src/,,config_generic.s index 391de569..42fa2925 100644 --- a/src/,,config_generic.s +++ b/src/,,config_generic.s @@ -36,9 +36,9 @@ // Memory model -// #define CONFIG_MEMORY_MODEL_38K +#define CONFIG_MEMORY_MODEL_38K // #define CONFIG_MEMORY_MODEL_46K -#define CONFIG_MEMORY_MODEL_50K +// #define CONFIG_MEMORY_MODEL_50K // #define CONFIG_MEMORY_MODEL_60K diff --git a/src/,,config_ultimate64.s b/src/,,config_ultimate64.s index b463c918..e30ec05d 100644 --- a/src/,,config_ultimate64.s +++ b/src/,,config_ultimate64.s @@ -36,9 +36,9 @@ // Memory model -// #define CONFIG_MEMORY_MODEL_38K +#define CONFIG_MEMORY_MODEL_38K // #define CONFIG_MEMORY_MODEL_46K -#define CONFIG_MEMORY_MODEL_50K +// #define CONFIG_MEMORY_MODEL_50K // #define CONFIG_MEMORY_MODEL_60K diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index 2c81a2de..c4c260c2 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -29,8 +29,9 @@ cmd_print_loop: cmd_print_after_comma: - // Now evaluate the expression + // Now evaluate the expression and check what to print + jsr tmpstr_free_all jsr FRMEVL lda VALTYP bpl cmd_print_float diff --git a/src/basic/board_m65/mega65_imports.s b/src/basic/board_m65/mega65_imports.s index c7aa9c34..a9891af5 100644 --- a/src/basic/board_m65/mega65_imports.s +++ b/src/basic/board_m65/mega65_imports.s @@ -25,6 +25,7 @@ .label JREADST = KERNAL_0.JREADST .label plot_set = KERNAL_0.plot_set .label init_oldtxt = BASIC_0.init_oldtxt +.label tmpstr_free_all_reset = BASIC_0.tmpstr_free_all_reset .label rom_revision_basic_string = BASIC_0.rom_revision_basic_string .label print_hex_byte = BASIC_0.proxy_B1_print_hex_byte .label print_integer = BASIC_0.proxy_B1_print_integer diff --git a/src/basic/engine_runtime/do_new_clr_restore.s b/src/basic/engine_runtime/do_new_clr_restore.s index 0323e5ad..28fbfed7 100644 --- a/src/basic/engine_runtime/do_new_clr_restore.s +++ b/src/basic/engine_runtime/do_new_clr_restore.s @@ -71,10 +71,7 @@ do_clr: // This is a good place to reset the temporary string stack - lda #$19 - sta TEMPPT - lda #$16 - sta LASTPT + jsr tmpstr_free_all_reset // FALLTROUGH (confirmed on real C64 that CLR indeed resets DATPTR) diff --git a/src/basic/engine_variables/tmpstr_free.s b/src/basic/engine_variables/tmpstr_free.s index b9d6c494..5d0086b8 100644 --- a/src/basic/engine_variables/tmpstr_free.s +++ b/src/basic/engine_variables/tmpstr_free.s @@ -67,7 +67,7 @@ tmpstr_free_loop: sty DSCPNT+0 phx_trash_a - jsr varstr_free + jsr varstr_free_non_0 plx_trash_a // Mark empty string as free and quit diff --git a/src/basic/engine_variables/tmpstr_free_all.s b/src/basic/engine_variables/tmpstr_free_all.s index 6f5c354c..303cff6e 100644 --- a/src/basic/engine_variables/tmpstr_free_all.s +++ b/src/basic/engine_variables/tmpstr_free_all.s @@ -9,12 +9,32 @@ tmpstr_free_all: ldx #$19 - // XXX implement this - //FALLTROUGH tmpstr_free_all_loop: - // XXX finish, deduplicate part with CLR + // Free all the strings, one by one + + cpx TEMPPT + beq tmpstr_free_all_reset + + lda $00, x + beq !+ + + phx_trash_a + jsr varstr_free_non_0 + plx_trash_a +!: + inx + bne tmpstr_free_all_loop // branch always + +tmpstr_free_all_reset: // entry point for CLR + + // RESET TEMPPT and LASTPT to default values + + lda #$19 + sta TEMPPT + lda #$16 + sta LASTPT rts diff --git a/src/basic/engine_variables/varstr_free.s b/src/basic/engine_variables/varstr_free.s index 8d9b5f4f..1f57d165 100644 --- a/src/basic/engine_variables/varstr_free.s +++ b/src/basic/engine_variables/varstr_free.s @@ -16,9 +16,11 @@ varstr_free: // Check the string size - do not do anything if 0 lda DSCPNT+0 - bne !+ + bne varstr_free_non_0 rts -!: + +varstr_free_non_0: // entry point to be used when it is clear that string is not empty + // Check if string is above FRETOP (in string area) // XXX move this check out of the routine From 3b4cf3faef72689301dc770115ed64c442afdc1f Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 10:21:25 +0200 Subject: [PATCH 065/130] use pseudocode instead of jmp/bra selection --- src/basic/basic_commands/cmd_run_goto.s | 7 +----- src/basic/basic_commands_CC/cmd_mem.s | 6 +---- src/basic/engine_editor/find_line.s | 10 ++++---- src/basic/engine_editor/tk_shorten.s | 6 +---- src/basic/engine_editor/tokenise_line.s | 6 +---- src/basic/engine_runtime/ad9e.frmevl.s | 6 +---- src/basic/engine_runtime/fetch_uint16.s | 6 +---- src/basic/engine_variables/fetch_variable.s | 12 ++------- src/basic/engine_variables/tmpstr_free.s | 7 ++---- src/basic/engine_variables/varstr_alloc.s | 6 +---- .../memory/under_rom_peek_fetch_46k_50k.s | 21 +++------------- src/basic/memory/under_rom_shift_46k_50k.s | 6 +---- src/basic/print/list_single_line.s | 25 ++++--------------- src/basic/print/print_packed_freq_string.s | 2 +- src/basic/wedge/wedge_dos.s | 12 ++------- src/kernal/keyboard/scnkey.s | 7 ++---- src/kernal/memory/under_rom_46k_50k.s | 12 ++------- 17 files changed, 32 insertions(+), 125 deletions(-) diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index 4f181c7a..043862c3 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -49,12 +49,7 @@ cmd_goto: // Else - search from the current line jsr find_line_from_current - -#if HAS_OPCODES_65C02 - bra cmd_goto_check -#else - jmp cmd_goto_check -#endif + jmp_8 cmd_goto_check cmd_goto_direct: diff --git a/src/basic/basic_commands_CC/cmd_mem.s b/src/basic/basic_commands_CC/cmd_mem.s index ee15221c..ded5d334 100644 --- a/src/basic/basic_commands_CC/cmd_mem.s +++ b/src/basic/basic_commands_CC/cmd_mem.s @@ -123,11 +123,7 @@ cmd_mem_loop: bcs !+ lda #$3F jsr JCHROUT -#if HAS_OPCODES_65C02 - bra cmd_mem_next -#else - jmp cmd_mem_next -#endif + jmp_8 cmd_mem_next !: jsr print_integer diff --git a/src/basic/engine_editor/find_line.s b/src/basic/engine_editor/find_line.s index 9487e432..b99f86a2 100644 --- a/src/basic/engine_editor/find_line.s +++ b/src/basic/engine_editor/find_line.s @@ -24,6 +24,8 @@ find_line_from_current: // Fetch the high byte of line number and compare ldy #$03 + // XXX consider optimized 46K/50K version + #if CONFIG_MEMORY_MODEL_60K ldx # $FF jsr varstr_garbage_collect -#if HAS_OPCODES_65C02 - bra varstr_alloc_retry -#else - jmp varstr_alloc_retry -#endif + jmp_8 varstr_alloc_retry diff --git a/src/basic/memory/under_rom_peek_fetch_46k_50k.s b/src/basic/memory/under_rom_peek_fetch_46k_50k.s index 6aedc40d..31368d5e 100644 --- a/src/basic/memory/under_rom_peek_fetch_46k_50k.s +++ b/src/basic/memory/under_rom_peek_fetch_46k_50k.s @@ -44,12 +44,7 @@ peek_under_roms_via_OLDTXT: // Retrieve value from under ROMs lda (OLDTXT), y - -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize peek_under_roms_via_VARPNT: @@ -61,12 +56,7 @@ peek_under_roms_via_VARPNT: // Retrieve value from under ROMs lda (VARPNT), y - -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize peek_under_roms_via_FAC1_PLUS_1: @@ -78,12 +68,7 @@ peek_under_roms_via_FAC1_PLUS_1: // Retrieve value from under ROMs lda (__FAC1 + 1), y - -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize #if ROM_LAYOUT_M65 diff --git a/src/basic/memory/under_rom_shift_46k_50k.s b/src/basic/memory/under_rom_shift_46k_50k.s index 99912589..cd023d33 100644 --- a/src/basic/memory/under_rom_shift_46k_50k.s +++ b/src/basic/memory/under_rom_shift_46k_50k.s @@ -33,11 +33,7 @@ shift_mem_up_internal: dec memmove__size+1 bne !- -#if HAS_OPCODES_65C02 - bra shift_mem_internal_finalize -#else - jmp shift_mem_internal_finalize -#endif + jmp_8 shift_mem_internal_finalize shift_mem_down_internal: diff --git a/src/basic/print/list_single_line.s b/src/basic/print/list_single_line.s index 65581a6e..ac2a4e19 100644 --- a/src/basic/print/list_single_line.s +++ b/src/basic/print/list_single_line.s @@ -127,11 +127,8 @@ list_display_token_CC: // Now ask for it to be printed jsr print_packed_keyword_CC -#if HAS_OPCODES_65C02 - bra list_token_displayed -#else - jmp list_token_displayed -#endif + jmp_8 list_token_displayed + list_display_token_CD: @@ -169,11 +166,7 @@ list_display_token_CD: // Now ask for it to be printed jsr print_packed_keyword_CD -#if HAS_OPCODES_65C02 - bra list_token_displayed -#else - jmp list_token_displayed -#endif + jmp_8 list_token_displayed list_display_token_V2: @@ -242,11 +235,7 @@ list_is_unknown: jsr STROUT ply_trash_a -#if HAS_OPCODES_65C02 - bra !+ -#else - jmp !+ -#endif + jmp_8 !+ list_is_literal_known: @@ -263,10 +252,6 @@ list_display_unknown_token: pla pla -#if HAS_OPCODES_65C02 - bra list_is_unknown -#else - jmp list_is_unknown -#endif + jmp_8 list_is_unknown #endif // ROM layout diff --git a/src/basic/print/print_packed_freq_string.s b/src/basic/print/print_packed_freq_string.s index a936a675..a467b850 100644 --- a/src/basic/print/print_packed_freq_string.s +++ b/src/basic/print/print_packed_freq_string.s @@ -114,7 +114,7 @@ print_freq_packed_string_nibble_hi: tax lda packed_as_1n-1, x - jmp !+ // XXX should be bra on some CPUs + jmp_8 !+ print_freq_packed_string_3n_single: diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index b1a1a555..ace10a2c 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -216,11 +216,7 @@ wedge_dos_status_get_done: wedge_dos_status: jsr wedge_dos_status_get -#if HAS_OPCODES_65C02 - bra wedge_dos_status_print_no_new_line -#else - jmp wedge_dos_status_print_no_new_line -#endif + jmp_8 wedge_dos_status_print_no_new_line wedge_dos_status_print: @@ -243,11 +239,7 @@ wedge_dos_status_print_no_new_line: !: // Clean-up and exit -#if HAS_OPCODES_65C02 - bra wedge_dos_clean_exit -#else - jmp wedge_dos_clean_exit -#endif + jmp_8 wedge_dos_clean_exit wedge_dos_directory: diff --git a/src/kernal/keyboard/scnkey.s b/src/kernal/keyboard/scnkey.s index cf832bf0..cd0cb7a5 100644 --- a/src/kernal/keyboard/scnkey.s +++ b/src/kernal/keyboard/scnkey.s @@ -150,11 +150,8 @@ scnkey_bucky_loop: lda KEYLOG+1 bne !+ jsr scnkey_set_keytab // KEYLOG routine on zeropage? most likely vector not set -#if HAS_OPCODES_65C02 - bra scnkey_keytab_set_done -#else - jmp scnkey_keytab_set_done -#endif + jmp_8 scnkey_keytab_set_done + !: #if HAS_OPCODES_65CE02 jsr_ind KEYLOG diff --git a/src/kernal/memory/under_rom_46k_50k.s b/src/kernal/memory/under_rom_46k_50k.s index 0db1dc6b..04ef9714 100644 --- a/src/kernal/memory/under_rom_46k_50k.s +++ b/src/kernal/memory/under_rom_46k_50k.s @@ -53,11 +53,7 @@ peek_under_roms_via_FNADDR: // Continue using common code -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize peek_under_roms_via_EAL: @@ -75,11 +71,7 @@ peek_under_roms_via_EAL: // Continue using common code -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize #endif From e85b5dbccf60a21e7685969324a6154e8fd3bf36 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 10:59:18 +0200 Subject: [PATCH 066/130] small ST/TI/TI$ cleanup --- src/basic/engine_variables/fetch_variable.s | 27 +++++-------------- src/basic/engine_variables/is_var_ST.s | 17 ++++++++++++ src/basic/engine_variables/is_var_TI.s | 17 ++++++++++++ src/basic/engine_variables/is_var_TI_string.s | 17 ++++++++++++ 4 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 src/basic/engine_variables/is_var_ST.s create mode 100644 src/basic/engine_variables/is_var_TI.s create mode 100644 src/basic/engine_variables/is_var_TI_string.s diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 95055994..1c8cc5be 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -93,28 +93,15 @@ fetch_variable_type_string: fetch_variable_special: - lda VARNAM+0 - cmp #$54 // 'T' - beq !+ - cmp #$53 // 'S' - bne fetch_variable_find_addr - - // First character is 'S', check the second one - - lda VARNAM+1 - cmp #$54 // 'T' - bne fetch_variable_find_addr - - jmp fetch_variable_ST -!: - // First character is 'T', check the second one - - lda VARNAM+1 - cmp #$49 - beq_16 fetch_variable_TI - cmp #$C9 + jsr is_var_TI_string beq_16 fetch_variable_TI_string + jsr is_var_TI + beq_16 fetch_variable_TI + + jsr is_var_ST + beq_16 fetch_variable_ST + // FALLTROUGH fetch_variable_find_addr: diff --git a/src/basic/engine_variables/is_var_ST.s b/src/basic/engine_variables/is_var_ST.s new file mode 100644 index 00000000..a6b991b5 --- /dev/null +++ b/src/basic/engine_variables/is_var_ST.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +is_var_ST: + + // Always start with VARNAM+1, there is a sligtly bigger chance it won't match + + lda VARNAM+1 + cmp #$54 // 'T' + bne !+ + + lda VARNAM+0 + cmp #$53 // 'S' +!: + rts diff --git a/src/basic/engine_variables/is_var_TI.s b/src/basic/engine_variables/is_var_TI.s new file mode 100644 index 00000000..70603af0 --- /dev/null +++ b/src/basic/engine_variables/is_var_TI.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +is_var_TI: + + // Always start with VARNAM+1, there is a sligtly bigger chance it won't match + + lda VARNAM+1 + cmp #$49 // 'I' + bne !+ + + lda VARNAM+0 + cmp #$54 // 'T' +!: + rts diff --git a/src/basic/engine_variables/is_var_TI_string.s b/src/basic/engine_variables/is_var_TI_string.s new file mode 100644 index 00000000..1d8162e2 --- /dev/null +++ b/src/basic/engine_variables/is_var_TI_string.s @@ -0,0 +1,17 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +is_var_TI_string: + + // Always start with VARNAM+1, there is a sligtly bigger chance it won't match + + lda VARNAM+1 + cmp #$C9 // 'I...$' + bne !+ + + lda VARNAM+0 + cmp #$54 // 'T' +!: + rts From b48d576698c78d206cadc31408163aa458f120ac Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 11:56:07 +0200 Subject: [PATCH 067/130] line search optimized --- .../{find_line.s => find_line_38K_60K.s} | 16 +--- src/basic/engine_editor/find_line_46K_50K.s | 93 +++++++++++++++++++ ...=> peek_line_pointer_null_check_38K_60K.s} | 25 ++--- .../peek_line_pointer_null_check_46K_50K.s | 46 +++++++++ 4 files changed, 157 insertions(+), 23 deletions(-) rename src/basic/engine_editor/{find_line.s => find_line_38K_60K.s} (77%) create mode 100644 src/basic/engine_editor/find_line_46K_50K.s rename src/basic/{peek_line_pointer_null_check.s => peek_line_pointer_null_check_38K_60K.s} (66%) create mode 100644 src/basic/peek_line_pointer_null_check_46K_50K.s diff --git a/src/basic/engine_editor/find_line.s b/src/basic/engine_editor/find_line_38K_60K.s similarity index 77% rename from src/basic/engine_editor/find_line.s rename to src/basic/engine_editor/find_line_38K_60K.s index b99f86a2..8a52c25c 100644 --- a/src/basic/engine_editor/find_line.s +++ b/src/basic/engine_editor/find_line_38K_60K.s @@ -6,6 +6,8 @@ // Find the BASIC line with number in LINNUM +#if CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K + find_line_from_start: // Get pointer to start of BASIC text @@ -24,13 +26,9 @@ find_line_from_current: // Fetch the high byte of line number and compare ldy #$03 - // XXX consider optimized 46K/50K version - #if CONFIG_MEMORY_MODEL_60K ldx # Date: Sun, 19 Jul 2020 12:13:58 +0200 Subject: [PATCH 068/130] more line search code optimizations --- src/basic/engine_editor/find_line_46K_50K.s | 43 ++++++++----------- .../peek_line_pointer_null_check_46K_50K.s | 10 ++++- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/basic/engine_editor/find_line_46K_50K.s b/src/basic/engine_editor/find_line_46K_50K.s index cbcce444..235129d3 100644 --- a/src/basic/engine_editor/find_line_46K_50K.s +++ b/src/basic/engine_editor/find_line_46K_50K.s @@ -25,8 +25,8 @@ find_line_from_current: // Check if line is not empty - jsr peek_line_pointer_null_check - bcc find_line_fail + jsr find_line_null_ptr_check // we can't use 'peek_line_pointer_null_check', it maps out/in the BASIC ROM + beq_16 remap_BASIC_sec_rts // search failed if there is no program // Fetch the high byte of line number and compare @@ -35,36 +35,25 @@ find_line_from_current: cmp LINNUM+1 beq !+ - bcs find_line_fail // branch if line number too high + bcs_16 remap_BASIC_sec_rts // search failed if line number too high bne find_line_next !: - // Fetch the low byte of line number and compare dey lda (OLDTXT),y cmp LINNUM+0 - beq find_line_success - bcs find_line_fail // branch if line number too high + beq_16 remap_BASIC_clc_rts + bcs_16 remap_BASIC_sec_rts // search failed if line number too high bne find_line_next -find_line_success: - - // Restore default memory mapping and quit - - lda #$27 - sta CPU_R6510 - - clc - rts - find_line_next: // Advance to the next line - jsr peek_line_pointer_null_check - bcc find_line_fail // branch in no more lines exist + jsr find_line_null_ptr_check // we can't use 'peek_line_pointer_null_check', it maps out/in the BASIC ROM + beq_16 remap_BASIC_sec_rts // search failed if no more line exists ldy #$00 lda (OLDTXT),y @@ -79,15 +68,19 @@ find_line_next: jmp_8 find_line_from_current -find_line_fail: +find_line_null_ptr_check: - // Restore default memory mapping and quit + // Check the pointer - lda #$27 - sta CPU_R6510 - - - sec + ldy #$01 // for non-NULL pointer, high byte is almost certainly not NULL + lda (OLDTXT),y + bne !+ + + dey + lda (OLDTXT),y + bne !+ +!: rts + #endif diff --git a/src/basic/peek_line_pointer_null_check_46K_50K.s b/src/basic/peek_line_pointer_null_check_46K_50K.s index c837cfe9..da4856be 100644 --- a/src/basic/peek_line_pointer_null_check_46K_50K.s +++ b/src/basic/peek_line_pointer_null_check_46K_50K.s @@ -21,14 +21,18 @@ peek_line_pointer_null_check: ldy #$01 // for non-NULL pointer, high byte is almost certainly not NULL lda (OLDTXT),y - bne !+ + bne !+ // branch if pointer not NULL dey lda (OLDTXT),y - bne !+ + bne !+ // branch if pointer not NULL // Pointer is NULL + // FALLTROUGH + +remap_BASIC_clc_rts: + lda #$27 sta CPU_R6510 @@ -37,6 +41,8 @@ peek_line_pointer_null_check: !: // Pointer not NULL +remap_BASIC_sec_rts: + lda #$27 sta CPU_R6510 From 46ee7e476e34385f1b579857b499b636800e3429 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 12:34:41 +0200 Subject: [PATCH 069/130] some more size/speed optimizations --- src/basic/engine_editor/find_line_38K_60K.s | 9 +++--- src/basic/engine_editor/find_line_46K_50K.s | 30 ++++++++++++++----- .../engine_runtime/execute_line_statements.s | 5 ++-- .../is_line_pointer_null_38K_60K.s} | 14 ++------- .../is_line_pointer_null_46K_50K.s} | 25 ++++------------ 5 files changed, 36 insertions(+), 47 deletions(-) rename src/basic/{peek_line_pointer_null_check_38K_60K.s => engine_runtime/is_line_pointer_null_38K_60K.s} (74%) rename src/basic/{peek_line_pointer_null_check_46K_50K.s => engine_runtime/is_line_pointer_null_46K_50K.s} (62%) diff --git a/src/basic/engine_editor/find_line_38K_60K.s b/src/basic/engine_editor/find_line_38K_60K.s index 8a52c25c..309975da 100644 --- a/src/basic/engine_editor/find_line_38K_60K.s +++ b/src/basic/engine_editor/find_line_38K_60K.s @@ -19,9 +19,8 @@ find_line_from_current: // Check if line is not empty - jsr peek_line_pointer_null_check - bcc find_line_fail - + jsr is_line_pointer_null + beq find_line_fail // Fetch the high byte of line number and compare ldy #$03 @@ -62,8 +61,8 @@ find_line_next: // Advance to the next line - jsr peek_line_pointer_null_check - bcc find_line_fail // branch in no more lines exist + jsr is_line_pointer_null + beq find_line_fail // branch in no more lines exist ldy #$00 diff --git a/src/basic/engine_editor/find_line_46K_50K.s b/src/basic/engine_editor/find_line_46K_50K.s index 235129d3..da797733 100644 --- a/src/basic/engine_editor/find_line_46K_50K.s +++ b/src/basic/engine_editor/find_line_46K_50K.s @@ -25,8 +25,8 @@ find_line_from_current: // Check if line is not empty - jsr find_line_null_ptr_check // we can't use 'peek_line_pointer_null_check', it maps out/in the BASIC ROM - beq_16 remap_BASIC_sec_rts // search failed if there is no program + jsr find_line_null_ptr_check // we can't use 'is_line_pointer_null', it maps out/in the BASIC ROM + beq remap_BASIC_sec_rts // search failed if there is no program // Fetch the high byte of line number and compare @@ -35,7 +35,7 @@ find_line_from_current: cmp LINNUM+1 beq !+ - bcs_16 remap_BASIC_sec_rts // search failed if line number too high + bcs remap_BASIC_sec_rts // search failed if line number too high bne find_line_next !: // Fetch the low byte of line number and compare @@ -44,16 +44,16 @@ find_line_from_current: lda (OLDTXT),y cmp LINNUM+0 - beq_16 remap_BASIC_clc_rts - bcs_16 remap_BASIC_sec_rts // search failed if line number too high + beq remap_BASIC_clc_rts + bcs remap_BASIC_sec_rts // search failed if line number too high bne find_line_next find_line_next: // Advance to the next line - jsr find_line_null_ptr_check // we can't use 'peek_line_pointer_null_check', it maps out/in the BASIC ROM - beq_16 remap_BASIC_sec_rts // search failed if no more line exists + jsr find_line_null_ptr_check // we can't use 'is_line_pointer_null', it maps out/in the BASIC ROM + beq remap_BASIC_sec_rts // search failed if no more line exists ldy #$00 lda (OLDTXT),y @@ -83,4 +83,20 @@ find_line_null_ptr_check: rts +remap_BASIC_clc_rts: + + lda #$27 + sta CPU_R6510 + + clc + rts + +remap_BASIC_sec_rts: + + lda #$27 + sta CPU_R6510 + + sec + rts + #endif diff --git a/src/basic/engine_runtime/execute_line_statements.s b/src/basic/engine_runtime/execute_line_statements.s index 40ad1821..3ac95047 100644 --- a/src/basic/engine_runtime/execute_line_statements.s +++ b/src/basic/engine_runtime/execute_line_statements.s @@ -189,9 +189,8 @@ execute_line: // Check if pointer is null, if so, we are at the end of the program - ldy #0 - jsr peek_line_pointer_null_check - bcc_16 shell_main_loop // branch if end of program reached + jsr is_line_pointer_null + beq_16 shell_main_loop // branch if end of program reached // Skip pointer and line number to get address of first statement diff --git a/src/basic/peek_line_pointer_null_check_38K_60K.s b/src/basic/engine_runtime/is_line_pointer_null_38K_60K.s similarity index 74% rename from src/basic/peek_line_pointer_null_check_38K_60K.s rename to src/basic/engine_runtime/is_line_pointer_null_38K_60K.s index 7f3457f4..5ca5b151 100644 --- a/src/basic/peek_line_pointer_null_check_38K_60K.s +++ b/src/basic/engine_runtime/is_line_pointer_null_38K_60K.s @@ -2,13 +2,12 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE -// Return C=1 if a pointer in BASIC memory space is NULL, else C=0 -// X = ZP pointer to check +// Return pointer in BASIC memory space status in Z flag #if CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K -peek_line_pointer_null_check: +is_line_pointer_null: // Check the pointer @@ -32,16 +31,7 @@ peek_line_pointer_null_check: lda (OLDTXT),y #endif - bne !+ - - // Pointer is NULL - - clc - rts !: - // Pointer not NULL - - sec rts #endif diff --git a/src/basic/peek_line_pointer_null_check_46K_50K.s b/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s similarity index 62% rename from src/basic/peek_line_pointer_null_check_46K_50K.s rename to src/basic/engine_runtime/is_line_pointer_null_46K_50K.s index da4856be..0f743885 100644 --- a/src/basic/peek_line_pointer_null_check_46K_50K.s +++ b/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s @@ -4,13 +4,12 @@ // This has to go $E000 or above - routine below banks out the main BASIC ROM! -// Return C=1 if a pointer in BASIC memory space is NULL, else C=0 -// X = ZP pointer to check +// Return pointer in BASIC memory space status in Z flag #if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K -peek_line_pointer_null_check: +is_line_pointer_null: // Unmap BASIC lower ROM @@ -25,28 +24,14 @@ peek_line_pointer_null_check: dey lda (OLDTXT),y - bne !+ // branch if pointer not NULL - - // Pointer is NULL - - // FALLTROUGH - -remap_BASIC_clc_rts: - - lda #$27 - sta CPU_R6510 - - clc - rts !: - // Pointer not NULL -remap_BASIC_sec_rts: + // Restore memory mapping and quit + php lda #$27 sta CPU_R6510 - - sec + plp rts #endif From b4400344143a2e2475c4c03ee941093585e8c732 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 12:56:51 +0200 Subject: [PATCH 070/130] optimization in variable search --- src/basic/engine_editor/find_line_46K_50K.s | 7 ++-- .../is_line_pointer_null_46K_50K.s | 11 ++---- src/basic/engine_variables/fetch_variable.s | 11 ++++-- .../helper_cmp_varnam_46K_50K.s | 38 +++++++++++++++++++ .../helper_strdesccpy_46K_50K.s | 2 +- 5 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 src/basic/engine_variables/helper_cmp_varnam_46K_50K.s diff --git a/src/basic/engine_editor/find_line_46K_50K.s b/src/basic/engine_editor/find_line_46K_50K.s index da797733..a62d8635 100644 --- a/src/basic/engine_editor/find_line_46K_50K.s +++ b/src/basic/engine_editor/find_line_46K_50K.s @@ -25,7 +25,7 @@ find_line_from_current: // Check if line is not empty - jsr find_line_null_ptr_check // we can't use 'is_line_pointer_null', it maps out/in the BASIC ROM + jsr line_pointer_null_check // we can't use 'is_line_pointer_null', it maps out/in the BASIC ROM beq remap_BASIC_sec_rts // search failed if there is no program // Fetch the high byte of line number and compare @@ -52,7 +52,7 @@ find_line_next: // Advance to the next line - jsr find_line_null_ptr_check // we can't use 'is_line_pointer_null', it maps out/in the BASIC ROM + jsr line_pointer_null_check // we can't use 'is_line_pointer_null', it maps out/in the BASIC ROM beq remap_BASIC_sec_rts // search failed if no more line exists ldy #$00 @@ -68,7 +68,7 @@ find_line_next: jmp_8 find_line_from_current -find_line_null_ptr_check: +line_pointer_null_check: // reused by 'is_line_pointer_null' // Check the pointer @@ -82,7 +82,6 @@ find_line_null_ptr_check: !: rts - remap_BASIC_clc_rts: lda #$27 diff --git a/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s b/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s index 0f743885..8ffc839d 100644 --- a/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s +++ b/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s @@ -16,15 +16,9 @@ is_line_pointer_null: lda #$26 sta CPU_R6510 - // Check the pointer + // Check the pointer - reuse code from other routine - ldy #$01 // for non-NULL pointer, high byte is almost certainly not NULL - lda (OLDTXT),y - bne !+ // branch if pointer not NULL - - dey - lda (OLDTXT),y -!: + jsr line_pointer_null_check // Restore memory mapping and quit @@ -32,6 +26,7 @@ is_line_pointer_null: lda #$27 sta CPU_R6510 plp + rts #endif diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 1c8cc5be..348fc6d2 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -130,13 +130,15 @@ fetch_variable_find_addr_loop: // Compare current variable name with searched one // XXX consider creating optimized version for 46K/50K memory models +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + jsr helper_cmp_varnam +#else + ldy #$00 #if CONFIG_MEMORY_MODEL_60K ldx # Date: Sun, 19 Jul 2020 13:40:21 +0200 Subject: [PATCH 071/130] optimizations in garbage collector --- .../is_line_pointer_null_46K_50K.s | 4 ++ .../helper_cmp_varnam_46K_50K.s | 10 +--- .../helper_gc_fetch_backpointer_46K_50K.s | 32 +++++++++++ .../engine_variables/helper_gc_misc_46K_50K.s | 57 +++++++++++++++++++ .../engine_variables/varstr_garbage_collect.s | 38 ++++--------- 5 files changed, 107 insertions(+), 34 deletions(-) create mode 100644 src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s create mode 100644 src/basic/engine_variables/helper_gc_misc_46K_50K.s diff --git a/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s b/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s index 8ffc839d..c9c81460 100644 --- a/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s +++ b/src/basic/engine_runtime/is_line_pointer_null_46K_50K.s @@ -20,6 +20,10 @@ is_line_pointer_null: jsr line_pointer_null_check + // FALLTROUGH + +remap_BASIC_preserve_P: + // Restore memory mapping and quit php diff --git a/src/basic/engine_variables/helper_cmp_varnam_46K_50K.s b/src/basic/engine_variables/helper_cmp_varnam_46K_50K.s index 0f3ad9e2..91a56e2e 100644 --- a/src/basic/engine_variables/helper_cmp_varnam_46K_50K.s +++ b/src/basic/engine_variables/helper_cmp_varnam_46K_50K.s @@ -2,7 +2,7 @@ // #LAYOUT# * BASIC_0 #TAKE-HIGH // #LAYOUT# * * #IGNORE -// This has to go $E000 or above - routines below banks out the main BASIC ROM! +// This has to go $E000 or above - routine below banks out the main BASIC ROM! #if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K @@ -26,13 +26,7 @@ helper_cmp_varnam: cmp VARNAM+1 !: // Restore default memory mapping - // XXX consider deduplicating with 'is_line_pointer_null' - php - lda #$27 - sta CPU_R6510 - plp - - rts + jmp remap_BASIC_preserve_P #endif diff --git a/src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s b/src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s new file mode 100644 index 00000000..1b72c7cd --- /dev/null +++ b/src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s @@ -0,0 +1,32 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_gc_fetch_backpointer: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Copy the back-pointer to OLDTXT, check if it is NULL + + ldy #$00 + lda (TXTPTR),y + sta OLDTXT+0 + + iny + lda (TXTPTR),y + sta OLDTXT+1 + + ora OLDTXT+0 + + // Restore default memory mapping + + jmp remap_BASIC_preserve_P + +#endif diff --git a/src/basic/engine_variables/helper_gc_misc_46K_50K.s b/src/basic/engine_variables/helper_gc_misc_46K_50K.s new file mode 100644 index 00000000..68c10bf1 --- /dev/null +++ b/src/basic/engine_variables/helper_gc_misc_46K_50K.s @@ -0,0 +1,57 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routines below bank out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_gc_set_memmove_src: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Set memmove__src + + lda (OLDTXT),y + sta memmove__src+0 + iny + lda (OLDTXT),y + sta memmove__src+1 + + // Restore default memory mapping + + jmp_8 helper_gc_misc_end + +helper_gc_increase_oldtxt: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Increase OLDTXT accordingly + + lda (OLDTXT),y + clc + adc INDEX+0 + sta (OLDTXT),y + iny + lda (OLDTXT),y + adc INDEX+1 + sta (OLDTXT),y + + // FALLTROUGH + +helper_gc_misc_end: + + // Restore default memory mapping + + lda #$27 + sta CPU_R6510 + + rts + +#endif diff --git a/src/basic/engine_variables/varstr_garbage_collect.s b/src/basic/engine_variables/varstr_garbage_collect.s index c7321971..ba7e192e 100644 --- a/src/basic/engine_variables/varstr_garbage_collect.s +++ b/src/basic/engine_variables/varstr_garbage_collect.s @@ -87,6 +87,12 @@ varstr_garbage_collect_check_bptr: // Copy the back-pointer to OLDTXT, check if it is NULL +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + jsr helper_gc_fetch_backpointer + +#else + ldy #$00 #if CONFIG_MEMORY_MODEL_60K @@ -96,13 +102,6 @@ varstr_garbage_collect_check_bptr: iny jsr peek_under_roms sta OLDTXT+1 -#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX consider optimized version without multiple JSRs - jsr peek_under_roms_via_TXTPTR - sta OLDTXT+0 - iny - jsr peek_under_roms_via_TXTPTR - sta OLDTXT+1 #else // CONFIG_MEMORY_MODEL_38K lda (TXTPTR),y sta OLDTXT+0 @@ -112,6 +111,9 @@ varstr_garbage_collect_check_bptr: #endif ora OLDTXT+0 + +#endif + beq_16 varstr_garbage_collect_unused // The back-pointer is not NULL - string is used @@ -159,12 +161,7 @@ varstr_garbage_collect_check_bptr: jsr peek_under_roms sta memmove__src+1 #elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX consider optimized version without multiple JSRs - jsr peek_under_roms_via_OLDTXT - sta memmove__src+0 - iny - jsr peek_under_roms_via_OLDTXT - sta memmove__src+1 + jsr helper_gc_set_memmove_src #else // CONFIG_MEMORY_MODEL_38K lda (OLDTXT),y sta memmove__src+0 @@ -227,19 +224,8 @@ varstr_garbage_collect_check_bptr: jsr poke_under_roms #elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX consider optimized version without multiple JSRs - - jsr peek_under_roms_via_OLDTXT - clc - adc INDEX+0 - sta (OLDTXT),y - iny - - php - jsr peek_under_roms_via_OLDTXT - plp - adc INDEX+1 - sta (OLDTXT),y + + jsr helper_gc_increase_oldtxt #else // CONFIG_MEMORY_MODEL_38K From a59f4647ad4aa75061c8e8302268e67c064da9e8 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 14:07:31 +0200 Subject: [PATCH 072/130] fixed another bug in string release code --- bin/basic_generic.rom | Bin 8192 -> 8192 bytes bin/basic_ultimate64.rom | Bin 8192 -> 8192 bytes bin/kernal_generic.rom | Bin 8192 -> 8192 bytes bin/kernal_ultimate64.rom | Bin 8192 -> 8192 bytes bin/mega65.rom | Bin 131072 -> 131072 bytes bin/mega65_pxlfont.rom | Bin 131072 -> 131072 bytes src/,,config_generic.s | 4 ++-- src/,,config_ultimate64.s | 4 ++-- src/basic/engine_variables/tmpstr_free_all.s | 10 +++++++++- 9 files changed, 13 insertions(+), 5 deletions(-) diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 217ffa26cdc08aed101d50c37eed953a3e2219ca..d0f19bd4eb4f392d95d442d5d69876988495327e 100644 GIT binary patch delta 4274 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 RVFY$E+fR>y4cQ4!;osQ-D-r+z diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom index f7d37a5e9ef6bb479f40557dfaeb9a2bde05ff39..36ce32cb0bbbdd1205682c3ad9a9e6c98794228c 100644 GIT binary patch delta 4186 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 vS8Z!mgo<{o7^Q}WmTSR1cB-o?A(6?)I|ow diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 4353929f471de78c1ec40b452b056ec5af4b1f02..29d756fa22dd2a51ec3af47bd833128e12388e22 100644 GIT binary patch delta 4013 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 delta 4033 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 delta 3986 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 Date: Sun, 19 Jul 2020 14:51:29 +0200 Subject: [PATCH 073/130] small rework towards TI$ assignment and arrays support --- src/basic/engine_variables/assign_variable.s | 17 +++- .../assign_variable_TI_string.s | 10 ++ src/basic/engine_variables/fetch_variable.s | 82 +-------------- .../engine_variables/fetch_variable_name.s | 99 +++++++++++++++++++ 4 files changed, 128 insertions(+), 80 deletions(-) create mode 100644 src/basic/engine_variables/assign_variable_TI_string.s create mode 100644 src/basic/engine_variables/fetch_variable_name.s diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index d9e24960..849cf50b 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -7,7 +7,7 @@ assign_variable: // Fetch variable name, should be followed by assign operator - jsr fetch_variable + jsr fetch_variable_name #if HAS_OPCODES_65CE02 @@ -26,6 +26,21 @@ assign_variable: #endif + // Check for special variables + + jsr is_var_TI_string + beq_16 assign_variable_TI_string + + jsr is_var_TI + beq_16 do_SYNTAX_error + + jsr is_var_ST + beq_16 do_SYNTAX_error + + // Retrieve the variable address + + jsr fetch_variable_find_addr + // Determine variable type and push it to the stack lda #$00 diff --git a/src/basic/engine_variables/assign_variable_TI_string.s b/src/basic/engine_variables/assign_variable_TI_string.s new file mode 100644 index 00000000..46a2d09f --- /dev/null +++ b/src/basic/engine_variables/assign_variable_TI_string.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +assign_variable_TI_string: + + // XXX implement + + jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 348fc6d2..1c99b4f6 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -9,89 +9,13 @@ fetch_variable: - // Set default second character and variable type + // Start by fetching variable name - lda #$00 - sta VARNAM+1 - - // Fetch the first character of variable name - - jsr fetch_character_skip_spaces - jsr is_AZ + jsr fetch_variable_name bcc !+ - -#if !HAS_OPCODES_65CE02 - jsr unconsume_character -#else - dew TXTPTR -#endif - - sec rts !: - sta VARNAM+0 - - // Fetch the (optional) second character - - jsr fetch_character - jsr is_09_AZ - bcs fetch_variable_check_type - - sta VARNAM+1 - - // Fetch the remaining variable characters - ignore them -!: - jsr fetch_character - jsr is_09_AZ - bcc !- - - // FALLTROUGH - -fetch_variable_check_type: - - // Encode variable type within name, as documented in: - // - https://sites.google.com/site/h2obsession/CBM/basic/variable-format - - cmp #$24 // '$' - beq fetch_variable_type_string - cmp #$25 // '%' - beq fetch_variable_type_integer - - // FALLTORUGH - -fetch_variable_type_float: - -#if !HAS_OPCODES_65CE02 - jsr unconsume_character -#else - dew TXTPTR -#endif - - jmp_8 fetch_variable_special - -fetch_variable_type_integer: - - lda VARNAM+0 - ora #$80 - sta VARNAM+0 - - lda #$00 - skip_2_bytes_trash_nvz - - // FALLTROUGH - -fetch_variable_type_string: - - lda #$80 - sta VALTYP - - lda VARNAM+1 - ora #$80 - sta VARNAM+1 - - // FALLTROUGH - -fetch_variable_special: + // Handle special variables - TI$, TI, ST jsr is_var_TI_string beq_16 fetch_variable_TI_string diff --git a/src/basic/engine_variables/fetch_variable_name.s b/src/basic/engine_variables/fetch_variable_name.s new file mode 100644 index 00000000..d4356d79 --- /dev/null +++ b/src/basic/engine_variables/fetch_variable_name.s @@ -0,0 +1,99 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Carry set = failure, not recognized variable name +// + + +fetch_variable_name: + + // Set default second character and variable type + + lda #$00 + sta VARNAM+1 + + // Fetch the first character of variable name + + jsr fetch_character_skip_spaces + jsr is_AZ + bcc !+ + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + + sec + rts +!: + sta VARNAM+0 + + // Fetch the (optional) second character + + jsr fetch_character + jsr is_09_AZ + bcs fetch_variable_check_type + + sta VARNAM+1 + + // Fetch the remaining variable characters - ignore them +!: + jsr fetch_character + jsr is_09_AZ + bcc !- + + // FALLTROUGH + +fetch_variable_check_type: + + // Encode variable type within name, as documented in: + // - https://sites.google.com/site/h2obsession/CBM/basic/variable-format + + cmp #$24 // '$' + beq fetch_variable_type_string + cmp #$25 // '%' + beq fetch_variable_type_integer + + // FALLTORUGH + +fetch_variable_type_float: + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + + jmp_8 fetch_variable_name_check_array + +fetch_variable_type_integer: + + lda VARNAM+0 + ora #$80 + sta VARNAM+0 + + lda #$00 + skip_2_bytes_trash_nvz + + // FALLTROUGH + +fetch_variable_type_string: + + lda #$80 + sta VALTYP + + lda VARNAM+1 + ora #$80 + sta VARNAM+1 + + // FALLTROUGH + +fetch_variable_name_check_array: + + // XXX add check for array + + clc + rts From 8826394e8076fd565d474cb183eab20d11fc225d Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 15:33:42 +0200 Subject: [PATCH 074/130] TI$ variable can now be assigned --- doc/Extended-BASIC-TODO.md | 1 + src/basic/basic_commands/cmd_print.s | 2 + src/basic/engine_runtime/do_error.s | 3 +- .../assign_variable_TI_string.s | 78 ++++++++++++++++++- 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/doc/Extended-BASIC-TODO.md b/doc/Extended-BASIC-TODO.md index 78194e9b..d262dbe9 100644 --- a/doc/Extended-BASIC-TODO.md +++ b/doc/Extended-BASIC-TODO.md @@ -58,6 +58,7 @@ Ideas for the future, most of them suitable for Mega65 or other power machines o * `RUN` should be able to run program from device, as in BASIC V10 * `PAGE` and `DELAY` commands from Simons BASIC, or something similar * `DUMP` command from Simons BASIC, or something similar +* it should be possbile to assign to `TI` special variable * function to insert a substring starting from given position * function to generate string of n duplicated characters * function to retrieve fractional part of a number diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index c4c260c2..2dad7ba7 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -42,6 +42,8 @@ cmd_print_string: // Print a string value + // XXX add optimized 46K/50K version + ldy #$00 !: cpy __FAC1 + 0 diff --git a/src/basic/engine_runtime/do_error.s b/src/basic/engine_runtime/do_error.s index c8d51e0a..fc2b6573 100644 --- a/src/basic/engine_runtime/do_error.s +++ b/src/basic/engine_runtime/do_error.s @@ -182,9 +182,10 @@ do_basic_error: // error code in .X jsr map_NORMAL #endif - // "?" + // Clear all temporary variables, print "?" phx_trash_a + jsr tmpstr_free_all ldx #IDX__STR_RET_QM jsr print_packed_misc_str plx_trash_a diff --git a/src/basic/engine_variables/assign_variable_TI_string.s b/src/basic/engine_variables/assign_variable_TI_string.s index 46a2d09f..c18cbf1a 100644 --- a/src/basic/engine_variables/assign_variable_TI_string.s +++ b/src/basic/engine_variables/assign_variable_TI_string.s @@ -5,6 +5,80 @@ assign_variable_TI_string: - // XXX implement + // Evaluate the expression, check if the result is suitable - jmp do_NOT_IMPLEMENTED_error + jsr FRMEVL + + lda VALTYP + bpl_16 do_TYPE_MISMATCH_error // branch if not string + + lda __FAC1+0 + cmp #$06 + bne_16 do_ILLEGAL_QUANTITY_error // we need exactly 6-character string + + // Initialize new time counter, process all the digits + + ldy #$00 + + sty INDEX+0 + sty INDEX+1 + sty INDEX+2 + + // FALLTROUGH + + // XXX provide optimized version for memory models 46K/50K + +assign_variable_TI_string_loop: + + // First fetch the digit + +#if CONFIG_MEMORY_MODEL_60K + ldx #<(__FAC1 + 1) + jsr peek_under_roms +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + jsr peek_under_roms_via_FAC1_PLUS_1 +#else // CONFIG_MEMORY_MODEL_38K + lda (__FAC1 + 1), y +#endif + + jsr convert_PETSCII_to_digit + bcs_16 do_ILLEGAL_QUANTITY_error + + tax // move decoded digit to .X + + // Strangely, original implementation seems to be very permissive, + // it accepts any digit at any position; for compatibility + // we should better follow this convention + +assign_variable_TI_string_loop_digit: + + cpx #$00 + beq assign_variable_TI_string_loop_next + + clc + lda table_TI_lo, y + adc INDEX+0 + sta INDEX+0 + lda table_TI_mid, y + adc INDEX+1 + sta INDEX+1 + lda table_TI_hi, y + adc INDEX+2 + sta INDEX+2 + + dex + bpl assign_variable_TI_string_loop_digit // branch always + +assign_variable_TI_string_loop_next: + + iny + cpy #$06 + bne assign_variable_TI_string_loop + + // Set the resulting value + + ldy INDEX+0 + ldx INDEX+1 + lda INDEX+2 + + jmp JSETTIM From 12abb60d2235f891d8ddeb75c49b5bff9941cac0 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 16:15:50 +0200 Subject: [PATCH 075/130] some more code optimizations --- src/basic/basic_commands/cmd_print.s | 19 +++++++------ .../helper_print_string_46K_50K.s | 27 +++++++++++++++++++ .../helper_frmevl_strdesccpy_46K_50K.s | 4 +++ .../assign_variable_TI_string.s | 2 -- .../engine_variables/helper_gc_misc_46K_50K.s | 5 +--- .../memory/under_rom_peek_fetch_46k_50k.s | 15 +++++------ 6 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 src/basic/basic_commands/helper_print_string_46K_50K.s diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index 2dad7ba7..13faafdd 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -42,7 +42,12 @@ cmd_print_string: // Print a string value - // XXX add optimized 46K/50K version +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + jsr helper_print_string + jmp_8 cmd_print_next_arg + +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K ldy #$00 !: @@ -50,23 +55,17 @@ cmd_print_string: beq cmd_print_next_arg #if CONFIG_MEMORY_MODEL_60K - ldx #<(__FAC1 + 1) jsr peek_under_roms - -#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - - jsr peek_under_roms_via_FAC1_PLUS_1 - #else // CONFIG_MEMORY_MODEL_38K - lda (__FAC1 + 1), y - #endif jsr JCHROUT iny - jmp !- + bpl !- + +#endif cmd_print_float: diff --git a/src/basic/basic_commands/helper_print_string_46K_50K.s b/src/basic/basic_commands/helper_print_string_46K_50K.s new file mode 100644 index 00000000..4902509e --- /dev/null +++ b/src/basic/basic_commands/helper_print_string_46K_50K.s @@ -0,0 +1,27 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_print_string: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Print the string + + ldy #$00 +!: + cpy __FAC1 + 0 + beq_16 remap_BASIC // branch if end of the string + lda (__FAC1 + 1), y + jsr JCHROUT + iny + bpl !- + +#endif diff --git a/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s b/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s index bf6249a6..249dbb7d 100644 --- a/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s +++ b/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s @@ -30,6 +30,10 @@ helper_frmevl_strdesccpy: lda (VARPNT),y sta __FAC1+2 + // FALLTROUGH + +remap_BASIC: + // Restore default memory mapping lda #$27 diff --git a/src/basic/engine_variables/assign_variable_TI_string.s b/src/basic/engine_variables/assign_variable_TI_string.s index c18cbf1a..55c5f644 100644 --- a/src/basic/engine_variables/assign_variable_TI_string.s +++ b/src/basic/engine_variables/assign_variable_TI_string.s @@ -26,8 +26,6 @@ assign_variable_TI_string: // FALLTROUGH - // XXX provide optimized version for memory models 46K/50K - assign_variable_TI_string_loop: // First fetch the digit diff --git a/src/basic/engine_variables/helper_gc_misc_46K_50K.s b/src/basic/engine_variables/helper_gc_misc_46K_50K.s index 68c10bf1..503df2aa 100644 --- a/src/basic/engine_variables/helper_gc_misc_46K_50K.s +++ b/src/basic/engine_variables/helper_gc_misc_46K_50K.s @@ -49,9 +49,6 @@ helper_gc_misc_end: // Restore default memory mapping - lda #$27 - sta CPU_R6510 - - rts + jmp remap_BASIC #endif diff --git a/src/basic/memory/under_rom_peek_fetch_46k_50k.s b/src/basic/memory/under_rom_peek_fetch_46k_50k.s index 31368d5e..f4b652aa 100644 --- a/src/basic/memory/under_rom_peek_fetch_46k_50k.s +++ b/src/basic/memory/under_rom_peek_fetch_46k_50k.s @@ -21,7 +21,7 @@ peek_under_roms_via_TXTPTR: // FALLTROUGH -peek_under_roms_finalize: +remap_BASIC_preserve_A: // Restore memory mapping @@ -44,7 +44,7 @@ peek_under_roms_via_OLDTXT: // Retrieve value from under ROMs lda (OLDTXT), y - jmp_8 peek_under_roms_finalize + jmp_8 remap_BASIC_preserve_A peek_under_roms_via_VARPNT: @@ -56,7 +56,7 @@ peek_under_roms_via_VARPNT: // Retrieve value from under ROMs lda (VARPNT), y - jmp_8 peek_under_roms_finalize + jmp_8 remap_BASIC_preserve_A peek_under_roms_via_FAC1_PLUS_1: @@ -67,9 +67,8 @@ peek_under_roms_via_FAC1_PLUS_1: // Retrieve value from under ROMs - lda (__FAC1 + 1), y - jmp_8 peek_under_roms_finalize - + lda (__FAC1+1), y + jmp_8 remap_BASIC_preserve_A #if ROM_LAYOUT_M65 @@ -90,7 +89,7 @@ fetch_character: // Restore memory mapping - bra peek_under_roms_finalize + jmp_8 remap_BASIC_preserve_A fetch_character_skip_spaces: @@ -114,7 +113,7 @@ fetch_character_skip_spaces: // Restore memory mapping - bra peek_under_roms_finalize + jmp_8 remap_BASIC_preserve_A #endif From ffbb58bcbc59de8edf4730f3635755e745a0953a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 16:24:45 +0200 Subject: [PATCH 076/130] changed TIME variable format to default one --- src/basic/basic_commands_CC/helper_ask_if_sure.s | 4 ++-- src/basic/engine_variables/assign_variable_TI_string.s | 4 ++-- src/basic/engine_variables/fetch_variable_TI_string.s | 4 ++-- src/basic/math/rnd_seed_init.s | 2 +- src/kernal/time/udtim.s | 10 +++++----- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/basic/basic_commands_CC/helper_ask_if_sure.s b/src/basic/basic_commands_CC/helper_ask_if_sure.s index 92d36947..2d554b7c 100644 --- a/src/basic/basic_commands_CC/helper_ask_if_sure.s +++ b/src/basic/basic_commands_CC/helper_ask_if_sure.s @@ -60,10 +60,10 @@ helper_ask_if_sure: jsr JCHROUT clc - lda TIME+0 + lda TIME+2 adc #$0C !: - cmp TIME+0 + cmp TIME+2 bne !- // FALLTROUGH diff --git a/src/basic/engine_variables/assign_variable_TI_string.s b/src/basic/engine_variables/assign_variable_TI_string.s index 55c5f644..229b85cc 100644 --- a/src/basic/engine_variables/assign_variable_TI_string.s +++ b/src/basic/engine_variables/assign_variable_TI_string.s @@ -75,8 +75,8 @@ assign_variable_TI_string_loop_next: // Set the resulting value - ldy INDEX+0 + ldy INDEX+2 ldx INDEX+1 - lda INDEX+2 + lda INDEX+0 jmp JSETTIM diff --git a/src/basic/engine_variables/fetch_variable_TI_string.s b/src/basic/engine_variables/fetch_variable_TI_string.s index 753477b9..5e70d6c1 100644 --- a/src/basic/engine_variables/fetch_variable_TI_string.s +++ b/src/basic/engine_variables/fetch_variable_TI_string.s @@ -17,9 +17,9 @@ fetch_variable_TI_string: jsr JRDTIM - sty INDEX+0 + sty INDEX+2 stx INDEX+1 - sta INDEX+2 + sta INDEX+0 // Now calculate the digits, starting from the most important one diff --git a/src/basic/math/rnd_seed_init.s b/src/basic/math/rnd_seed_init.s index 56f0a13c..a2510214 100644 --- a/src/basic/math/rnd_seed_init.s +++ b/src/basic/math/rnd_seed_init.s @@ -21,7 +21,7 @@ rnd_seed_init: eor CIA1_TIMAHI sta RNDX+4 - lda TIME+0 // byte from jiffy counter might be useful too + lda TIME+2 // byte from jiffy counter might be useful too eor SID_RANDOM // not sure if SID set correctly, but it will not hurt #if CONFIG_MB_MEGA_65 eor VIC_XPOS // not sure if VIC-IV visible, but it will not hurt diff --git a/src/kernal/time/udtim.s b/src/kernal/time/udtim.s index 9c75406f..b2e2dcc8 100644 --- a/src/kernal/time/udtim.s +++ b/src/kernal/time/udtim.s @@ -18,14 +18,14 @@ UDTIM: // after this time we have to reset the clock. #if !HAS_OPCODES_65CE02 - inc TIME+0 + inc TIME+2 bne udtim_time_done // done with clock inc TIME+1 #else - inw TIME+0 + inw TIME+2 #endif bne udtim_clock_rollover - inc TIME+2 + inc TIME+0 // FALLTROUGH @@ -39,10 +39,10 @@ udtim_clock_rollover: lda TIME+1 cmp #$1A bne udtim_time_done // done with clock - lda TIME+2 + lda TIME+0 cmp #$4F bne udtim_time_done // done with clock lda #$00 - sta TIME+2 + sta TIME+0 sta TIME+1 beq udtim_time_done // done with clock - will always jump From 24115bc3abdf6a9bb959f278e9741bc9ead354d2 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 17:40:06 +0200 Subject: [PATCH 077/130] fixed TI$ values and UDTIM rollover --- src/basic/assets/table_ti_hi.s | 12 +++++----- src/basic/assets/table_ti_lo.s | 12 +++++----- src/basic/assets/table_ti_mid.s | 12 +++++----- src/kernal/time/settim.s | 2 +- src/kernal/time/udtim.s | 42 +++++++++++++++++---------------- 5 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/basic/assets/table_ti_hi.s b/src/basic/assets/table_ti_hi.s index 44e3b388..becbe187 100644 --- a/src/basic/assets/table_ti_hi.s +++ b/src/basic/assets/table_ti_hi.s @@ -8,9 +8,9 @@ table_TI_hi: - .byte $36 // 10 hours = 3600000 ticks - .byte $05 // 1 hour = 360000 ticks - .byte $00 // 10 minutes = 30000 ticks - .byte $00 // 1 minute = 3000 ticks - .byte $00 // 10 seconds = 500 ticks - .byte $00 // 1 second = 50 ticks + .byte $20 // 10 hours = 2169000 ticks + .byte $03 // 1 hour = 216000 ticks + .byte $00 // 10 minutes = 36000 ticks + .byte $00 // 1 minute = 3600 ticks + .byte $00 // 10 seconds = 600 ticks + .byte $00 // 1 second = 60 ticks diff --git a/src/basic/assets/table_ti_lo.s b/src/basic/assets/table_ti_lo.s index 5f09b6ac..5b3368cb 100644 --- a/src/basic/assets/table_ti_lo.s +++ b/src/basic/assets/table_ti_lo.s @@ -8,9 +8,9 @@ table_TI_lo: - .byte $80 // 10 hours = 3600000 ticks - .byte $40 // 1 hour = 360000 ticks - .byte $30 // 10 minutes = 30000 ticks - .byte $B8 // 1 minute = 3000 ticks - .byte $F4 // 10 seconds = 500 ticks - .byte $32 // 1 second = 50 ticks + .byte $80 // 10 hours = 2169000 ticks + .byte $C0 // 1 hour = 216000 ticks + .byte $A0 // 10 minutes = 36000 ticks + .byte $10 // 1 minute = 3600 ticks + .byte $58 // 10 seconds = 600 ticks + .byte $3C // 1 second = 60 ticks diff --git a/src/basic/assets/table_ti_mid.s b/src/basic/assets/table_ti_mid.s index ccecd6ff..5515a733 100644 --- a/src/basic/assets/table_ti_mid.s +++ b/src/basic/assets/table_ti_mid.s @@ -8,9 +8,9 @@ table_TI_mid: - .byte $EE // 10 hours = 3600000 ticks - .byte $7E // 1 hour = 360000 ticks - .byte $75 // 10 minutes = 30000 ticks - .byte $0B // 1 minute = 3000 ticks - .byte $01 // 10 seconds = 500 ticks - .byte $00 // 1 second = 50 ticks + .byte $F5 // 10 hours = 2169000 ticks + .byte $4B // 1 hour = 216000 ticks + .byte $8C // 10 minutes = 36000 ticks + .byte $0E // 1 minute = 3600 ticks + .byte $02 // 10 seconds = 600 ticks + .byte $00 // 1 second = 60 ticks diff --git a/src/kernal/time/settim.s b/src/kernal/time/settim.s index 7c07eb5c..c42b8627 100644 --- a/src/kernal/time/settim.s +++ b/src/kernal/time/settim.s @@ -21,7 +21,7 @@ SETTIM: sty TIME + 0 stx TIME + 1 sta TIME + 2 - +.break // Enable interrupts. More elegant solution would be pha + sei + ... + pla, // but (checked by running a test program) original ROM routine always // leaves IRQs enabled. diff --git a/src/kernal/time/udtim.s b/src/kernal/time/udtim.s index b2e2dcc8..1e52cae2 100644 --- a/src/kernal/time/udtim.s +++ b/src/kernal/time/udtim.s @@ -17,32 +17,34 @@ UDTIM: // (24 hours * 60 minutes * 60 seconds * 60 jiffies), // after this time we have to reset the clock. -#if !HAS_OPCODES_65CE02 inc TIME+2 - bne udtim_time_done // done with clock + bne udtim_rollover_check inc TIME+1 -#else - inw TIME+2 -#endif - bne udtim_clock_rollover + bne udtim_rollover_check inc TIME+0 // FALLTROUGH +udtim_rollover_check: + + lda TIME+0 + cmp #$4F + bcc udtim_time_done + lda TIME+1 + cmp #$1A + bcc udtim_time_done + + // FALLTROUGH + +udtim_clock_reset: + + lda #$00 + sta TIME+0 + sta TIME+1 + sta TIME+2 + + // FALLTROUGH + udtim_time_done: jmp udtim_keyboard - -udtim_clock_rollover: - - // At this point TIME+0 contains 0 - lda TIME+1 - cmp #$1A - bne udtim_time_done // done with clock - lda TIME+0 - cmp #$4F - bne udtim_time_done // done with clock - lda #$00 - sta TIME+0 - sta TIME+1 - beq udtim_time_done // done with clock - will always jump From 4c648a789131f6df9dbde7105a1193fbf927876f Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 17:45:08 +0200 Subject: [PATCH 078/130] saved 3 bytes in Kernal --- src/kernal/keyboard/udtim_keyboard.s | 54 ---------------------------- src/kernal/time/settim.s | 2 +- src/kernal/time/udtim.s | 53 ++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 59 deletions(-) delete mode 100644 src/kernal/keyboard/udtim_keyboard.s diff --git a/src/kernal/keyboard/udtim_keyboard.s b/src/kernal/keyboard/udtim_keyboard.s deleted file mode 100644 index d1c8c74e..00000000 --- a/src/kernal/keyboard/udtim_keyboard.s +++ /dev/null @@ -1,54 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 * #IGNORE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Keyboard part of the UDTIM routine, has to preserve .Y -// - - -udtim_keyboard: - - // According to [CM64], page 27, the action we have to perform is to copy - // the last row of keyboard to RAM, so that various routines can detect the STOP - // key press. But something as simple as this would have created warm restart - // with M+N+SPACE+RESTORE due to ghosting - so the original ROM has to provide - // some protection here. I do not know what the mechanism there exactly does, - // but I hope the mechanism below will be compatible enough. - - lda #$80 - sta CIA1_PRA // select all the rows except the last one -#if CONFIG_KEYBOARD_C128 - ldx #$00 - stx VIC_XSCAN // connect all the extra C128 keys -#endif -#if CONFIG_KEYBOARD_C65 - ldx #$00 - stx C65_EXTKEYS_PR // connect all the extra C65 keys -#endif - - lda CIA1_PRB // read the keys - eor #$FF - sta STKEY // store reversed state - to filter out anything vulnerable to ghosting - -#if CONFIG_KEYBOARD_C128 - dex // puts $FF - stx VIC_XSCAN // disconnect the extra C128 keys -#endif -#if CONFIG_KEYBOARD_C65 - dex // puts $FF - stx C65_EXTKEYS_PR // disconnect the extra C65 keys -#endif - lda #$7F - sta CIA1_PRA // select the last row (bit to 0) - - lda CIA1_PRB // read the row - ora STKEY // filter out what might be the reason of ghosting - sta STKEY - - // Leave the CIA configured this way. It would be far better to disconnect - // the keyboard at this point, but certain software (mainly intros) is - // unable to, for example, read the space bar status. - - rts diff --git a/src/kernal/time/settim.s b/src/kernal/time/settim.s index c42b8627..7c07eb5c 100644 --- a/src/kernal/time/settim.s +++ b/src/kernal/time/settim.s @@ -21,7 +21,7 @@ SETTIM: sty TIME + 0 stx TIME + 1 sta TIME + 2 -.break + // Enable interrupts. More elegant solution would be pha + sei + ... + pla, // but (checked by running a test program) original ROM routine always // leaves IRQs enabled. diff --git a/src/kernal/time/udtim.s b/src/kernal/time/udtim.s index 1e52cae2..94b3fff4 100644 --- a/src/kernal/time/udtim.s +++ b/src/kernal/time/udtim.s @@ -29,10 +29,10 @@ udtim_rollover_check: lda TIME+0 cmp #$4F - bcc udtim_time_done + bcc udtim_keyboard lda TIME+1 cmp #$1A - bcc udtim_time_done + bcc udtim_keyboard // FALLTROUGH @@ -45,6 +45,51 @@ udtim_clock_reset: // FALLTROUGH -udtim_time_done: +// +// Keyboard part of the UDTIM routine, has to preserve .Y +// - jmp udtim_keyboard +udtim_keyboard: + + // According to [CM64], page 27, the action we have to perform is to copy + // the last row of keyboard to RAM, so that various routines can detect the STOP + // key press. But something as simple as this would have created warm restart + // with M+N+SPACE+RESTORE due to ghosting - so the original ROM has to provide + // some protection here. I do not know what the mechanism there exactly does, + // but I hope the mechanism below will be compatible enough. + + lda #$80 + sta CIA1_PRA // select all the rows except the last one +#if CONFIG_KEYBOARD_C128 + ldx #$00 + stx VIC_XSCAN // connect all the extra C128 keys +#endif +#if CONFIG_KEYBOARD_C65 + ldx #$00 + stx C65_EXTKEYS_PR // connect all the extra C65 keys +#endif + + lda CIA1_PRB // read the keys + eor #$FF + sta STKEY // store reversed state - to filter out anything vulnerable to ghosting + +#if CONFIG_KEYBOARD_C128 + dex // puts $FF + stx VIC_XSCAN // disconnect the extra C128 keys +#endif +#if CONFIG_KEYBOARD_C65 + dex // puts $FF + stx C65_EXTKEYS_PR // disconnect the extra C65 keys +#endif + lda #$7F + sta CIA1_PRA // select the last row (bit to 0) + + lda CIA1_PRB // read the row + ora STKEY // filter out what might be the reason of ghosting + sta STKEY + + // Leave the CIA configured this way. It would be far better to disconnect + // the keyboard at this point, but certain software (mainly intros) is + // unable to, for example, read the space bar status. + + rts From 54a6daa2c1d7614b222769673ae7eaa4d1dc9f90 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 19 Jul 2020 19:10:55 +0200 Subject: [PATCH 079/130] one more string aloccation optimization - for extended ROM machines --- src/aliases/,aliases_config.s | 7 + src/basic/engine_variables/assign_variable.s | 145 +++++++++++++++++- .../helper_index_up_a_38K_60K.s | 2 +- .../helper_index_up_a_46K_50K.s | 2 +- 4 files changed, 148 insertions(+), 8 deletions(-) diff --git a/src/aliases/,aliases_config.s b/src/aliases/,aliases_config.s index 42c8166b..ae1798de 100644 --- a/src/aliases/,aliases_config.s +++ b/src/aliases/,aliases_config.s @@ -364,3 +364,10 @@ .const CONFIG_COLOR_TXT = $01 #endif + + +// Determine if we need space-savings in BASIC code + +#if !ROM_LAYOUT_M65 +#define HAS_SMALL_BASIC +#endif diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 849cf50b..896b895b 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -243,14 +243,15 @@ assign_string_not_same: assign_string_not_text_area: - // Check if the new string is a temporary one - if so, reuse alocation - - // XXX - // Check if the old string belongs to the string area (is above FRETOP) jsr helper_cmp_fretop + +#if HAS_SMALL_BASIC bcc assign_string_no_optimizations +#else + bcc assign_string_try_takeover +#endif // FALLTROUGH @@ -261,18 +262,27 @@ assign_string_try_reuse: lda DSCPNT+0 cmp __FAC1+0 +#if HAS_SMALL_BASIC + // If size of both string equals - simply reuse it beq_16 helper_strvarcpy -assign_string_try_reuse_unsuccesful: - // No special case optimization is possible - but first get rid of the old string jsr varstr_free // FALLTROUGH +#else + + // If size of both string equals - simply reuse it + + bne assign_string_try_takeover_free + jmp helper_strvarcpy + +#endif + assign_string_no_optimizations: // Allocate memory for the new string @@ -296,3 +306,126 @@ assign_string_no_optimizations: // Copy the string and quit jmp helper_strvarcpy + + +#if !HAS_SMALL_BASIC + +assign_string_try_takeover_free: + + jsr varstr_free + + // FALLTROUGH + +assign_string_try_takeover: + + // Check if the new string is a temporary one - if so, takeover the allocation + + ldx #$19 + + // FALLTROUGH + +assign_string_tmp_check_loop: + + cpx TEMPPT + beq assign_string_no_optimizations // branch if this is not a temporary string + + lda $01, x + cmp __FAC1+1 + bne assign_string_tmp_check_next + + lda $02, x + cmp __FAC1+2 + bne assign_string_tmp_check_next + + lda $01, x + beq assign_string_tmp_check_next + + // This is a temporary string - takeover the content + +#if CONFIG_MEMORY_MODEL_60K + + ldy #$00 + phx_trash_a + lda $00, x + ldx # Date: Sun, 19 Jul 2020 19:14:57 +0200 Subject: [PATCH 080/130] fixed broken compilation on Commander X16 --- src/kernal/board_x16/cx16_stubs.s | 3 --- src/kernal/time/udtim.s | 8 ++++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/kernal/board_x16/cx16_stubs.s b/src/kernal/board_x16/cx16_stubs.s index da530dd6..2407b0e5 100644 --- a/src/kernal/board_x16/cx16_stubs.s +++ b/src/kernal/board_x16/cx16_stubs.s @@ -39,6 +39,3 @@ setup_pal_ntsc: wait_x_bars: STUB_IMPLEMENTATION() - -udtim_keyboard: - STUB_IMPLEMENTATION() diff --git a/src/kernal/time/udtim.s b/src/kernal/time/udtim.s index 94b3fff4..2fafdf53 100644 --- a/src/kernal/time/udtim.s +++ b/src/kernal/time/udtim.s @@ -51,6 +51,12 @@ udtim_clock_reset: udtim_keyboard: +#if CONFIG_PLATFORM_COMMANDER_X16 + + STUB_IMPLEMENTATION() + +#else + // According to [CM64], page 27, the action we have to perform is to copy // the last row of keyboard to RAM, so that various routines can detect the STOP // key press. But something as simple as this would have created warm restart @@ -93,3 +99,5 @@ udtim_keyboard: // unable to, for example, read the space bar status. rts + +#endif From cfc970e21a5f7ad8598efbb1525d399cec6c0e68 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 20 Jul 2020 15:26:48 +0200 Subject: [PATCH 081/130] added fetching PI to expression parser, fixed compilation warning --- src/basic/basic_commands/cmd_print.s | 2 ++ src/basic/engine_runtime/ad9e.frmevl.jmp.s | 8 +++++ .../{ad9e.frmevl.s => frmevl.s} | 30 +++++++++---------- tools/pngprepare.c | 5 +++- 4 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 src/basic/engine_runtime/ad9e.frmevl.jmp.s rename src/basic/engine_runtime/{ad9e.frmevl.s => frmevl.s} (95%) diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index 13faafdd..1110c46a 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -72,6 +72,8 @@ cmd_print_float: // XXX probably we should also check INTFLG here // XXX provide implementation + jmp do_NOT_IMPLEMENTED_error + // FALLTROUGH cmd_print_next_arg: diff --git a/src/basic/engine_runtime/ad9e.frmevl.jmp.s b/src/basic/engine_runtime/ad9e.frmevl.jmp.s new file mode 100644 index 00000000..5f01cd7b --- /dev/null +++ b/src/basic/engine_runtime/ad9e.frmevl.jmp.s @@ -0,0 +1,8 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// Just a compatibility jump - our routine is longer than original one + + jmp FRMEVL diff --git a/src/basic/engine_runtime/ad9e.frmevl.s b/src/basic/engine_runtime/frmevl.s similarity index 95% rename from src/basic/engine_runtime/ad9e.frmevl.s rename to src/basic/engine_runtime/frmevl.s index 9bc5cefd..fd42ecdc 100644 --- a/src/basic/engine_runtime/ad9e.frmevl.s +++ b/src/basic/engine_runtime/frmevl.s @@ -1,5 +1,4 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -19,7 +18,7 @@ // in a correct order // -// XXX finish the implementation: invoking functions, fetcching PI, fetching float, fetching variables +// XXX finish the implementation: invoking functions, fetching floats FRMEVL: @@ -78,7 +77,7 @@ FRMEVL_loop: dew TXTPTR #endif jsr fetch_variable - bcs !+ + bcs FRMEVL_fetch_float // Found the variable - copy descriptor to FAC1 @@ -116,17 +115,6 @@ FRMEVL_loop: jmp_8 FRMEVL_got_value -!: - // There is one possibility left - a floating point value - - - // XXX implement this part - - - // Nothing recognized - - jmp do_SYNTAX_error - // // This subroutine handles the situation when we have to execute a BASIC function // in place when parser normally expects a value @@ -175,9 +163,11 @@ FRMEVL_handle_bracket: FRMEVL_fetch_PI: - // XXX implement this + lda #const_PI + jsr mov_MEM_FAC1 - jmp do_NOT_IMPLEMENTED_error + jmp_8 FRMEVL_got_value_float // // This subroutine fetches the floating point value from the 'outside world' @@ -189,6 +179,14 @@ FRMEVL_fetch_float: jmp do_NOT_IMPLEMENTED_error + // FALLTROUGH + +FRMEVL_got_value_float: + + lda #$00 + sta VALTYP + beq FRMEVL_got_value + // // This subroutine fetches the string value from the 'outside world' // diff --git a/tools/pngprepare.c b/tools/pngprepare.c index 7c5b245c..8b5c6b5c 100644 --- a/tools/pngprepare.c +++ b/tools/pngprepare.c @@ -108,13 +108,16 @@ void abort_(const char * s, ...) void read_png_file(char* file_name) { unsigned char header[8]; // 8 is the maximum size that can be checked + size_t readResult; /* open file and test for it being a png */ infile = fopen(file_name, "rb"); if (infile == NULL) abort_("[read_png_file] File %s could not be opened for reading", file_name); - fread(header, 1, 8, infile); + readResult = fread(header, 1, 8, infile); + if (readResult != 8) + abort_("[read_png_file] File %s could not be read", file_name); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); From 151b9440dd11746c14395267d677b0def1abc659 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 20 Jul 2020 22:59:12 +0200 Subject: [PATCH 082/130] disabled some BASIC extensions on machines without extended ROM --- doc/Extended-BASIC.md | 36 +++++++++---------- .../basic_commands_CC/cmd__jumptable_CC.s | 22 +++++++++++- src/basic/basic_commands_CC/cmd_cold.s | 4 +++ src/basic/basic_commands_CC/cmd_mem.s | 3 ++ .../basic_commands_CC/helper_ask_if_sure.s | 4 +++ .../basic_commands_CC/helper_mem_tab_str.s | 3 ++ .../basic_commands_CC/helper_mem_tab_x.s | 3 ++ .../basic_commands_CC/helper_mem_tab_y.s | 3 ++ src/basic/wedge/wedge_dos.s | 4 +++ tools/generate_strings.cc | 26 +++++++------- 10 files changed, 76 insertions(+), 32 deletions(-) diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index 0e0e09cf..42765376 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -7,19 +7,19 @@ NOTE: Command syntax, behaviour details, and tokens are still subject to change! The DOS Wedge commands are only available in direct mode, and they have to start from the first character of the line. -### `@` +### `@` (all) Displays the error/status read from the current drive. Current drive is either the last device used by any I/O command, the one set by DOS Wedge command, or 8 as a fallback. -### `@$` +### `@$` (all) Displays the directory of the current drive. Does not destroy BASIC program in memory. -### `@device_number` +### `@device_number` (all) Changes the current drive number. -### `@command` +### `@command` (all) Sends the DOS command to the current drive. @@ -27,55 +27,55 @@ Sends the DOS command to the current drive. The Tape Wedge commands are only available in direct mode, and they have to start from the first character of the line. -### `←L ["file_name"]` +### `←L ["file_name"]` (all) Loads the file from tape. Depending on the configuration, it tries to load the file in TurboTape 64 format, in the standard CBM format, or autodetects the file format. -### `←M ["file_name"]` +### `←M ["file_name"]` (all) Like above, but merges a BASIC program to the one already stored in memory. -### `←H` +### `←H` (Mega65) Launches a built-in tape head alignment tool. Destroys program in memory. Press `RUN/STOP` to terminate the tool. ## Additional BASIC commands - I/O -### `MERGE "file_name" [, device_number]` +### `MERGE "file_name" [, device_number]` (all) Appends the BASIC program from a storage medium to the one currently present in memory. -### `BLOAD "file_name", device_number, start_address` +### `BLOAD "file_name", device_number, start_address` (all) Loads a binary file starting from the given memory location. Does not clear variables, does not perform BASIC program relinking, etc. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. -### `BVERIFY "file_name", device_number, start_address` +### `BVERIFY "file_name", device_number, start_address` (all) Verify operation for the binary data starting from a given addres. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. -### `BSAVE "file_name", device_number, start_address, end_address` +### `BSAVE "file_name", device_number, start_address, end_address` (all) Saves the binary data from the given memory area. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. ## Additional BASIC commands - misc -### `COLD` +### `COLD` (Mega65) Resets the machine. In direct mode asks for confirmation first. -### `FAST` +### `FAST` (all) Tries to switch the machine to turbo mode - details differ depending on the configured machine / motherboard. -### `SLOW` +### `SLOW` (all) Tries to switch the machine back to 1 MHz operation mode. -### `OLD` +### `OLD` (all) Tries to restore program destroyed by the `NEW` command or a reset. -### `MEM` +### `MEM` (Mega65) Displays BASIC memory usage information: * `TEXT` - size of BASIC program text, always at least 2 bytes are used @@ -84,10 +84,10 @@ Displays BASIC memory usage information: * `STRS` - bytes occupied by strings, also the ones belonging to arrays * `FREE` - unused space -### `CLEAR` +### `CLEAR` (all) Clears the screen content. -### `DISPOSE` +### `DISPOSE` (all) Runs the garbage collector - disposes outdated strings. diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s index 68245e36..97109edf 100644 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ b/src/basic/basic_commands_CC/cmd__jumptable_CC.s @@ -6,6 +6,7 @@ // Jumptable for BASIC commands with tokens prefixed by $CC // +#if !HAS_SMALL_BASIC .const command_CC_list = List().add( @@ -17,12 +18,31 @@ cmd_bsave, cmd_bverify, - cmd_cold, cmd_clear, varstr_garbage_collect, // cmd_dispose + + cmd_cold, cmd_mem ) +#else + +.const command_CC_list = List().add( + + cmd_old, + + cmd_merge, + + cmd_bload, + cmd_bsave, + cmd_bverify, + + cmd_clear, + varstr_garbage_collect // cmd_dispose +) + +#endif + #if !HAS_OPCODES_65C02 diff --git a/src/basic/basic_commands_CC/cmd_cold.s b/src/basic/basic_commands_CC/cmd_cold.s index e7300a4a..21f9cc05 100644 --- a/src/basic/basic_commands_CC/cmd_cold.s +++ b/src/basic/basic_commands_CC/cmd_cold.s @@ -3,6 +3,8 @@ // #LAYOUT# * * #IGNORE +#if !HAS_SMALL_BASIC + cmd_cold: jsr helper_ask_if_sure @@ -12,3 +14,5 @@ cmd_cold: jmp (vector_reset) // hardware CPU vector !: rts + +#endif diff --git a/src/basic/basic_commands_CC/cmd_mem.s b/src/basic/basic_commands_CC/cmd_mem.s index ded5d334..debd0e0c 100644 --- a/src/basic/basic_commands_CC/cmd_mem.s +++ b/src/basic/basic_commands_CC/cmd_mem.s @@ -4,6 +4,7 @@ // #LAYOUT# * * #IGNORE +#if !HAS_SMALL_BASIC #if (!ROM_LAYOUT_M65 || SEGMENT_BASIC_0) @@ -144,3 +145,5 @@ cmd_mem_next: #endif // ROM layout + +#endif // !HAS_SMALL_BASIC diff --git a/src/basic/basic_commands_CC/helper_ask_if_sure.s b/src/basic/basic_commands_CC/helper_ask_if_sure.s index 2d554b7c..e274b38e 100644 --- a/src/basic/basic_commands_CC/helper_ask_if_sure.s +++ b/src/basic/basic_commands_CC/helper_ask_if_sure.s @@ -9,6 +9,8 @@ // +#if !HAS_SMALL_BASIC + helper_ask_if_sure: #if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) @@ -75,3 +77,5 @@ helper_ask_if_sure_ok: #endif // ROM layout + +#endif // !HAS_SMALL_BASIC diff --git a/src/basic/basic_commands_CC/helper_mem_tab_str.s b/src/basic/basic_commands_CC/helper_mem_tab_str.s index 816add66..8bf56176 100644 --- a/src/basic/basic_commands_CC/helper_mem_tab_str.s +++ b/src/basic/basic_commands_CC/helper_mem_tab_str.s @@ -7,6 +7,7 @@ // Helper table for 'MEM' command - list of strings to print // +#if !HAS_SMALL_BASIC helper_mem_tab_str: @@ -15,3 +16,5 @@ helper_mem_tab_str: .byte IDX__STR_MEM_ARRS .byte IDX__STR_MEM_VARS .byte IDX__STR_MEM_TEXT + +#endif \ No newline at end of file diff --git a/src/basic/basic_commands_CC/helper_mem_tab_x.s b/src/basic/basic_commands_CC/helper_mem_tab_x.s index 2df7e5f9..ec74d04a 100644 --- a/src/basic/basic_commands_CC/helper_mem_tab_x.s +++ b/src/basic/basic_commands_CC/helper_mem_tab_x.s @@ -7,6 +7,7 @@ // Helper table for 'MEM' command - list of minuend zeropage variables // +#if !HAS_SMALL_BASIC helper_mem_tab_x: @@ -15,3 +16,5 @@ helper_mem_tab_x: .byte STREND .byte ARYTAB .byte VARTAB + +#endif diff --git a/src/basic/basic_commands_CC/helper_mem_tab_y.s b/src/basic/basic_commands_CC/helper_mem_tab_y.s index 74861e4a..d8a02f22 100644 --- a/src/basic/basic_commands_CC/helper_mem_tab_y.s +++ b/src/basic/basic_commands_CC/helper_mem_tab_y.s @@ -7,6 +7,7 @@ // Helper table for 'MEM' command - list of subtrahend zeropage variables // +#if !HAS_SMALL_BASIC helper_mem_tab_y: @@ -15,3 +16,5 @@ helper_mem_tab_y: .byte ARYTAB .byte VARTAB .byte TXTTAB + +#endif diff --git a/src/basic/wedge/wedge_dos.s b/src/basic/wedge/wedge_dos.s index ace10a2c..dae70840 100644 --- a/src/basic/wedge/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -60,6 +60,8 @@ wedge_dos: wedge_dos_command: +#if !HAS_SMALL_BASIC + // Check if command needs confirmation ldy #$00 @@ -106,6 +108,8 @@ wedge_dos_command_ask: wedge_dos_command_confirmed: +#endif // !HAS_SMALL_BASIC + // Provide command name jsr wedge_dos_setnam diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index 1c6da077..623e6a46 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -183,10 +183,10 @@ const StringEntryList GLOBAL_Keywords_CC = { ListType::KEYWORDS, "keywords_CC", { true, true, true, true, "KCC_03", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html { true, true, true, true, "KCC_04", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html { true, true, true, true, "KCC_05", "BVERIFY", }, - { true, true, true, true, "KCC_06", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) - { true, true, true, true, "KCC_07", "CLEAR", }, // Not present in CBM BASIC dialects, OpenROMs specific - { true, true, true, true, "KCC_08", "DISPOSE", }, // Not present in CBM BASIC dialects, OpenROMs specific - { true, true, true, true, "KCC_09", "MEM", }, // Not present in CBM BASIC dialects, OpenROMs specific + { true, true, true, true, "KCC_06", "CLEAR", }, // Not present in CBM BASIC dialects, OpenROMs specific + { true, true, true, true, "KCC_07", "DISPOSE", }, // Not present in CBM BASIC dialects, OpenROMs specific + { false, true, false, false, "KCC_08", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { false, true, false, false, "KCC_09", "MEM", }, // Not present in CBM BASIC dialects, OpenROMs specific // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c } }; @@ -316,17 +316,17 @@ const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", { true, true, true, true, "STR_READY", "\rREADY.\r" }, // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html { true, true, true, true, "STR_IN", " IN " }, - { true, true, true, true, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm + { false, true, false, false, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm // STD M65 U64 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, - { true, true, true, true, "STR_MEM_HDR", "\r\x12 AREA START SIZE \r" }, - { true, true, true, true, "STR_MEM_1", " $" }, - { true, true, true, true, "STR_MEM_2", " " }, - { true, true, true, true, "STR_MEM_TEXT", "\r TEXT" }, - { true, true, true, true, "STR_MEM_VARS", "\r VARS" }, - { true, true, true, true, "STR_MEM_ARRS", "\r ARRS" }, - { true, true, true, true, "STR_MEM_STRS", "\r STRS" }, - { true, true, true, true, "STR_MEM_FREE", "\r\r FREE" }, + { false, true, false, false, "STR_MEM_HDR", "\r\x12 AREA START SIZE \r" }, + { false, true, false, false, "STR_MEM_1", " $" }, + { false, true, false, false, "STR_MEM_2", " " }, + { false, true, false, false, "STR_MEM_TEXT", "\r TEXT" }, + { false, true, false, false, "STR_MEM_VARS", "\r VARS" }, + { false, true, false, false, "STR_MEM_ARRS", "\r ARRS" }, + { false, true, false, false, "STR_MEM_STRS", "\r STRS" }, + { false, true, false, false, "STR_MEM_FREE", "\r\r FREE" }, // Note: depending on configuration, additional strings will be added here } }; From 985a0882f6599893520f9c6779d6a3b0f0fb4f05 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 21 Jul 2020 17:45:24 +0200 Subject: [PATCH 083/130] changed handling of external token lists --- Makefile | 4 +- doc/Extended-BASIC-TODO.md | 2 +- ...packed_keywords_V2.s => packed_keywords.s} | 0 ...ked_keywords_CC.s => packed_keywords_01.s} | 4 +- ...ked_keywords_CD.s => packed_keywords_02.s} | 7 +- .../basic_commands_01/cmd__jumptable_01.s | 58 +++++++ .../cmd_fast_slow.s | 0 .../cmd_old.s | 0 .../basic_commands_02/cmd__jumptable_02.s | 60 +++++++ .../cmd_bload_bverify.s | 0 .../cmd_bsave.s | 0 .../cmd_clear.s | 0 .../cmd_cold.s | 0 .../cmd_dispose.s | 0 .../cmd_mem.s | 0 .../cmd_merge.s | 0 .../helper_ask_if_sure.s | 0 .../helper_bload_fetch_address.s | 0 .../helper_bload_fetch_filename.s | 0 .../helper_mem_tab_str.s | 0 .../helper_mem_tab_x.s | 0 .../helper_mem_tab_y.s | 0 .../basic_commands_CC/cmd__jumptable_CC.s | 76 --------- .../basic_commands_CD/cmd__jumptable_CD.s | 46 ------ src/basic/engine_editor/tokenise_line.s | 28 ++-- .../engine_runtime/execute_line_statements.s | 54 ++++--- src/basic/print/list_single_line.s | 152 +++++++++--------- src/basic/print/print_packed_freq_string.s | 16 +- tools/generate_strings.cc | 104 ++++-------- 29 files changed, 295 insertions(+), 316 deletions(-) rename src/basic/assets/{packed_keywords_V2.s => packed_keywords.s} (100%) rename src/basic/assets/{packed_keywords_CC.s => packed_keywords_01.s} (69%) rename src/basic/assets/{packed_keywords_CD.s => packed_keywords_02.s} (59%) create mode 100644 src/basic/basic_commands_01/cmd__jumptable_01.s rename src/basic/{basic_commands_CD => basic_commands_01}/cmd_fast_slow.s (100%) rename src/basic/{basic_commands_CC => basic_commands_01}/cmd_old.s (100%) create mode 100644 src/basic/basic_commands_02/cmd__jumptable_02.s rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_bload_bverify.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_bsave.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_clear.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_cold.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_dispose.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_mem.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/cmd_merge.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/helper_ask_if_sure.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/helper_bload_fetch_address.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/helper_bload_fetch_filename.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/helper_mem_tab_str.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/helper_mem_tab_x.s (100%) rename src/basic/{basic_commands_CC => basic_commands_02}/helper_mem_tab_y.s (100%) delete mode 100644 src/basic/basic_commands_CC/cmd__jumptable_CC.s delete mode 100644 src/basic/basic_commands_CD/cmd__jumptable_CD.s diff --git a/Makefile b/Makefile index 4236d9ce..ac8a7a94 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,8 @@ SRCDIR_BASIC = $(SRCDIR_COMMON) \ src/basic/,stubs_math \ src/basic/assets \ src/basic/basic_commands \ - src/basic/basic_commands_CC \ - src/basic/basic_commands_CD \ + src/basic/basic_commands_01 \ + src/basic/basic_commands_02 \ src/basic/basic_operators \ src/basic/basic_functions \ src/basic/board_m65 \ diff --git a/doc/Extended-BASIC-TODO.md b/doc/Extended-BASIC-TODO.md index d262dbe9..7f2ce4a7 100644 --- a/doc/Extended-BASIC-TODO.md +++ b/doc/Extended-BASIC-TODO.md @@ -31,7 +31,7 @@ Ideas for the future, most of them suitable for Mega65 or other power machines o * consider `BOOT` command * possibly some commands for creating menus and dialog boxes * more configurable `INPUT` -* `PRINT USING`, `PRINT AT(x, y)`, `PRINT CENTRE` +* `PRINT USING`, ability to position cursor, ability to print result in the center of the screen * `CURSOR` command from BASIC V10 * `RESTORE` should accept lline number as argument * hex/dec conversion functions diff --git a/src/basic/assets/packed_keywords_V2.s b/src/basic/assets/packed_keywords.s similarity index 100% rename from src/basic/assets/packed_keywords_V2.s rename to src/basic/assets/packed_keywords.s diff --git a/src/basic/assets/packed_keywords_CC.s b/src/basic/assets/packed_keywords_01.s similarity index 69% rename from src/basic/assets/packed_keywords_CC.s rename to src/basic/assets/packed_keywords_01.s index 8cbf9bed..85093d48 100644 --- a/src/basic/assets/packed_keywords_CC.s +++ b/src/basic/assets/packed_keywords_01.s @@ -4,6 +4,6 @@ // #LAYOUT# * * #IGNORE -packed_freq_keywords_CC: +packed_freq_keywords_01: - put_packed_freq_keywords_CC() + put_packed_freq_keywords_01() diff --git a/src/basic/assets/packed_keywords_CD.s b/src/basic/assets/packed_keywords_02.s similarity index 59% rename from src/basic/assets/packed_keywords_CD.s rename to src/basic/assets/packed_keywords_02.s index c474d947..37c9903a 100644 --- a/src/basic/assets/packed_keywords_CD.s +++ b/src/basic/assets/packed_keywords_02.s @@ -3,7 +3,10 @@ // #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE +#if !HAS_SMALL_BASIC -packed_freq_keywords_CD: +packed_freq_keywords_02: - put_packed_freq_keywords_CD() + put_packed_freq_keywords_02() + +#endif diff --git a/src/basic/basic_commands_01/cmd__jumptable_01.s b/src/basic/basic_commands_01/cmd__jumptable_01.s new file mode 100644 index 00000000..cc119e31 --- /dev/null +++ b/src/basic/basic_commands_01/cmd__jumptable_01.s @@ -0,0 +1,58 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Jumptable for BASIC commands with tokens prefixed by $01 +// + + +.const command_01_list = List().add( + + cmd_slow, + cmd_fast, + cmd_old, + + // NOTE! These commands are temporarily placed here, they should be a part of list 02! + + cmd_merge, + + cmd_bload, + cmd_bsave, + cmd_bverify, + + cmd_clear, + varstr_garbage_collect // cmd_dispose +) + + +#if !HAS_OPCODES_65C02 + + +command_01_jumptable_lo: + + put_jumptable_lo(command_01_list) + + +command_01_jumptable_hi: + + put_jumptable_hi(command_01_list) + + +#else // HAS_OPCODES_65C02 + + +__before_command_01_jumptable: + +.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary + +command_01_jumptable: + + put_jumptable(command_01_list) + + // Make sure routine size is always the same - build system limitation + +.if (__before_command_01_jumptable == command_01_jumptable) { brk } + + +#endif diff --git a/src/basic/basic_commands_CD/cmd_fast_slow.s b/src/basic/basic_commands_01/cmd_fast_slow.s similarity index 100% rename from src/basic/basic_commands_CD/cmd_fast_slow.s rename to src/basic/basic_commands_01/cmd_fast_slow.s diff --git a/src/basic/basic_commands_CC/cmd_old.s b/src/basic/basic_commands_01/cmd_old.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_old.s rename to src/basic/basic_commands_01/cmd_old.s diff --git a/src/basic/basic_commands_02/cmd__jumptable_02.s b/src/basic/basic_commands_02/cmd__jumptable_02.s new file mode 100644 index 00000000..6b669104 --- /dev/null +++ b/src/basic/basic_commands_02/cmd__jumptable_02.s @@ -0,0 +1,60 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Jumptable for BASIC commands with tokens prefixed by $02 +// + +#if !HAS_SMALL_BASIC + +.const command_02_list = List().add( + + // NOTE! These commands are temporarily placed in list 01! + + // cmd_merge, + + // cmd_bload, + // cmd_bsave, + // cmd_bverify, + + // cmd_clear, + // varstr_garbage_collect, // cmd_dispose + + cmd_cold, + cmd_mem +) + + +#if !HAS_OPCODES_65C02 + + +command_02_jumptable_lo: + + put_jumptable_lo(command_02_list) + + +command_02_jumptable_hi: + + put_jumptable_hi(command_02_list) + + +#else // HAS_OPCODES_65C02 + + +__before_command_02_jumptable: + +.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary + +command_02_jumptable: + + put_jumptable(command_02_list) + + // Make sure routine size is always the same - build system limitation + +.if (__before_command_02_jumptable == command_02_jumptable) { brk } + + +#endif + +#endif diff --git a/src/basic/basic_commands_CC/cmd_bload_bverify.s b/src/basic/basic_commands_02/cmd_bload_bverify.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_bload_bverify.s rename to src/basic/basic_commands_02/cmd_bload_bverify.s diff --git a/src/basic/basic_commands_CC/cmd_bsave.s b/src/basic/basic_commands_02/cmd_bsave.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_bsave.s rename to src/basic/basic_commands_02/cmd_bsave.s diff --git a/src/basic/basic_commands_CC/cmd_clear.s b/src/basic/basic_commands_02/cmd_clear.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_clear.s rename to src/basic/basic_commands_02/cmd_clear.s diff --git a/src/basic/basic_commands_CC/cmd_cold.s b/src/basic/basic_commands_02/cmd_cold.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_cold.s rename to src/basic/basic_commands_02/cmd_cold.s diff --git a/src/basic/basic_commands_CC/cmd_dispose.s b/src/basic/basic_commands_02/cmd_dispose.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_dispose.s rename to src/basic/basic_commands_02/cmd_dispose.s diff --git a/src/basic/basic_commands_CC/cmd_mem.s b/src/basic/basic_commands_02/cmd_mem.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_mem.s rename to src/basic/basic_commands_02/cmd_mem.s diff --git a/src/basic/basic_commands_CC/cmd_merge.s b/src/basic/basic_commands_02/cmd_merge.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_merge.s rename to src/basic/basic_commands_02/cmd_merge.s diff --git a/src/basic/basic_commands_CC/helper_ask_if_sure.s b/src/basic/basic_commands_02/helper_ask_if_sure.s similarity index 100% rename from src/basic/basic_commands_CC/helper_ask_if_sure.s rename to src/basic/basic_commands_02/helper_ask_if_sure.s diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_address.s b/src/basic/basic_commands_02/helper_bload_fetch_address.s similarity index 100% rename from src/basic/basic_commands_CC/helper_bload_fetch_address.s rename to src/basic/basic_commands_02/helper_bload_fetch_address.s diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_filename.s b/src/basic/basic_commands_02/helper_bload_fetch_filename.s similarity index 100% rename from src/basic/basic_commands_CC/helper_bload_fetch_filename.s rename to src/basic/basic_commands_02/helper_bload_fetch_filename.s diff --git a/src/basic/basic_commands_CC/helper_mem_tab_str.s b/src/basic/basic_commands_02/helper_mem_tab_str.s similarity index 100% rename from src/basic/basic_commands_CC/helper_mem_tab_str.s rename to src/basic/basic_commands_02/helper_mem_tab_str.s diff --git a/src/basic/basic_commands_CC/helper_mem_tab_x.s b/src/basic/basic_commands_02/helper_mem_tab_x.s similarity index 100% rename from src/basic/basic_commands_CC/helper_mem_tab_x.s rename to src/basic/basic_commands_02/helper_mem_tab_x.s diff --git a/src/basic/basic_commands_CC/helper_mem_tab_y.s b/src/basic/basic_commands_02/helper_mem_tab_y.s similarity index 100% rename from src/basic/basic_commands_CC/helper_mem_tab_y.s rename to src/basic/basic_commands_02/helper_mem_tab_y.s diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s deleted file mode 100644 index 97109edf..00000000 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ /dev/null @@ -1,76 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Jumptable for BASIC commands with tokens prefixed by $CC -// - -#if !HAS_SMALL_BASIC - -.const command_CC_list = List().add( - - cmd_old, - - cmd_merge, - - cmd_bload, - cmd_bsave, - cmd_bverify, - - cmd_clear, - varstr_garbage_collect, // cmd_dispose - - cmd_cold, - cmd_mem -) - -#else - -.const command_CC_list = List().add( - - cmd_old, - - cmd_merge, - - cmd_bload, - cmd_bsave, - cmd_bverify, - - cmd_clear, - varstr_garbage_collect // cmd_dispose -) - -#endif - - -#if !HAS_OPCODES_65C02 - - -command_CC_jumptable_lo: - - put_jumptable_lo(command_CC_list) - - -command_CC_jumptable_hi: - - put_jumptable_hi(command_CC_list) - - -#else // HAS_OPCODES_65C02 - - -__before_command_CC_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - -command_CC_jumptable: - - put_jumptable(command_CC_list) - - // Make sure routine size is always the same - build system limitation - -.if (__before_command_CC_jumptable == command_CC_jumptable) { brk } - - -#endif diff --git a/src/basic/basic_commands_CD/cmd__jumptable_CD.s b/src/basic/basic_commands_CD/cmd__jumptable_CD.s deleted file mode 100644 index 9cfa0c9a..00000000 --- a/src/basic/basic_commands_CD/cmd__jumptable_CD.s +++ /dev/null @@ -1,46 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Jumptable for BASIC commands with tokens prefixed by $CD -// - - -.const command_CD_list = List().add( - - cmd_slow, - cmd_fast -) - - -#if !HAS_OPCODES_65C02 - - -command_CD_jumptable_lo: - - put_jumptable_lo(command_CD_list) - - -command_CD_jumptable_hi: - - put_jumptable_hi(command_CD_list) - - -#else // HAS_OPCODES_65C02 - - -__before_command_CD_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - -command_CD_jumptable: - - put_jumptable(command_CD_list) - - // Make sure routine size is always the same - build system limitation - -.if (__before_command_CD_jumptable == command_CD_jumptable) { brk } - - -#endif diff --git a/src/basic/engine_editor/tokenise_line.s b/src/basic/engine_editor/tokenise_line.s index a8dc44ab..06ddf755 100644 --- a/src/basic/engine_editor/tokenise_line.s +++ b/src/basic/engine_editor/tokenise_line.s @@ -80,21 +80,25 @@ tokenise_line_loop: // Check for extended tokens - lda #packed_freq_keywords_CC + lda #>packed_freq_keywords_01 sta FRESPC+1 jsr tk_search - bcc tokenise_line_keyword_CC // branch if keyword identified + bcc tokenise_line_keyword_01 // branch if keyword identified - lda #packed_freq_keywords_CD + lda #>packed_freq_keywords_02 sta FRESPC+1 jsr tk_search - bcc tokenise_line_keyword_CD // branch if keyword identified + bcc tokenise_line_keyword_02 // branch if keyword identified + +#endif // Shorten packed keyword candidate and try again @@ -169,20 +173,24 @@ tokenise_line_char: // Support for extended keyword lists -tokenise_line_keyword_CC: +#if !HAS_SMALL_BASIC + +tokenise_line_keyword_02: // Store the token list index - lda #$CC + lda #$02 skip_2_bytes_trash_nvz // FALLTROUGH -tokenise_line_keyword_CD: +#endif + +tokenise_line_keyword_01: // Store the token list index - lda #$CD + lda #$01 ldy tk__offset sta BUF, y diff --git a/src/basic/engine_runtime/execute_line_statements.s b/src/basic/engine_runtime/execute_line_statements.s index 3ac95047..17624201 100644 --- a/src/basic/engine_runtime/execute_line_statements.s +++ b/src/basic/engine_runtime/execute_line_statements.s @@ -39,12 +39,24 @@ execute_statements: // Check if token is valid for execution +#if HAS_SMALL_BASIC + + cpx #$01 + beq execute_statements_01 + +#else + + cpx #$03 + bcc execute_statements_extended + +#endif + + cpx #$CB + beq_16 cmd_go // // 'GO' command has a strange token, placed after function tokens + cpx #$7F bcc_16 execute_statements_var_assign // not a token - try variable assign - cpx #$A6 - bcs execute_statements_extended - #if !HAS_OPCODES_65C02 // Get the jump table entry for it, push it on the stack, and then RTS to start it. @@ -67,25 +79,25 @@ execute_statements: #endif +#if !HAS_SMALL_BASIC execute_statements_extended: // Support for extended BASIC commands - cpx #$CC - beq execute_statements_CC - cpx #$CD - beq execute_statements_CD + // XXX consider jumpable here - // 'GO' command has a strange token, it is placed after function tokens + cpx #$01 + beq execute_statements_01 - cpx #$CB - beq_16 cmd_go + cpx #$02 + beq execute_statements_02 jmp do_SYNTAX_error +#endif -execute_statements_CC: +execute_statements_01: // Get the sub-token, check that it is valid @@ -93,7 +105,7 @@ execute_statements_CC: cmp #$00 beq_16 do_SYNTAX_error - cmp #(TK__MAXTOKEN_keywords_CC+1) + cmp #(TK__MAXTOKEN_keywords_01+1) bcs_16 do_SYNTAX_error // Execute command @@ -103,9 +115,9 @@ execute_statements_CC: // Get the jump table entry for it, push it on the stack, and then RTS to start it. tax - lda command_CC_jumptable_hi - 1, x + lda command_01_jumptable_hi - 1, x pha - lda command_CC_jumptable_lo - 1, x + lda command_01_jumptable_lo - 1, x pha rts @@ -116,12 +128,13 @@ execute_statements_CC: asl tax - jmp (command_CC_jumptable - 2, x) + jmp (command_01_jumptable - 2, x) #endif +#if !HAS_SMALL_BASIC -execute_statements_CD: +execute_statements_02: // Get the sub-token, check that it is valid @@ -129,7 +142,7 @@ execute_statements_CD: cmp #$00 beq_16 do_SYNTAX_error - cmp #(TK__MAXTOKEN_keywords_CD+1) + cmp #(TK__MAXTOKEN_keywords_02+1) bcs_16 do_SYNTAX_error // Execute command @@ -139,9 +152,9 @@ execute_statements_CD: // Get the jump table entry for it, push it on the stack, and then RTS to start it. tax - lda command_CD_jumptable_hi - 1, x + lda command_02_jumptable_hi - 1, x pha - lda command_CD_jumptable_lo - 1, x + lda command_02_jumptable_lo - 1, x pha rts @@ -152,10 +165,11 @@ execute_statements_CD: asl tax - jmp (command_CD_jumptable - 2, x) + jmp (command_02_jumptable - 2, x) #endif +#endif // !HAS_SMALL_BASIC execute_statements_end_of_line: diff --git a/src/basic/print/list_single_line.s b/src/basic/print/list_single_line.s index ac2a4e19..ce235f98 100644 --- a/src/basic/print/list_single_line.s +++ b/src/basic/print/list_single_line.s @@ -79,6 +79,7 @@ list_print_loop: jmp list_is_literal list_not_quote: + // Check quote mode, and display as literal if required ldx QTSW bne list_is_literal @@ -86,87 +87,19 @@ list_not_quote: cmp #$FF beq list_is_pi + // Check for extended BASIC tokens + cmp #$01 + beq list_display_token_01 +#if !HAS_SMALL_BASIC + cmp #$02 + beq list_display_token_02 +#endif + + // Check for literals cmp #$7F bcc list_is_literal - // Display a token - -list_display_token_CC: - - cmp #$CC - bne list_display_token_CD - - // Fetch the sub-token - - iny -#if ROM_LAYOUT_M65 - jsr peek_via_OLDTXT -#elif CONFIG_MEMORY_MODEL_60K - ldx #packed_freq_keywords_CC + lda #packed_freq_keywords_01 bne print_freq_packed_string // branch always -print_packed_keyword_CD: // .X - token number +#if !HAS_SMALL_BASIC - lda #packed_freq_keywords_CD +print_packed_keyword_02: // .X - token number + + lda #packed_freq_keywords_02 bne print_freq_packed_string // branch always +#endif + print_packed_keyword_V2: // .X - token number lda # Date: Tue, 21 Jul 2020 17:48:33 +0200 Subject: [PATCH 084/130] small size optimization in LIST command --- src/basic/print/list_single_line.s | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/basic/print/list_single_line.s b/src/basic/print/list_single_line.s index ce235f98..e7b2fcce 100644 --- a/src/basic/print/list_single_line.s +++ b/src/basic/print/list_single_line.s @@ -199,11 +199,15 @@ list_display_token_01: // Now ask for it to be printed phy_trash_a jsr print_packed_keyword_01 + + // FALLTROUGH + +list_display_token_01_done: + ply_trash_a // Next iteration - jmp list_print_loop - + jmp_8 list_print_loop #if !HAS_SMALL_BASIC @@ -219,10 +223,7 @@ list_display_token_02: // Now ask for it to be printed phy_trash_a jsr print_packed_keyword_02 - ply_trash_a - - // Next iteration - jmp list_print_loop + jmp_8 list_display_token_01_done #endif From 41fcc14921b8feba957db4e3f1ad6f924ce76548 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 21 Jul 2020 17:57:31 +0200 Subject: [PATCH 085/130] bugfix for LIST command and extended keywords --- src/basic/print/list_single_line.s | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/basic/print/list_single_line.s b/src/basic/print/list_single_line.s index e7b2fcce..c0efd299 100644 --- a/src/basic/print/list_single_line.s +++ b/src/basic/print/list_single_line.s @@ -142,6 +142,7 @@ list_not_rem: bne list_print_loop // branch always list_is_pi: + lda #$7E // FALLTROUGH @@ -202,12 +203,12 @@ list_display_token_01: // FALLTROUGH -list_display_token_01_done: +list_display_token_ext_done: ply_trash_a // Next iteration - jmp_8 list_print_loop + jmp_8 list_not_rem #if !HAS_SMALL_BASIC @@ -223,7 +224,7 @@ list_display_token_02: // Now ask for it to be printed phy_trash_a jsr print_packed_keyword_02 - jmp_8 list_display_token_01_done + jmp_8 list_display_token_ext_done #endif From a1b13b31efac57aeb4169fabcb46b706b885a7f5 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 21 Jul 2020 18:18:52 +0200 Subject: [PATCH 086/130] removed unneeded 65C02 bugfix --- src/basic/basic_commands_01/cmd__jumptable_01.s | 11 +---------- src/basic/basic_commands_02/cmd__jumptable_02.s | 11 +---------- src/basic/basic_functions/fun__jumptable.s | 11 +---------- src/kernal/screen/chrout_screen_jumptable_codes.s | 11 +---------- 4 files changed, 4 insertions(+), 40 deletions(-) diff --git a/src/basic/basic_commands_01/cmd__jumptable_01.s b/src/basic/basic_commands_01/cmd__jumptable_01.s index cc119e31..6e3f4f61 100644 --- a/src/basic/basic_commands_01/cmd__jumptable_01.s +++ b/src/basic/basic_commands_01/cmd__jumptable_01.s @@ -41,18 +41,9 @@ command_01_jumptable_hi: #else // HAS_OPCODES_65C02 - -__before_command_01_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - command_01_jumptable: + // Note: 65C02 has the page boundary vector bug fixed! put_jumptable(command_01_list) - // Make sure routine size is always the same - build system limitation - -.if (__before_command_01_jumptable == command_01_jumptable) { brk } - - #endif diff --git a/src/basic/basic_commands_02/cmd__jumptable_02.s b/src/basic/basic_commands_02/cmd__jumptable_02.s index 6b669104..f554611f 100644 --- a/src/basic/basic_commands_02/cmd__jumptable_02.s +++ b/src/basic/basic_commands_02/cmd__jumptable_02.s @@ -41,20 +41,11 @@ command_02_jumptable_hi: #else // HAS_OPCODES_65C02 - -__before_command_02_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - command_02_jumptable: + // Note: 65C02 has the page boundary vector bug fixed! put_jumptable(command_02_list) - // Make sure routine size is always the same - build system limitation - -.if (__before_command_02_jumptable == command_02_jumptable) { brk } - - #endif #endif diff --git a/src/basic/basic_functions/fun__jumptable.s b/src/basic/basic_functions/fun__jumptable.s index 266ff347..d5b47811 100644 --- a/src/basic/basic_functions/fun__jumptable.s +++ b/src/basic/basic_functions/fun__jumptable.s @@ -55,18 +55,9 @@ function_jumptable_hi: #else // HAS_OPCODES_65C02 - -__before_function_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - function_jumptable: + // Note: 65C02 has the page boundary vector bug fixed! put_jumptable(function_list) - // Make sure routine size is always the same - build system limitation - -.if (__before_function_jumptable == function_jumptable) { brk } - - #endif diff --git a/src/kernal/screen/chrout_screen_jumptable_codes.s b/src/kernal/screen/chrout_screen_jumptable_codes.s index 1f4fe7b3..07d30cd4 100644 --- a/src/kernal/screen/chrout_screen_jumptable_codes.s +++ b/src/kernal/screen/chrout_screen_jumptable_codes.s @@ -83,18 +83,9 @@ chrout_screen_jumptable_hi: #else // HAS_OPCODES_65C02 - -__before_chrout_screen_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - chrout_screen_jumptable: + // Note: 65C02 has the page boundary vector bug fixed! put_jumptable(chrout_list) - // Make sure routine size is always the same - build system limitation - -.if (__before_chrout_screen_jumptable == chrout_screen_jumptable) { brk } - - #endif From 05cd426cba3276aa5d8fbf472cb3f5a68a421a11 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 21 Jul 2020 18:26:42 +0200 Subject: [PATCH 087/130] made LIST command more robust --- src/basic/print/list_single_line.s | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/basic/print/list_single_line.s b/src/basic/print/list_single_line.s index c0efd299..51f90887 100644 --- a/src/basic/print/list_single_line.s +++ b/src/basic/print/list_single_line.s @@ -195,7 +195,7 @@ list_display_token_01: // Check if token is known cpx #TK__MAXTOKEN_keywords_01 - bcs list_is_unknown // XXX consider displaying two question marks here, not one + bcs list_is_unknown // Now ask for it to be printed phy_trash_a @@ -219,7 +219,7 @@ list_display_token_02: // Check if token is known cpx #TK__MAXTOKEN_keywords_02 - bcs list_is_unknown // XXX consider displaying two question marks here, not one + bcs list_is_unknown // Now ask for it to be printed phy_trash_a @@ -248,8 +248,15 @@ list_fetch_subtoken: // Subtract $1 from token to get offset in token list tax + beq list_fetch_subtoken_fail dex rts +list_fetch_subtoken_fail: + + dey + jmp list_display_unknown_token + + #endif // ROM layout From 148f1c190866bcb37419d3f8163ca882a5b08746 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 21 Jul 2020 18:39:52 +0200 Subject: [PATCH 088/130] naming is now uniform --- README.md | 2 +- bin/README.txt | 2 +- doc/Development.md | 44 +++++++++---------- .../board_m65/4000.mega65_vectable_basic_1.s | 2 +- src/basic/engine_runtime/do_error.s | 2 +- .../board_m65/4000.mega65_vectable_kernal_1.s | 2 +- tools/generate_strings.cc | 10 ++--- 7 files changed, 32 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 2472cd42..fa697474 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# open-roms +# Open ROMs ![screenshot demonstrating some features](./doc/screenshot-demo.png) diff --git a/bin/README.txt b/bin/README.txt index 7358db92..806e59cf 100644 --- a/bin/README.txt +++ b/bin/README.txt @@ -22,6 +22,6 @@ Have fun! ------ -PXL font was created by Retrofan, we got a permission to include it with OpenROMs under GNU Lesser General Public License 3.0, see: +PXL font was created by Retrofan, we got a permission to include it with Open ROMs under GNU Lesser General Public License 3.0, see: - https://www.forum64.de/index.php?thread/84000-neuer-c64-systemfont-auch-plus4-c128-atari/&postID=1493383#post1493383 diff --git a/doc/Development.md b/doc/Development.md index 2a834a22..fab2ca6e 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -1,5 +1,5 @@ -# OpenROMs development guide +# Open ROMs development guide NOTE: this document is a preliminary version, definitely incomplete! @@ -10,30 +10,30 @@ NOTE: this document is a preliminary version, definitely incomplete! - [DolphinDOS](./Protocol-DolphinDOS.md) -## Guidelines for software developers for OpenROMs compatibility +## Guidelines for software developers for Open ROMs compatibility -Most important: always test your software on the original ROMs too. If your code works on the OpenROMs, but fails on the original firmware - than something is clearly wrong, and it might stop working once we make OpenROMs more compatible for one reason or another. +Most important: always test your software on the original ROMs too. If your code works on the Open ROMs, but fails on the original firmware - than something is clearly wrong, and it might stop working once we make Open ROMs more compatible for one reason or another. ### Unofficial ROM APIs -Please, do not use any internal/unofficial OpenROMs API. They WILL change in an incompatible way, you may believe me. Using unofficial API of the original ROMs is OK if the routine is marked as supported in the [implementation status](../STATUS.md) document. +Please, do not use any internal/unofficial Open ROMs API. They WILL change in an incompatible way, you may believe me. Using unofficial API of the original ROMs is OK if the routine is marked as supported in the [implementation status](../STATUS.md) document. -### Compatibility with OpenROMs for Mega65 +### Compatibility with Open ROMs for Mega65 -The Mega65 OpenROMs build aims to provide a C64-compatible memory map in range `$00000-$0FFFF`. For `$10000` and above, everything is still subject to change. +The Mega65 Open ROMs build aims to provide a C64-compatible memory map in range `$00000-$0FFFF`. For `$10000` and above, everything is still subject to change. Please note, that certain ROM routines are moved to additional Mega65 ROM area (2x8KB is not enough to implement full ROM functionality and additional features) - original locations contain just short compatibility code which remaps memory, calls the real routine, and restores default mapping (that means all blocks unmapped). This shouldn't be a problem for original C64 software, but can make a difference for Mega65-aware code; thus, please follow these simple rules: - do not call ROM routines with .B set to anything other than 0 (and .B set to 0x40 or above is a receipe for disaster!) - be aware that ROM routines may restore the default memory mapping by means of MAP/EOM -OpenROMs interrupt handlers do not touch the ROM mapping, range `0x4000-0xBFFF` can be freely mapped without disabling IRQ or NMI. The .Z register is mostly safe to use too - some routines might use it, but they will alwayys restore it's previous state. Please be aware, that for maximum compatibility our IRQ/NMI handlers DO NOT store/restore .Z register. +Open ROMs interrupt handlers do not touch the ROM mapping, range `0x4000-0xBFFF` can be freely mapped without disabling IRQ or NMI. The .Z register is mostly safe to use too - some routines might use it, but they will alwayys restore it's previous state. Please be aware, that for maximum compatibility our IRQ/NMI handlers DO NOT store/restore .Z register. ### API extensions #### PETSCII -OpenROMs provides support for several additional PETSCII codes (all compatible with C128 and/or C65): +Open ROMs provides support for several additional PETSCII codes (all compatible with C128 and/or C65): | PETSCII code | description | | :----------: | :-------------------------------------------------- | @@ -69,7 +69,7 @@ Mega65 build starts in legacy mode, which is intended to be reasonably compatibl - Slightly different chargen. On C64 machines pressing C= + G or C= + M key combinations produces the same visual result as C= + H or C= + N, respectively - despite keycap printing suggests they should produce tinner bars. This was intentional change in the C64 ROMs (compared to VIC-20), to prevent colour problems on 80s era TVs. Screen font used in the legacy mode duplicates this change, but the font intended for native mode has this change reverted back. Additionally, the π sign is available for lower/upper case set too. -## Tinkering with OpenROMs +## Tinkering with Open ROMs Make sure to read the main [README](../README.md) first - although any help with the project is always welcome, you need to be aware of the possible legal problems we want to avoid. @@ -77,19 +77,19 @@ Make sure to read the main [README](../README.md) first - although any help with List of the most important make targets: -| target | description | -| :------------------ | :----------------------------------------------------------------------------- | -| `all` | builds all ROMs, places them in 'build' subdirectory | -| `clean` | removes all the compilation results and intermediate files | -| `updatebin` | upates ROMs in 'bin' subdirectory - with embedded version string, for release | -| `testsimilarity` | launches the similarity tool, see [README](../README.md) | -| `test` | builds the 'custom' configuration, launches it using VICE emulator | -| `test_generic` | builds the default ROMs, for generic C64/C128, launches using VICE | -| `test_generic_x128` | as above, but launches C128 emulator instead | -| `test_mega65` | builds the Mega65 ROM, launches it using XEMU emulator | -| `test_ultimate64` | builds the Ultimate 64 configuration, launches it using VICE emulator | -| `test_hybrid` | builds a hybrid ROM (OpenROMs Kernal + original BASIC), launches it using VICE | -| `test_testing` | builds a rather odd testing configuration, launches it using VICE emulator | +| target | description | +| :------------------ | :------------------------------------------------------------------------------ | +| `all` | builds all ROMs, places them in 'build' subdirectory | +| `clean` | removes all the compilation results and intermediate files | +| `updatebin` | upates ROMs in 'bin' subdirectory - with embedded version string, for release | +| `testsimilarity` | launches the similarity tool, see [README](../README.md) | +| `test` | builds the 'custom' configuration, launches it using VICE emulator | +| `test_generic` | builds the default ROMs, for generic C64/C128, launches using VICE | +| `test_generic_x128` | as above, but launches C128 emulator instead | +| `test_mega65` | builds the Mega65 ROM, launches it using XEMU emulator | +| `test_ultimate64` | builds the Ultimate 64 configuration, launches it using VICE emulator | +| `test_hybrid` | builds a hybrid ROM (Open ROMs Kernal + original BASIC), launches it using VICE | +| `test_testing` | builds a rather odd testing configuration, launches it using VICE emulator | ### Code segments and ROM layouts diff --git a/src/basic/board_m65/4000.mega65_vectable_basic_1.s b/src/basic/board_m65/4000.mega65_vectable_basic_1.s index d49ed0fe..17f96e1b 100644 --- a/src/basic/board_m65/4000.mega65_vectable_basic_1.s +++ b/src/basic/board_m65/4000.mega65_vectable_basic_1.s @@ -31,7 +31,7 @@ #else - // Vector table (OpenROMs private!) + // Vector table (Open ROMs private!) .word INITMSG .word LINKPRG diff --git a/src/basic/engine_runtime/do_error.s b/src/basic/engine_runtime/do_error.s index fc2b6573..a3d64f63 100644 --- a/src/basic/engine_runtime/do_error.s +++ b/src/basic/engine_runtime/do_error.s @@ -50,7 +50,7 @@ do_kernal_error: // .A = KERNAL error code, also almost ma bpl do_basic_error // branch always #endif - // Error messages specific to OpenROMs BASIC dialect + // Error messages specific to Open ROMs BASIC dialect do_MEMORY_CORRUPT_error: .byte $E6 diff --git a/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s b/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s index 9accb56b..95d310e5 100644 --- a/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s +++ b/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s @@ -21,7 +21,7 @@ #else - // Vector table (OpenROMs private!) + // Vector table (Open ROMs private!) .word IOINIT .word RAMTAS diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index 5a438b6d..e54a6ef3 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -190,8 +190,8 @@ const StringEntryList GLOBAL_Keywords_01 = { ListType::KEYWORDS, "keywords_01", { true, true, true, true, "K02_02", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html { true, true, true, true, "K02_03", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html { true, true, true, true, "K02_04", "BVERIFY", }, - { true, true, true, true, "K02_05", "CLEAR", }, // Not present in CBM BASIC dialects, OpenROMs specific - { true, true, true, true, "K02_06", "DISPOSE", }, // Not present in CBM BASIC dialects, OpenROMs specific + { true, true, true, true, "K02_05", "CLEAR", }, // Not present in CBM BASIC dialects, Open ROMs specific + { true, true, true, true, "K02_06", "DISPOSE", }, // Not present in CBM BASIC dialects, Open ROMs specific } }; // extended BASIC keywords - list reserved for generic (mostly hardware independent) BASIC commands @@ -201,7 +201,7 @@ const StringEntryList GLOBAL_Keywords_02 = { ListType::KEYWORDS, "keywords_02", // STD M65 U64 X16 { false, true, false, false, "K02_07", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) - { false, true, false, false, "K02_08", "MEM", }, // Not present in CBM BASIC dialects, OpenROMs specific + { false, true, false, false, "K02_08", "MEM", }, // Not present in CBM BASIC dialects, Open ROMs specific // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c } }; @@ -263,7 +263,7 @@ const StringEntryList GLOBAL_Errors = { ListType::STRINGS_BASIC, "errors", { false, false, false, false, "EV7_27", "UNRESOLVED REFERENCE" }, // not used for now { true, true, true, true, "EV7_28", "NOT IMPLEMENTED" }, // this message actually differs from the CBM one { false, false, false, false, "EV7_29", "FILE READ" }, // not used for now - // STD M65 U64 X16 --- error strings specific to OpenROMs, not present in CBM BASIC dialects + // STD M65 U64 X16 --- error strings specific to Open ROMs, not present in CBM BASIC dialects { true, true, true, true, "EOR_2A", "MEMORY CORRUPT" }, } }; @@ -278,7 +278,7 @@ const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html { true, true, true, true, "STR_IN", " IN " }, { false, true, false, false, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm - // STD M65 U64 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs + // STD M65 U64 X16 --- misc strings specific to Open ROMs, not present in CBM ROMs { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, { false, true, false, false, "STR_MEM_HDR", "\r\x12 AREA START SIZE \r" }, { false, true, false, false, "STR_MEM_1", " $" }, From 3189edd0d30b3dc92b77dc5f4fce321517e3e98a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Tue, 21 Jul 2020 20:17:03 +0200 Subject: [PATCH 089/130] started work on arrays --- src/aliases/,aliases_ram_lowmem.s | 4 ++-- src/basic/basic_commands/cmd__jumptable.s | 2 +- src/basic/engine_variables/array_create.s | 10 ++++++++++ src/basic/engine_variables/fetch_variable.s | 5 +++++ src/basic/engine_variables/fetch_variable_arr.s | 10 ++++++++++ src/basic/engine_variables/fetch_variable_name.s | 3 +++ 6 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/basic/engine_variables/array_create.s create mode 100644 src/basic/engine_variables/fetch_variable_arr.s diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index d673f7bc..f0f4438a 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -35,8 +35,8 @@ .label RESHO = $26 // $26-$2A temporary variables, [!] our usage might be different .label TXTTAB = $2B // $2B-$2C start of BASIC code .label VARTAB = $2D // $2D-$2E end of BASIC code, start of variables - .label ARYTAB = $2F // $2F-$30 -- NOT IMPLEMENTED -- - .label STREND = $31 // $31-$32 -- NOT IMPLEMENTED -- + .label ARYTAB = $2F // $2F-$30 pointer to start of array storage + .label STREND = $31 // $31-$32 pointer to start of free RAM .label FRETOP = $33 // $33-$34 pointer to bottom of strings area .label FRESPC = $35 // $35-$36 [!] our implementation uses this as temporary string pointer .label MEMSIZ = $37 // $37-$38 highest address of BASIC memory + 1 diff --git a/src/basic/basic_commands/cmd__jumptable.s b/src/basic/basic_commands/cmd__jumptable.s index a23533a4..321ebb31 100644 --- a/src/basic/basic_commands/cmd__jumptable.s +++ b/src/basic/basic_commands/cmd__jumptable.s @@ -17,7 +17,7 @@ cmd_data, cmd_inputhash, cmd_input, - cmd_dim, + array_create, // cmd_dim cmd_read, assign_variable, // cmd_let cmd_goto, diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s new file mode 100644 index 00000000..159d9cc1 --- /dev/null +++ b/src/basic/engine_variables/array_create.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +array_create: + + // XXX + + jsr do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 1c99b4f6..29957635 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -15,6 +15,11 @@ fetch_variable: bcc !+ rts !: + // If this is array, redirect to appropriate routine + + bit DIMFLG + bmi_16 fetch_variable_arr + // Handle special variables - TI$, TI, ST jsr is_var_TI_string diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s new file mode 100644 index 00000000..c2ce4581 --- /dev/null +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +fetch_variable_arr: + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine_variables/fetch_variable_name.s b/src/basic/engine_variables/fetch_variable_name.s index d4356d79..5fe50075 100644 --- a/src/basic/engine_variables/fetch_variable_name.s +++ b/src/basic/engine_variables/fetch_variable_name.s @@ -94,6 +94,9 @@ fetch_variable_type_string: fetch_variable_name_check_array: // XXX add check for array + lda #$00 + sta DIMFLG + clc rts From 800361b27f87e6552fe47d1a7bb77dd7d42a0af3 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 22 Jul 2020 20:16:25 +0200 Subject: [PATCH 090/130] some more work towards arrays --- src/aliases/,aliases_ram_lowmem.s | 2 +- src/basic/basic_commands/cmd__unimplemented.s | 2 - src/basic/basic_commands/cmd_dim.s | 6 +++ src/basic/basic_commands/cmd_let.s | 6 +++ src/basic/engine_variables/array_create.s | 13 +++++++ .../engine_variables/fetch_variable_name.s | 39 +++++++++++++++---- 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 src/basic/basic_commands/cmd_dim.s create mode 100644 src/basic/basic_commands/cmd_let.s diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index f0f4438a..ef37b7ac 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -53,7 +53,7 @@ .label OPMASK = $4D // -- NOT IMPLEMENTED -- .label DEFPNT = $4E // $4E-$4F -- NOT IMPLEMENTED -- .label DSCPNT = $50 // $50-$52 temporary area fro string handling, [!] our usage might differ - .label FOUR6 = $53 // -- NOT IMPLEMENTED -- + .label FOUR6 = $53 // size of variable content (float = 5, integer = 2, string descriptor = 3) .label JMPER = $54 // $54-$56 -- NOT IMPLEMENTED -- .label TEMPF1 = $57 // $57-$5B BASIC numeric work area .label TEMPF2 = $5C // $5C-$60 BASIC numeric work area diff --git a/src/basic/basic_commands/cmd__unimplemented.s b/src/basic/basic_commands/cmd__unimplemented.s index ffa3d866..18c9fb1c 100644 --- a/src/basic/basic_commands/cmd__unimplemented.s +++ b/src/basic/basic_commands/cmd__unimplemented.s @@ -19,8 +19,6 @@ cmd_inputhash: nop cmd_input: nop -cmd_dim: - nop cmd_read: nop cmd_if: diff --git a/src/basic/basic_commands/cmd_dim.s b/src/basic/basic_commands/cmd_dim.s new file mode 100644 index 00000000..cccb47e2 --- /dev/null +++ b/src/basic/basic_commands/cmd_dim.s @@ -0,0 +1,6 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +// PLACEHOLDER for completeness - jumptable contains direct address diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s new file mode 100644 index 00000000..cccb47e2 --- /dev/null +++ b/src/basic/basic_commands/cmd_let.s @@ -0,0 +1,6 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +// PLACEHOLDER for completeness - jumptable contains direct address diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 159d9cc1..d63dd62b 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -5,6 +5,19 @@ array_create: + // First retrieve array name + + jsr fetch_variable_name + bcs_16 do_SYNTAX_error + + // It will be easier if we first perform garbage collecion (arrays are not declared often) + + jsr varstr_garbage_collect + + // XXX bit DIMFLG, bmi = use default params + + + // XXX jsr do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine_variables/fetch_variable_name.s b/src/basic/engine_variables/fetch_variable_name.s index 5fe50075..74e0dbd5 100644 --- a/src/basic/engine_variables/fetch_variable_name.s +++ b/src/basic/engine_variables/fetch_variable_name.s @@ -4,7 +4,7 @@ // // Carry set = failure, not recognized variable name -// +// sets FOUR6 and DIMFLG ($80 for array, $00 for regular variable) fetch_variable_name: @@ -61,6 +61,9 @@ fetch_variable_check_type: fetch_variable_type_float: + lda #$05 + sta FOUR6 + #if !HAS_OPCODES_65CE02 jsr unconsume_character #else @@ -71,19 +74,25 @@ fetch_variable_type_float: fetch_variable_type_integer: + ldy #$02 + + lda #$02 + sta FOUR6 + lda VARNAM+0 ora #$80 sta VARNAM+0 lda #$00 - skip_2_bytes_trash_nvz - - // FALLTROUGH + beq !+ // branch always fetch_variable_type_string: + ldy #$03 lda #$80 +!: sta VALTYP + sty FOUR6 lda VARNAM+1 ora #$80 @@ -93,10 +102,24 @@ fetch_variable_type_string: fetch_variable_name_check_array: - // XXX add check for array + jsr fetch_character_skip_spaces + cmp #$28 // '(' + beq !+ + + // This is not an array + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + lda #$00 + skip_2_bytes_trash_nvz +!: + // This is an array + + lda #$80 + sta DIMFLG - - - clc rts From 448132060013d9cd293af55ae345784231877772 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 23 Jul 2020 15:26:48 +0200 Subject: [PATCH 091/130] added TI$ and keybopard scanning constants for UP9600 interrupt rate --- src/basic/assets/table_ti_hi.s | 13 +++++++++++++ src/basic/assets/table_ti_lo.s | 13 +++++++++++++ src/basic/assets/table_ti_mid.s | 13 +++++++++++++ src/basic/engine_variables/array_create.s | 4 +++- src/kernal/assets/irq_timing_hi.s | 16 ++++++++++++++++ src/kernal/assets/irq_timing_lo.s | 16 ++++++++++++++++ src/kernal/keyboard/scnkey.s | 4 ++++ src/kernal/rs232/up9600_ihitab.s | 21 --------------------- src/kernal/rs232/up9600_ilotab.s | 21 --------------------- src/kernal/time/udtim.s | 10 +++++++++- 10 files changed, 87 insertions(+), 44 deletions(-) delete mode 100644 src/kernal/rs232/up9600_ihitab.s delete mode 100644 src/kernal/rs232/up9600_ilotab.s diff --git a/src/basic/assets/table_ti_hi.s b/src/basic/assets/table_ti_hi.s index becbe187..e0615a58 100644 --- a/src/basic/assets/table_ti_hi.s +++ b/src/basic/assets/table_ti_hi.s @@ -8,9 +8,22 @@ table_TI_hi: +#if !CONFIG_RS232_UP9600 + .byte $20 // 10 hours = 2169000 ticks .byte $03 // 1 hour = 216000 ticks .byte $00 // 10 minutes = 36000 ticks .byte $00 // 1 minute = 3600 ticks .byte $00 // 10 seconds = 600 ticks .byte $00 // 1 second = 60 ticks + +#else + + .byte $23 // 10 hours = 2304000 ticks + .byte $03 // 1 hour = 230400 ticks + .byte $00 // 10 minutes = 38400 ticks + .byte $00 // 1 minute = 3840 ticks + .byte $00 // 10 seconds = 640 ticks + .byte $00 // 1 second = 64 ticks + +#endif \ No newline at end of file diff --git a/src/basic/assets/table_ti_lo.s b/src/basic/assets/table_ti_lo.s index 5b3368cb..4f7ef5ae 100644 --- a/src/basic/assets/table_ti_lo.s +++ b/src/basic/assets/table_ti_lo.s @@ -8,9 +8,22 @@ table_TI_lo: +#if !CONFIG_RS232_UP9600 + .byte $80 // 10 hours = 2169000 ticks .byte $C0 // 1 hour = 216000 ticks .byte $A0 // 10 minutes = 36000 ticks .byte $10 // 1 minute = 3600 ticks .byte $58 // 10 seconds = 600 ticks .byte $3C // 1 second = 60 ticks + +#else + + .byte $00 // 10 hours = 2304000 ticks + .byte $00 // 1 hour = 230400 ticks + .byte $00 // 10 minutes = 38400 ticks + .byte $00 // 1 minute = 3840 ticks + .byte $80 // 10 seconds = 640 ticks + .byte $40 // 1 second = 64 ticks + +#endif diff --git a/src/basic/assets/table_ti_mid.s b/src/basic/assets/table_ti_mid.s index 5515a733..22b38fb8 100644 --- a/src/basic/assets/table_ti_mid.s +++ b/src/basic/assets/table_ti_mid.s @@ -8,9 +8,22 @@ table_TI_mid: +#if !CONFIG_RS232_UP9600 + .byte $F5 // 10 hours = 2169000 ticks .byte $4B // 1 hour = 216000 ticks .byte $8C // 10 minutes = 36000 ticks .byte $0E // 1 minute = 3600 ticks .byte $02 // 10 seconds = 600 ticks .byte $00 // 1 second = 60 ticks + +#else + + .byte $28 // 10 hours = 2304000 ticks + .byte $84 // 1 hour = 230400 ticks + .byte $96 // 10 minutes = 38400 ticks + .byte $0F // 1 minute = 3840 ticks + .byte $02 // 10 seconds = 640 ticks + .byte $00 // 1 second = 64 ticks + +#endif diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index d63dd62b..14d4a750 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -10,7 +10,9 @@ array_create: jsr fetch_variable_name bcs_16 do_SYNTAX_error - // It will be easier if we first perform garbage collecion (arrays are not declared often) + // XXX check if the array already exists + + // It will be easier if we first perform garbage collection (arrays are not declared often) jsr varstr_garbage_collect diff --git a/src/kernal/assets/irq_timing_hi.s b/src/kernal/assets/irq_timing_hi.s index b884d60b..69547d41 100644 --- a/src/kernal/assets/irq_timing_hi.s +++ b/src/kernal/assets/irq_timing_hi.s @@ -22,5 +22,21 @@ irq_timing_hi: // high bytes +#if !CONFIG_RS232_UP9600 + .byte >17045 // NTSC .byte >16421 // PAL + +#else + +// +// Timer values needed by UP9600 +// +// Original driver code by Daniel Dallman with Bo Zimmerman adaptations, +// these causes the tick to be generated 64 times per second +// + + .byte $42 // NTSC + .byte $40 // PAL + +#endif \ No newline at end of file diff --git a/src/kernal/assets/irq_timing_lo.s b/src/kernal/assets/irq_timing_lo.s index 5043d2ba..3760f444 100644 --- a/src/kernal/assets/irq_timing_lo.s +++ b/src/kernal/assets/irq_timing_lo.s @@ -22,5 +22,21 @@ irq_timing_lo: // low bytes +#if !CONFIG_RS232_UP9600 + .byte <17045 // NTSC .byte <16421 // PAL + +#else + +// +// Timer values needed by UP9600 +// +// Original driver code by Daniel Dallman with Bo Zimmerman adaptations, +// these causes the tick to be generated 64 times per second +// + + .byte $95 // NTSC + .byte $25 // PAL + +#endif \ No newline at end of file diff --git a/src/kernal/keyboard/scnkey.s b/src/kernal/keyboard/scnkey.s index cd0cb7a5..c48f847b 100644 --- a/src/kernal/keyboard/scnkey.s +++ b/src/kernal/keyboard/scnkey.s @@ -327,7 +327,11 @@ scnkey_got_key: // .Y should now contain the key offset in matrix pointed by KEY // // Besides - since I am the one who writes the code, I will make the values exactly how I like them :D +#if !CONFIG_RS232_UP9600 lda #$16 +#else + lda #$18 +#endif sta DELAY // FALLTROUGH diff --git a/src/kernal/rs232/up9600_ihitab.s b/src/kernal/rs232/up9600_ihitab.s deleted file mode 100644 index 43b53bd7..00000000 --- a/src/kernal/rs232/up9600_ihitab.s +++ /dev/null @@ -1,21 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Timer values for PAL/NTSC - high bytes -// - -// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations - - -#if CONFIG_RS232_UP9600 - - -up9600_ihitab: - - .byte $42 - .byte $40 - - -#endif // CONFIG_RS232_UP9600 diff --git a/src/kernal/rs232/up9600_ilotab.s b/src/kernal/rs232/up9600_ilotab.s deleted file mode 100644 index 5492bedf..00000000 --- a/src/kernal/rs232/up9600_ilotab.s +++ /dev/null @@ -1,21 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Timer values for PAL/NTSC - low bytes -// - -// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations - - -#if CONFIG_RS232_UP9600 - - -up9600_ilotab: - - .byte $95 - .byte $25 - - -#endif // CONFIG_RS232_UP9600 diff --git a/src/kernal/time/udtim.s b/src/kernal/time/udtim.s index 2fafdf53..44913c57 100644 --- a/src/kernal/time/udtim.s +++ b/src/kernal/time/udtim.s @@ -28,10 +28,18 @@ UDTIM: udtim_rollover_check: lda TIME+0 +#if !CONFIG_RS232_UP9600 cmp #$4F +#else + cmp #$54 +#endif bcc udtim_keyboard lda TIME+1 - cmp #$1A +#if !CONFIG_RS232_UP9600 + cmp #$1A +#else + cmp #$60 +#endif bcc udtim_keyboard // FALLTROUGH From d6163f7cf7d5c0766f4531bef03865ea29656a2a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 23 Jul 2020 16:36:31 +0200 Subject: [PATCH 092/130] small optimization in string handling code --- src/basic/engine_variables/tmpstr_free.s | 2 +- src/basic/engine_variables/tmpstr_free_all.s | 2 +- src/basic/engine_variables/varstr_free.s | 13 ++++++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/basic/engine_variables/tmpstr_free.s b/src/basic/engine_variables/tmpstr_free.s index b21678dd..14d41291 100644 --- a/src/basic/engine_variables/tmpstr_free.s +++ b/src/basic/engine_variables/tmpstr_free.s @@ -64,7 +64,7 @@ tmpstr_free_loop: sty DSCPNT+0 phx_trash_a - jsr varstr_free_non_0 + jsr varstr_free_no_checks plx_trash_a // Mark empty string as free and quit diff --git a/src/basic/engine_variables/tmpstr_free_all.s b/src/basic/engine_variables/tmpstr_free_all.s index 86e5f6fe..bd0f3067 100644 --- a/src/basic/engine_variables/tmpstr_free_all.s +++ b/src/basic/engine_variables/tmpstr_free_all.s @@ -28,7 +28,7 @@ tmpstr_free_all_loop: sta DSCPNT+2 phx_trash_a - jsr varstr_free_non_0 + jsr varstr_free_no_checks plx_trash_a !: inx diff --git a/src/basic/engine_variables/varstr_free.s b/src/basic/engine_variables/varstr_free.s index 1f57d165..b4815d7a 100644 --- a/src/basic/engine_variables/varstr_free.s +++ b/src/basic/engine_variables/varstr_free.s @@ -16,21 +16,20 @@ varstr_free: // Check the string size - do not do anything if 0 lda DSCPNT+0 - bne varstr_free_non_0 + bne !+ rts - -varstr_free_non_0: // entry point to be used when it is clear that string is not empty - +!: // Check if string is above FRETOP (in string area) - // XXX move this check out of the routine jsr helper_cmp_fretop - bcs !+ + bcs varstr_free_no_checks // No, it does not belong to string area - quit rts -!: + +varstr_free_no_checks: // entry point to be used when it is clear that string is not empty and above FRETOP + // Check if this is the lowest string bne varstr_free_inside From 28f6a96ff30ecdc46584e8dae4aeba776d94ddf6 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 23 Jul 2020 19:43:28 +0200 Subject: [PATCH 093/130] more work towards array creating --- src/basic/engine_variables/array_create.s | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 14d4a750..811de49a 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -16,6 +16,46 @@ array_create: jsr varstr_garbage_collect + // Now, create the array structure + + lda STREND+0 + sta INDEX+0 + lda STREND+1 + sta INDEX+1 + + // XXX check if there is enough distance between INDEX and FRETOP + + // Store: + // - the array name (2 bytes) + // - offset to the next array (2 bytes) - 0 to mark the last one + // - initial array dimension - 0 + +#if CONFIG_MEMORY_MODEL_60K + + // XXX: implement this + +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + ldy #$00 + lda VARNAM+0 + sta (STREND), y + iny + lda VARNAM+1 + sta (STREND), y + iny + lda #$00 + sta (STREND),y + iny + sta (STREND),y + iny + sta (STREND),y + +#endif + + // + + + // XXX bit DIMFLG, bmi = use default params From 692890787725595746d7b81c487178f3be314fc5 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 24 Jul 2020 21:24:45 +0200 Subject: [PATCH 094/130] reworked current array creation code (idea was wrong), compilation fix in Kernal --- src/basic/engine_variables/array_create.s | 100 +++++++++++++++------- src/kernal/rs232/rs232_count_channels.s | 4 +- 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 811de49a..14558871 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -12,54 +12,90 @@ array_create: // XXX check if the array already exists - // It will be easier if we first perform garbage collection (arrays are not declared often) + // Push variable name and FOUR6 on the stack - fetching dimensions might cause + // the to be overwritten by the expression parser + + lda VARNAM+0 + pha + lda VARNAM+1 + pha + lda FOUR6 + pha + + // Push 0 to mark end of the dimensions + + lda #$00 + pha + + // Now check if the array dimension is given - if not, assume '10' was specified + + bit DIMFLG + bmi array_create_fetch_dims + + lda #$0A + pha + bne array_create_store_dims // branch always + +array_create_fetch_dims: + + // XXX check if stack has reasonable space free + + // Fetch the dimension, put it on the stack - confirmed with orioginal ROM, + // that it also stores dimensions in the reverse order + + jsr fetch_uint8 + bcs_16 do_SYNTAX_error + pha + + // Check if more dimensions are given + + jsr fetch_character_skip_spaces + cmp #$2C // ',' + beq array_create_fetch_dims + cmp #$29 // ')' + bne_16 do_SYNTAX_error + + // FALLTROUGH + +array_create_store_dims: + + // We got the dimensions, time to alocate memory. Arrays are not declared too often, + // it will be easier if we perform the garbage collection now jsr varstr_garbage_collect - // Now, create the array structure + // Create the initial array structure - lda STREND+0 - sta INDEX+0 - lda STREND+1 - sta INDEX+1 + // Bytes 0/1 - array name, but we can not fetch it easily now, so skip it + // Bytes 2/3 - offset to the next array - our will be the last one, so 0 - but we will set it later + // Byte 4 - number of dimensions, determine it + // Bytes 5+ - size in each dimension - // XXX check if there is enough distance between INDEX and FRETOP + // INDEX+2/+3 will be used to calculate number of 'records' - // Store: - // - the array name (2 bytes) - // - offset to the next array (2 bytes) - 0 to mark the last one - // - initial array dimension - 0 + ldy #$01 + sty INDEX+3 + dey + sty INDEX+4 -#if CONFIG_MEMORY_MODEL_60K - - // XXX: implement this + ldy #$05 +!: + pla + beq array_create_store_num_dims -#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX implement this - ldy #$00 - lda VARNAM+0 - sta (STREND), y - iny - lda VARNAM+1 - sta (STREND), y - iny - lda #$00 - sta (STREND),y - iny - sta (STREND),y - iny - sta (STREND),y -#endif +array_create_store_num_dims: - // + // .Y contains number of dimensions + 5 + + // XXX rework code below - // XXX bit DIMFLG, bmi = use default params - // XXX jsr do_NOT_IMPLEMENTED_error diff --git a/src/kernal/rs232/rs232_count_channels.s b/src/kernal/rs232/rs232_count_channels.s index 49379a81..c4f17976 100644 --- a/src/kernal/rs232/rs232_count_channels.s +++ b/src/kernal/rs232/rs232_count_channels.s @@ -16,13 +16,13 @@ rs232_count_channels: ldy LDTND !: dey - bmi close_rs232_search_done + bmi !+ lda FAT, y cmp #$02 bne !- inx bpl !- // branch always - +!: rts From 7eada6daa713cbaf4bb6427e370662b1b4da22db Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 26 Jul 2020 10:10:34 +0200 Subject: [PATCH 095/130] more work on creating arrays --- src/basic/engine_variables/array_create.s | 117 ++++++++++++++---- .../helper_array_create_mul.s | 76 ++++++++++++ 2 files changed, 167 insertions(+), 26 deletions(-) create mode 100644 src/basic/engine_variables/helper_array_create_mul.s diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 14558871..6994ed3b 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -22,36 +22,48 @@ array_create: lda FOUR6 pha - // Push 0 to mark end of the dimensions - - lda #$00 - pha - - // Now check if the array dimension is given - if not, assume '10' was specified + // Check if the array dimension is given - if not, assume '10' was specified bit DIMFLG bmi array_create_fetch_dims lda #$0A pha + lda #$00 + pha + ldx #$01 bne array_create_store_dims // branch always array_create_fetch_dims: + ldx #$00 // counts number of dimensions + + // FALLTROUGH + +array_create_fetch_dims_loop: + + inx + // XXX check if stack has reasonable space free // Fetch the dimension, put it on the stack - confirmed with orioginal ROM, // that it also stores dimensions in the reverse order - jsr fetch_uint8 + jsr fetch_uint16 bcs_16 do_SYNTAX_error + + // XXX we probably need to increment LINNUM first + + lda LINNUM+0 + pha + lda LINNUM+1 pha // Check if more dimensions are given jsr fetch_character_skip_spaces cmp #$2C // ',' - beq array_create_fetch_dims + beq array_create_fetch_dims_loop cmp #$29 // ')' bne_16 do_SYNTAX_error @@ -62,40 +74,93 @@ array_create_store_dims: // We got the dimensions, time to alocate memory. Arrays are not declared too often, // it will be easier if we perform the garbage collection now + phx_trash_a jsr varstr_garbage_collect - // Create the initial array structure - - // Bytes 0/1 - array name, but we can not fetch it easily now, so skip it - // Bytes 2/3 - offset to the next array - our will be the last one, so 0 - but we will set it later - // Byte 4 - number of dimensions, determine it - // Bytes 5+ - size in each dimension - - // INDEX+2/+3 will be used to calculate number of 'records' + // __FAC1+0/+1 will be used to calculate number of elements ldy #$01 - sty INDEX+3 + sty __FAC1+0 dey - sty INDEX+4 + sty __FAC1+1 - ldy #$05 -!: + // Create the initial array structure (format checked by creating arrays with original ROM) + + // Bytes 0/1 - array name, but we can not fetch it easily now, so skip it for now + // Bytes 2/3 - offset to the next array, skip it for now too + // Byte 4 - number of dimensions + // Bytes 5+ - max index in each dimension (big endian!), this will be set in a loop + + ldy #$04 pla - beq array_create_store_num_dims - // XXX implement this +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K -array_create_store_num_dims: + sta (STREND), y - // .Y contains number of dimensions + 5 +#endif - // XXX rework code below + iny // .Y - index to store dimension sizes + tax // .X - dimensions not sotred yet + // FALLTROUGH +array_create_store_loop: +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + pla + sta (STREND), y + sta __FAC1+3 + iny + pla + sta (STREND), y + sta __FAC1+2 + iny +#endif + + jsr helper_array_create_mul + + dex + bne array_create_store_loop + + // FALLTROUGH + +array_create_store_dims_done: + + // Restore FOUR6, calculate number of bytes needed for storage + + pha + sta FOUR6 // XXX do we need to store this value in FOUR6? + sta __FAC1+2 + stx __FAC1+3 // .X is 0 at this point + + jsr helper_array_create_mul + + // XXX check if we have enough memory + + // XXX retrieve and store array name + + // XXX calculate and store offset to the next array + + // XXX clear area + + // XXX adjust STREND + + // XXX adjust offset of the previous array + + jmp do_NOT_IMPLEMENTED_error - jsr do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine_variables/helper_array_create_mul.s b/src/basic/engine_variables/helper_array_create_mul.s new file mode 100644 index 00000000..3be777ec --- /dev/null +++ b/src/basic/engine_variables/helper_array_create_mul.s @@ -0,0 +1,76 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// 16-bit multiplication, INDEX+0/+1 = __FAC1+0/+1 * __FAC1+2/+3; __FAC1+0/+1 = INDEX+0/+1 +// uses INDEX+2/+3 (for helper routine) as work area + + +helper_array_create_mul: // preserves .X and .Y + + phx_trash_a + + // We will reuse 8x8 multiplication routine used by floating point operations + + // __FAC1+0 (lo byte) * __FAC1+2 (lo byte) + + lda __FAC1+0 + sta INDEX+2 + lda __FAC1+2 + jsr mul_FAC2_FAC1_8x8 // this preserves .Y + + sta INDEX+0 // result - lo byte + stx INDEX+1 // result - hi byte + + // __FAC1+0 (lo byte) * __FAC1+3 (hi byte) + + lda __FAC1+0 + sta INDEX+2 + lda __FAC1+3 + jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result + + // __FAC1+1 (hi byte) * __FAC1+2 (lo byte) + + lda __FAC1+1 + sta INDEX+2 + lda __FAC1+2 + jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result + + // __FAC1+1 (hi byte) * __FAC1+3 (hi byte) has to be 0, + // otherwise the result would be out of range + // do not calculate + + lda __FAC1+0 + beq helper_array_create_mul_success + lda __FAC1+3 + beq helper_array_create_mul_success + + // FALLTROUGH + +helper_array_create_mul_error: + + jmp do_OUT_OF_MEMORY_error + +helper_array_create_mul_success: + + lda INDEX+0 + sta __FAC+0 + lda INDEX+1 + sta __FAC+1 + + plx_trash_a + rts + +helper_array_create_mul_add: + + jsr mul_FAC2_FAC1_8x8 + + cpx #$00 + bne helper_array_create_mul_error + + clc + adc INDEX+1 + bcs helper_array_create_mul_error + sta INDEX+1 + + rts From 07bbc21e50cf086514359f37ea94db4823905eb7 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 26 Jul 2020 18:06:01 +0200 Subject: [PATCH 096/130] small code reorganization for arrays support --- src/basic/engine_runtime/check_stack_space.s | 12 +++ src/basic/engine_runtime/frmevl.s | 4 +- src/basic/engine_variables/array_create.s | 94 ++++++++++++++++--- .../helper_array_create_mul.s | 6 +- .../helper_index_up_a_38K_60K.s | 2 +- .../helper_index_up_a_46K_50K.s | 2 +- 6 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 src/basic/engine_runtime/check_stack_space.s diff --git a/src/basic/engine_runtime/check_stack_space.s b/src/basic/engine_runtime/check_stack_space.s new file mode 100644 index 00000000..2aa2d8b3 --- /dev/null +++ b/src/basic/engine_runtime/check_stack_space.s @@ -0,0 +1,12 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +check_stack_space: + + tsx + cpx #$60 // XXX is this a safe threshold? + bcc_16 do_FORMULA_TOO_COMPLEX_error + + rts diff --git a/src/basic/engine_runtime/frmevl.s b/src/basic/engine_runtime/frmevl.s index fd42ecdc..c2b24bdd 100644 --- a/src/basic/engine_runtime/frmevl.s +++ b/src/basic/engine_runtime/frmevl.s @@ -323,9 +323,7 @@ FRMEVL_push_operator_address: // Check if there is enough stack space; this could not have been done earlier, // as this is the place where unary operator support calls - tsx - cpx #$60 // XXX is this a safe threshold? - bcc_16 do_FORMULA_TOO_COMPLEX_error + jsr check_stack_space // Push the operator address to stack, in a form // suitable for RTS diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 6994ed3b..d63106e9 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -44,15 +44,26 @@ array_create_fetch_dims_loop: inx - // XXX check if stack has reasonable space free + // Check if the stack has reasonable space free - // Fetch the dimension, put it on the stack - confirmed with orioginal ROM, - // that it also stores dimensions in the reverse order + jsr check_stack_space + + // Fetch the dimension, increment it by 1, and put it on the stack; + // confirmed with original ROM, that it also stores dimensions in the reverse order jsr fetch_uint16 bcs_16 do_SYNTAX_error - // XXX we probably need to increment LINNUM first +#if !HAS_OPCODES_65CE02 + inc LINNUM+0 + bne !+ + inc LINNUM+1 +!: +#else + inw LINNUM +#endif + + beq_16 do_OUT_OF_MEMORY_error lda LINNUM+0 pha @@ -144,7 +155,7 @@ array_create_store_dims_done: // Restore FOUR6, calculate number of bytes needed for storage pha - sta FOUR6 // XXX do we need to store this value in FOUR6? + sta FOUR6 // XXX do we need to store this value in FOUR6? is it still needed? sta __FAC1+2 stx __FAC1+3 // .X is 0 at this point @@ -152,15 +163,76 @@ array_create_store_dims_done: // XXX check if we have enough memory - // XXX retrieve and store array name + // Retrieve and store array name - // XXX calculate and store offset to the next array + ldy #$00 - // XXX clear area +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX - // XXX adjust STREND +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX adjust offset of the previous array + pla + sta (STREND), y + iny + pla + sta (STREND), y + +#endif + + // Calculate and store offset to the next array + + lda #$02 + jsr helper_INDEX_up_A + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + ldy #$04 + lda (STREND), y + +#endif + + asl + jsr helper_INDEX_up_A + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + ldy #$02 + lda INDEX+0 + sta (STREND), y + iny + lda INDEX+1 + sta (STREND), y + +#endif + + // Clear newly alocated area + + // XXX implement this + + // Adjust STREND + + // XXX implement this jmp do_NOT_IMPLEMENTED_error - diff --git a/src/basic/engine_variables/helper_array_create_mul.s b/src/basic/engine_variables/helper_array_create_mul.s index 3be777ec..1d42e218 100644 --- a/src/basic/engine_variables/helper_array_create_mul.s +++ b/src/basic/engine_variables/helper_array_create_mul.s @@ -54,14 +54,14 @@ helper_array_create_mul_error: helper_array_create_mul_success: lda INDEX+0 - sta __FAC+0 + sta __FAC1+0 lda INDEX+1 - sta __FAC+1 + sta __FAC1+1 plx_trash_a rts -helper_array_create_mul_add: +helper_array_create_mul_8x8_add: jsr mul_FAC2_FAC1_8x8 diff --git a/src/basic/engine_variables/helper_index_up_a_38K_60K.s b/src/basic/engine_variables/helper_index_up_a_38K_60K.s index 259453da..54198e25 100644 --- a/src/basic/engine_variables/helper_index_up_a_38K_60K.s +++ b/src/basic/engine_variables/helper_index_up_a_38K_60K.s @@ -3,7 +3,7 @@ // #LAYOUT# * * #IGNORE // -// Helper routine, used by garbage collector and string concatenation +// Helper routine, used in several places // #if CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K diff --git a/src/basic/engine_variables/helper_index_up_a_46K_50K.s b/src/basic/engine_variables/helper_index_up_a_46K_50K.s index e5b09d35..38ede00c 100644 --- a/src/basic/engine_variables/helper_index_up_a_46K_50K.s +++ b/src/basic/engine_variables/helper_index_up_a_46K_50K.s @@ -5,7 +5,7 @@ // This has to go $E000 or above - it can be used by routines which bank out the main BASIC ROM! // -// Helper routine, used by garbage collector and string concatenation +// Helper routine, used in several places // #if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K From b7dee84390a08a1ebf2c19b58311ac0b33490768 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 26 Jul 2020 22:03:06 +0200 Subject: [PATCH 097/130] added memory checks and some other bits to array creation routine --- src/basic/engine_variables/array_create.s | 102 ++++++++++-------- .../helper_array_create_checkmem.s | 62 +++++++++++ .../helper_array_create_mul.s | 32 +++--- 3 files changed, 133 insertions(+), 63 deletions(-) create mode 100644 src/basic/engine_variables/helper_array_create_checkmem.s diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index d63106e9..46026364 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -88,14 +88,21 @@ array_create_store_dims: phx_trash_a jsr varstr_garbage_collect - // __FAC1+0/+1 will be used to calculate number of elements + // __FAC1+1/+2 will be used to calculate number of elements ldy #$01 - sty __FAC1+0 - dey sty __FAC1+1 + dey + sty __FAC1+2 - // Create the initial array structure (format checked by creating arrays with original ROM) + // Check if there is enough free memory for the header + + pla // .A - number of dimensions + sta __FAC1+0 + jsr helper_array_create_checkmem + lda __FAC1+0 + + // Create the initial array structure (header) - format checked by creating arrays with original ROM // Bytes 0/1 - array name, but we can not fetch it easily now, so skip it for now // Bytes 2/3 - offset to the next array, skip it for now too @@ -103,13 +110,15 @@ array_create_store_dims: // Bytes 5+ - max index in each dimension (big endian!), this will be set in a loop ldy #$04 - pla #if CONFIG_MEMORY_MODEL_60K - // XXX - // XXX: implement this - // XXX + stx INDEX+2 + + ldx # 0, then we certainly have enough space + + lda INDEX+3 + bne helper_array_create_checkmem_success + + // We have very little memory left - we need at least number of dimensions*2 + 5 bytes + + lda __FAC1+0 + asl + clc + adc #$04 + + cmp INDEX+2 + bcs helper_array_create_checkmem_fail + + // FALLTROUGH + +helper_array_create_checkmem_success: + + rts + +helper_array_create_checkmem_fail: + + jmp do_OUT_OF_MEMORY_error diff --git a/src/basic/engine_variables/helper_array_create_mul.s b/src/basic/engine_variables/helper_array_create_mul.s index 1d42e218..b0424f44 100644 --- a/src/basic/engine_variables/helper_array_create_mul.s +++ b/src/basic/engine_variables/helper_array_create_mul.s @@ -2,7 +2,7 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE -// 16-bit multiplication, INDEX+0/+1 = __FAC1+0/+1 * __FAC1+2/+3; __FAC1+0/+1 = INDEX+0/+1 +// 16-bit multiplication, INDEX+0/+1 = __FAC1+1/+2 * __FAC1+3/+4; __FAC1+1/+2 = INDEX+0/+1 // uses INDEX+2/+3 (for helper routine) as work area @@ -12,37 +12,37 @@ helper_array_create_mul: // preserves .X and .Y // We will reuse 8x8 multiplication routine used by floating point operations - // __FAC1+0 (lo byte) * __FAC1+2 (lo byte) + // __FAC1+1 (lo byte) * __FAC1+3 (lo byte) - lda __FAC1+0 + lda __FAC1+1 sta INDEX+2 - lda __FAC1+2 + lda __FAC1+3 jsr mul_FAC2_FAC1_8x8 // this preserves .Y sta INDEX+0 // result - lo byte stx INDEX+1 // result - hi byte - // __FAC1+0 (lo byte) * __FAC1+3 (hi byte) - - lda __FAC1+0 - sta INDEX+2 - lda __FAC1+3 - jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result - - // __FAC1+1 (hi byte) * __FAC1+2 (lo byte) + // __FAC1+1 (lo byte) * __FAC1+4 (hi byte) lda __FAC1+1 sta INDEX+2 - lda __FAC1+2 + lda __FAC1+4 jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result - // __FAC1+1 (hi byte) * __FAC1+3 (hi byte) has to be 0, + // __FAC1+2 (hi byte) * __FAC1+3 (lo byte) + + lda __FAC1+2 + sta INDEX+2 + lda __FAC1+3 + jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result + + // __FAC1+2 (hi byte) * __FAC1+4 (hi byte) has to be 0, // otherwise the result would be out of range // do not calculate - lda __FAC1+0 + lda __FAC1+2 beq helper_array_create_mul_success - lda __FAC1+3 + lda __FAC1+4 beq helper_array_create_mul_success // FALLTROUGH From ad521ab9113dd8c7add0b3a0beda093076336191 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 27 Jul 2020 18:01:55 +0200 Subject: [PATCH 098/130] fix for variable name recognition regression --- src/basic/engine_variables/fetch_variable_name.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basic/engine_variables/fetch_variable_name.s b/src/basic/engine_variables/fetch_variable_name.s index 74e0dbd5..a733fb1b 100644 --- a/src/basic/engine_variables/fetch_variable_name.s +++ b/src/basic/engine_variables/fetch_variable_name.s @@ -120,6 +120,7 @@ fetch_variable_name_check_array: // This is an array lda #$80 - sta DIMFLG + + clc rts From 68ea3eb314ad064b7980d228a7f204478121e018 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 27 Jul 2020 18:38:29 +0200 Subject: [PATCH 099/130] fixed bug in 16-bit multiplication --- src/basic/engine_variables/helper_array_create_mul.s | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/basic/engine_variables/helper_array_create_mul.s b/src/basic/engine_variables/helper_array_create_mul.s index b0424f44..56512725 100644 --- a/src/basic/engine_variables/helper_array_create_mul.s +++ b/src/basic/engine_variables/helper_array_create_mul.s @@ -15,7 +15,7 @@ helper_array_create_mul: // preserves .X and .Y // __FAC1+1 (lo byte) * __FAC1+3 (lo byte) lda __FAC1+1 - sta INDEX+2 + sta INDEX+3 lda __FAC1+3 jsr mul_FAC2_FAC1_8x8 // this preserves .Y @@ -25,14 +25,14 @@ helper_array_create_mul: // preserves .X and .Y // __FAC1+1 (lo byte) * __FAC1+4 (hi byte) lda __FAC1+1 - sta INDEX+2 + sta INDEX+3 lda __FAC1+4 jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result // __FAC1+2 (hi byte) * __FAC1+3 (lo byte) lda __FAC1+2 - sta INDEX+2 + sta INDEX+3 lda __FAC1+3 jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result From 8abaa6f735eba5066d38de52c3691d23f181e2a2 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 27 Jul 2020 21:41:37 +0200 Subject: [PATCH 100/130] various array creation bugfixes --- src/basic/engine_variables/array_create.s | 6 ++++-- src/basic/math/mul_FAC2_FAC1_8x8.s | 10 ++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 46026364..d40c1148 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -46,7 +46,9 @@ array_create_fetch_dims_loop: // Check if the stack has reasonable space free + phx_trash_a jsr check_stack_space + plx_trash_a // Fetch the dimension, increment it by 1, and put it on the stack; // confirmed with original ROM, that it also stores dimensions in the reverse order @@ -172,8 +174,8 @@ array_create_store_loop: array_create_store_dims_done: // Restore FOUR6, calculate number of bytes needed for storage - - pha +.break + pla sta FOUR6 // XXX do we need to store this value in FOUR6? is it still needed? sta __FAC1+3 stx __FAC1+4 // .X is 0 at this point diff --git a/src/basic/math/mul_FAC2_FAC1_8x8.s b/src/basic/math/mul_FAC2_FAC1_8x8.s index aa903e0d..bfc0730c 100644 --- a/src/basic/math/mul_FAC2_FAC1_8x8.s +++ b/src/basic/math/mul_FAC2_FAC1_8x8.s @@ -12,10 +12,16 @@ mul_FAC2_FAC1_8x8: - // Special case (optimization) - handle 0 in INDEX+2 + // Special cases - handle multiplication by 0 + + beq mul_FAC2_FAC1_8x8_zero + sta INDEX+2 + + lda INDEX+3 beq mul_FAC2_FAC1_8x8_zero - sta INDEX+2 + // Multiply INDEX+2 * INDEX+3 + lda #$00 dec INDEX+3 // decrement because we will be adding with carry set for speed (an extra one) From 2f8953c431ffd47fe7735a5f8d43c447129dc877 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 27 Jul 2020 21:56:43 +0200 Subject: [PATCH 101/130] more array format adjustments to original ROM format --- src/basic/engine_variables/array_create.s | 6 +++--- src/basic/engine_variables/helper_array_create_mul.s | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index d40c1148..bf867cc2 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -174,12 +174,12 @@ array_create_store_loop: array_create_store_dims_done: // Restore FOUR6, calculate number of bytes needed for storage -.break + pla sta FOUR6 // XXX do we need to store this value in FOUR6? is it still needed? + sta __FAC1+3 stx __FAC1+4 // .X is 0 at this point - jsr helper_array_create_mul // Check if there is enough free memory @@ -212,7 +212,7 @@ array_create_store_dims_done: // Calculate and store offset to the next array - lda #$02 + lda #$05 jsr helper_INDEX_up_A lda __FAC1+0 diff --git a/src/basic/engine_variables/helper_array_create_mul.s b/src/basic/engine_variables/helper_array_create_mul.s index 56512725..fca065b5 100644 --- a/src/basic/engine_variables/helper_array_create_mul.s +++ b/src/basic/engine_variables/helper_array_create_mul.s @@ -54,9 +54,9 @@ helper_array_create_mul_error: helper_array_create_mul_success: lda INDEX+0 - sta __FAC1+0 - lda INDEX+1 sta __FAC1+1 + lda INDEX+1 + sta __FAC1+2 plx_trash_a rts From f70fe31e0c3fbd69db5e2b958c3dff3169245986 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Mon, 27 Jul 2020 22:16:31 +0200 Subject: [PATCH 102/130] array creation routine seems complete now --- src/basic/engine_variables/array_create.s | 66 +++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index bf867cc2..867d1e89 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -169,6 +169,10 @@ array_create_store_loop: dex bne array_create_store_loop + // Store .Y in a safe place - this is the header size + + sty __FAC1+5 + // FALLTROUGH array_create_store_dims_done: @@ -241,8 +245,64 @@ array_create_store_dims_done: #endif - // Clear newly alocated area, adjust STREND + // First increase STREND past the header - // XXX implement this + clc + lda __FAC1+5 + adc STREND+0 + sta STREND+0 + bcc !+ + inc STREND+1 +!: + // Clear the newly alocated area - jmp do_NOT_IMPLEMENTED_error + ldy #$00 +#if CONFIG_MEMORY_MODEL_60K + ldx # Date: Wed, 29 Jul 2020 06:21:21 +0200 Subject: [PATCH 103/130] started work on array element location --- src/basic/engine_variables/array_create.s | 11 ++- src/basic/engine_variables/fetch_variable.s | 28 ------ .../engine_variables/fetch_variable_arr.s | 12 +++ src/basic/engine_variables/find_array.s | 89 +++++++++++++++++++ .../find_array_next_46K_50K.s | 44 +++++++++ .../helper_cmp_varnam_38K_60K.s | 34 +++++++ 6 files changed, 186 insertions(+), 32 deletions(-) create mode 100644 src/basic/engine_variables/find_array.s create mode 100644 src/basic/engine_variables/find_array_next_46K_50K.s create mode 100644 src/basic/engine_variables/helper_cmp_varnam_38K_60K.s diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index 867d1e89..a8de236a 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -10,15 +10,18 @@ array_create: jsr fetch_variable_name bcs_16 do_SYNTAX_error - // XXX check if the array already exists + // Make sure the array does not exist + + jsr find_array + bcc_16 do_REDIMD_ARRAY_error // Push variable name and FOUR6 on the stack - fetching dimensions might cause // the to be overwritten by the expression parser - lda VARNAM+0 - pha lda VARNAM+1 pha + lda VARNAM+0 + pha lda FOUR6 pha @@ -180,7 +183,7 @@ array_create_store_dims_done: // Restore FOUR6, calculate number of bytes needed for storage pla - sta FOUR6 // XXX do we need to store this value in FOUR6? is it still needed? + sta FOUR6 // needed by variable fetch routine sta __FAC1+3 stx __FAC1+4 // .X is 0 at this point diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 29957635..7333ab14 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -57,36 +57,8 @@ fetch_variable_find_addr_loop: beq fetch_variable_alocate !: // Compare current variable name with searched one - // XXX consider creating optimized version for 46K/50K memory models -#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K jsr helper_cmp_varnam -#else - - ldy #$00 - -#if CONFIG_MEMORY_MODEL_60K - ldx # Date: Wed, 29 Jul 2020 17:17:41 +0200 Subject: [PATCH 104/130] added alternative, smaller 8x8 multiplication routine --- CREDITS.md | 2 +- src/basic/math/mul_FAC2_FAC1_8x8.s | 35 +++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CREDITS.md b/CREDITS.md index c1cfb957..c1a3082a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -5,7 +5,7 @@ * Retrofan - for his Mega65 banner artwork and PXLfont * TWW/CTR - for his keyboard handling code -* Graham - for his PAL/NTSC detection routine +* Graham - for his PAL/NTSC detection code and compact 8x8 multiplication routine * enthusi/Onslaught - for his example Turbo Tape 64 compatible loader * djmips - for fast 8x8 multiplication routine * Verz - for the integer division routine diff --git a/src/basic/math/mul_FAC2_FAC1_8x8.s b/src/basic/math/mul_FAC2_FAC1_8x8.s index bfc0730c..ff06c0c2 100644 --- a/src/basic/math/mul_FAC2_FAC1_8x8.s +++ b/src/basic/math/mul_FAC2_FAC1_8x8.s @@ -3,8 +3,10 @@ // #LAYOUT# * * #IGNORE // -// Helper routine, based on code by djmips from: +// Helper routine, based on code by djmips (fast version) from: // - https://codebase64.org/doku.php?id=base:8bit_multiplication_16bit_product_fast_no_tables +// or by code by Graham (small version) from: +// - https://codebase64.org/doku.php?id=base:short_8bit_multiplication_16bit_product // // input: .A (and Zero flag set according to .A), INDEX+3 // output: .X (high byte), .A (low byte), carry always clear @@ -22,6 +24,10 @@ mul_FAC2_FAC1_8x8: // Multiply INDEX+2 * INDEX+3 +#if !HAS_SMALL_BASIC + + // Fast multiplication routine + lda #$00 dec INDEX+3 // decrement because we will be adding with carry set for speed (an extra one) @@ -71,6 +77,33 @@ mul_FAC2_FAC1_8x8: tax lda INDEX+2 +#else + + // Small multiplication routine + + lda #$00 + ldx #$08 + clc +!: + bcc !+ + clc + adc INDEX+3 +!: + ror + ror INDEX+2 + dex + bpl !-- + ldx INDEX+2 + + // Reverse return byte order, to match fast version + // (such order is easier top handle for the callers) + + stx INDEX+2 + tax + lda INDEX+2 + +#endif + clc rts From 7e5cfe9d920d5c6372917bbc9de8ff7eeb9c9d5a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 29 Jul 2020 18:01:03 +0200 Subject: [PATCH 105/130] more work towards arrays support --- src/basic/engine_runtime/check_stack_space.s | 4 + src/basic/engine_variables/array_create.s | 2 - src/basic/engine_variables/fetch_variable.s | 21 ++-- .../engine_variables/fetch_variable_arr.s | 103 +++++++++++++++++- .../engine_variables/helper_varpnt_up_A.s | 18 +++ 5 files changed, 129 insertions(+), 19 deletions(-) create mode 100644 src/basic/engine_variables/helper_varpnt_up_A.s diff --git a/src/basic/engine_runtime/check_stack_space.s b/src/basic/engine_runtime/check_stack_space.s index 2aa2d8b3..9cbd5aa1 100644 --- a/src/basic/engine_runtime/check_stack_space.s +++ b/src/basic/engine_runtime/check_stack_space.s @@ -5,8 +5,12 @@ check_stack_space: + phx_trash_a + tsx cpx #$60 // XXX is this a safe threshold? bcc_16 do_FORMULA_TOO_COMPLEX_error + plx_trash_a + rts diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index a8de236a..b8fc146a 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -49,9 +49,7 @@ array_create_fetch_dims_loop: // Check if the stack has reasonable space free - phx_trash_a jsr check_stack_space - plx_trash_a // Fetch the dimension, increment it by 1, and put it on the stack; // confirmed with original ROM, that it also stores dimensions in the reverse order diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 7333ab14..083142ba 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -69,13 +69,9 @@ fetch_variable_adjust_VARPNT: #if !HAS_OPCODES_65CE02 - clc - lda VARPNT+0 - adc #$02 - sta VARPNT+0 - bcc !+ - inc VARPNT+1 -!: + lda #$02 + jsr helper_VARPNT_up_A + #else // HAS_OPCODES_65CE02 inw VARPNT @@ -91,13 +87,10 @@ fetch_variable_find_addr_next: // Increase VARPNT by 7 - constant value, each variable uses 7 bytes, see: // - https://sites.google.com/site/h2obsession/CBM/basic/variable-format - clc - lda VARPNT+0 - adc #$07 - sta VARPNT+0 - bcc fetch_variable_find_addr_loop - inc VARPNT+1 - bne fetch_variable_find_addr_loop // branch always + lda #$07 + jsr helper_VARPNT_up_A + + jmp_8 fetch_variable_find_addr_loop fetch_variable_alocate: diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index ae47cb7d..2c4fc5a8 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -10,13 +10,110 @@ fetch_variable_arr: // Array does not exist - we will have to create one with default parameters - lda #$00 - sta VARPNT+1 + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error !: // Fetch the 'coordinates' + ldx #$00 // counts number of dimensions + + // FALLTROUGH + +fetch_variable_arr_fetch_coords_loop: + + inx + + // Check if the stack has reasonable space free + + jsr check_stack_space + + // Fetch the dimension and put it on the stack + + jsr fetch_uint16 + bcs_16 do_SYNTAX_error + + lda LINNUM+0 + pha + lda LINNUM+1 + pha + + // Check if more dimensions are given + + jsr fetch_character_skip_spaces + cmp #$2C // ',' + beq fetch_variable_arr_fetch_coords_loop + cmp #$29 // ')' + bne_16 do_SYNTAX_error + + // FALLTROUGH + +fetch_variable_arr_check_dimensions: + + // Check if the number of dimensions matches the stored ones + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + // XXX + // XXX + // XXX + +#else // CONFIG_MEMORY_MODEL_38 + + ldy #$04 + txa + cmp (VARPNT), y + +#endif + + bne_16 do_BAD_SUBSCRIPT_error + + // FALLTROUGH + +fetch_variable_arr_calc_pos: + + // Move VARPNT po point to sizes in each dimension + + lda #$05 + jsr helper_VARPNT_up_A + + // Set previous dimension size as '1' + // XXX implement this - // XXX finish the implementation + // FALLTROUGH + +fetch_variable_arr_calc_pos_loop: + + // Fetch the coordinate from stack + + // XXX implement this + + // Compare current coordinate with current dimension size + + // XXX implement this + + // Multiply current coordinate with previous dimension + + // XXX implement this + + // Store current dimension, for the next iteration + + // XXX implement this + + // Check if there are more dimensions to handle + + dex + bne fetch_variable_arr_calc_pos_loop + + // Increment VARPNT by the calculated offset and quit + + // XXX implement this jmp do_NOT_IMPLEMENTED_error diff --git a/src/basic/engine_variables/helper_varpnt_up_A.s b/src/basic/engine_variables/helper_varpnt_up_A.s new file mode 100644 index 00000000..c6238dea --- /dev/null +++ b/src/basic/engine_variables/helper_varpnt_up_A.s @@ -0,0 +1,18 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine, used by various variable-related routines +// + + +helper_VARPNT_up_A: // .A - bytes to increment VARPNT + + clc + adc VARPNT+0 + sta VARPNT+0 + bcc !+ + inc VARPNT+1 +!: + rts From 0f58b32b5bcf7646d850b37123b5bf912b28636a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Wed, 29 Jul 2020 21:59:39 +0200 Subject: [PATCH 106/130] increased BASIC_1 segment size for Mega65 to 16KB --- Makefile | 18 ++++++++---------- doc/Development.md | 2 +- src/basic/board_m65/mega65_map_helpers.s | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index ac8a7a94..498de7f4 100644 --- a/Makefile +++ b/Makefile @@ -330,7 +330,7 @@ $(DIR_M65)/OUTK_0.BIN $(DIR_M65)/KERNAL_0_combined.vs $(DIR_M65)/KERNAL_0_combin $(DIR_M65)/basic.seg_1 $(DIR_M65)/BASIC_1_combined.vs $(DIR_M65)/BASIC_1_combined.sym: @mkdir -p $(DIR_M65) @rm -f $@* $(DIR_M65)/basic.seg_1 $(DIR_M65)/BASIC_1* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s BASIC_1 -i BASIC_1-mega65 -o basic.seg_1 -d $(DIR_M65) -l 4000 -h 5fff $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_BASIC) $(GEN_BASIC) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s BASIC_1 -i BASIC_1-mega65 -o basic.seg_1 -d $(DIR_M65) -l 4000 -h 7fff $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_BASIC) $(GEN_BASIC) $(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1_combined.vs $(DIR_M65)/KERNAL_1_combined.sym: @mkdir -p $(DIR_M65) @@ -409,29 +409,27 @@ build/symbols_hybrid.vs: $(DIR_GEN)/KERNAL_combined.vs # Rules - platform 'Mega65' specific -build/padding_08_KB: - dd if=/dev/zero bs=8192 count=1 of=build/padding_08_KB +build/padding_16_KB: + @mkdir -p build + dd if=/dev/zero bs=8192 count=2 of=build/padding_16_KB build/padding_64_KB: + @mkdir -p build dd if=/dev/zero bs=8192 count=8 of=build/padding_64_KB -$(TARGET_M65_x) $(TARGET_M65_x_PXL): build/padding_08_KB build/padding_64_KB $(SEG_LIST_M65) build/chargen_openroms.rom build/chargen_openroms.patched build/chargen_pxlfont.rom build/chargen_pxlfont.patched +$(TARGET_M65_x) $(TARGET_M65_x_PXL): build/padding_16_KB build/padding_64_KB $(SEG_LIST_M65) build/chargen_openroms.rom build/chargen_openroms.patched build/chargen_pxlfont.rom build/chargen_pxlfont.patched @echo - cat build/padding_08_KB > $(TARGET_M65_x) - cat build/padding_08_KB >> $(TARGET_M65_x) + cat build/padding_16_KB > $(TARGET_M65_x) cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x) cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x) - cat build/padding_08_KB >> $(TARGET_M65_x) cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x) cat build/chargen_openroms.rom >> $(TARGET_M65_x) cat build/chargen_openroms.patched >> $(TARGET_M65_x) cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x) cat build/padding_64_KB >> $(TARGET_M65_x) @echo - cat build/padding_08_KB > $(TARGET_M65_x_PXL) - cat build/padding_08_KB >> $(TARGET_M65_x_PXL) + cat build/padding_16_KB > $(TARGET_M65_x_PXL) cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x_PXL) cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x_PXL) - cat build/padding_08_KB >> $(TARGET_M65_x_PXL) cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x_PXL) cat build/chargen_pxlfont.rom >> $(TARGET_M65_x_PXL) cat build/chargen_pxlfont.patched >> $(TARGET_M65_x_PXL) diff --git a/doc/Development.md b/doc/Development.md index fab2ca6e..29655ae6 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -97,7 +97,7 @@ List of the most important make targets: Currently there are 3 ROM layouts defined: - `STD` - with 2 code segments: `BASIC` (`$A000-$E4D2`, where `$C000-$DFFF` is a skip-gap for RAM and I/O area) and `KERNAL` (`$E4D3 - $FFFF`) -- `M65` - where `BASIC` becames `BASIC_0` and `KERNAL` becames `KERNAL_0`, additional segments might be added to the build system in the future; at the moment of writing this document additional 8KB of ROM is defined as `BASIC_1` segment and additional 8KB of ROM is defined as `KERNAL_1` segment +- `M65` - where `BASIC` becames `BASIC_0` and `KERNAL` becames `KERNAL_0`, additional segments might be added to the build system in the future; at the moment of writing this document additional 16KB of ROM is defined as `BASIC_1` segment and additional 8KB of ROM is defined as `KERNAL_1` segment - `X16` - memory layout for the Commander X16 machine To check for current ROM layout or code segment use KickAssembler preprocessor defines, like `ROM_LAYOUT_STD`, `ROM_LAYOUT_M65`, `SEGMENT_BASIC`, `SEGMENT_KERNAL_1`. diff --git a/src/basic/board_m65/mega65_map_helpers.s b/src/basic/board_m65/mega65_map_helpers.s index 73e22cdb..2ed00bff 100644 --- a/src/basic/board_m65/mega65_map_helpers.s +++ b/src/basic/board_m65/mega65_map_helpers.s @@ -23,6 +23,6 @@ map_BASIC_1: taz lda #$20 - ldx #$42 // 0x4000 <- map 8KB from 0x22000 + ldx #$C2 // 0x4000 <- map 16KB from 0x22000 jmp map_end From 2126085899baa8aef58d66fd396a5a0ae73e967e Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 30 Jul 2020 18:35:32 +0200 Subject: [PATCH 107/130] more work towards arrays --- src/basic/engine_variables/assign_variable.s | 2 + .../engine_variables/fetch_variable_arr.s | 100 +++++++++++++++--- 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 896b895b..6956affd 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -37,6 +37,8 @@ assign_variable: jsr is_var_ST beq_16 do_SYNTAX_error + // XXX add support for arrays + // Retrieve the variable address jsr fetch_variable_find_addr diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 2c4fc5a8..8c17b36e 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -16,6 +16,9 @@ fetch_variable_arr: !: // Fetch the 'coordinates' + lda FOUR6 + pha // FOUR6 might get overridden, but we'll need it + ldx #$00 // counts number of dimensions // FALLTROUGH @@ -74,6 +77,10 @@ fetch_variable_arr_check_dimensions: bne_16 do_BAD_SUBSCRIPT_error + // Store number of dimensions, will be needed later + + stx __FAC1+0 + // FALLTROUGH fetch_variable_arr_calc_pos: @@ -83,37 +90,100 @@ fetch_variable_arr_calc_pos: lda #$05 jsr helper_VARPNT_up_A - // Set previous dimension size as '1' + // Set the initial offset as '0' - // XXX implement this + lda #$00 + sta __FAC1+1 + sta __FAC1+2 // FALLTROUGH fetch_variable_arr_calc_pos_loop: - // Fetch the coordinate from stack + // Fetch the current dimension - // XXX implement this + dex + txa + asl + tay + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + // XXX + // XXX + // XXX + +#else // CONFIG_MEMORY_MODEL_38 + + lda (VARPNT), y + sta __FAC1+3 + iny + lda (VARPNT), y + sta __FAC1+4 + iny + +#endif + + // Multiply offset by current dimension + + jsr helper_array_create_mul + + // Fetch the coordinate from stack; also add it to offset + + clc + pla + sta INDEX+0 + adc __FAC1+1 + sta __FAC1+1 + pla + sta INDEX+1 + adc __FAC1+2 + sta __FAC1+2 // Compare current coordinate with current dimension size + // XXX // XXX implement this - - // Multiply current coordinate with previous dimension - - // XXX implement this - - // Store current dimension, for the next iteration - - // XXX implement this + // XXX // Check if there are more dimensions to handle - dex + cpx #$00 bne fetch_variable_arr_calc_pos_loop + // FALLTROUGH + +fetch_variable_arr_calc_pos_loop_done: + + // Retrieve FOUR6, use it to calculate final offset + + pla + sta FOUR6 // XXX is it needed? + sta __FAC1+3 + stx __FAC1+4 // .X is 0 at this moment + + jsr helper_array_create_mul + + // Increment VARPNT by number of dimensions * 2, to point start of data + + lda __FAC1+0 + asl + jsr helper_VARPNT_up_A + // Increment VARPNT by the calculated offset and quit - // XXX implement this + clc + lda __FAC1+1 + adc VARPNT+0 + sta VARPNT+0 + lda __FAC1+2 + adc VARPNT+1 + sta VARPNT+1 - jmp do_NOT_IMPLEMENTED_error + rts From 461e6e0b84d74dd1a347dfdce9b02ef25678207f Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 30 Jul 2020 22:19:37 +0200 Subject: [PATCH 108/130] fixed memory corruption in case of garbage collection during assignment --- src/basic/engine_variables/assign_variable.s | 42 +++++++++----------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 6956affd..0328ee66 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -37,13 +37,30 @@ assign_variable: jsr is_var_ST beq_16 do_SYNTAX_error - // XXX add support for arrays + // Push the VARNAM to the stack - it might get overridden + + lda VARNAM+0 + pha + lda VARNAM+1 + pha + + // Evaluate the expression + + jsr FRMEVL + + // Restore VARNAM + + pla + sta VARNAM+1 + pla + sta VARNAM+0 // Retrieve the variable address + // XXX add support for arrays jsr fetch_variable_find_addr - // Determine variable type and push it to the stack + // Determine variable type lda #$00 clc @@ -55,29 +72,8 @@ assign_variable: bpl !+ adc #$80 !: - pha - - // Push the VARPNT to the stack - it might get overridden - - lda VARPNT+0 - pha - lda VARPNT+1 - pha - - // Evaluate the expression - - jsr FRMEVL - - // Restore VARPNT - - pla - sta VARPNT+1 - pla - sta VARPNT+0 - // Determine what to assign - pla bmi assign_string beq assign_float From 0e8cb413ed9c197a0d96fc73b9c763de9dc914f3 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 30 Jul 2020 22:26:03 +0200 Subject: [PATCH 109/130] fix problem with comparing variable types --- src/basic/basic_operators/oper_add.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index 52124a25..e663af97 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -9,8 +9,8 @@ oper_add: // First check whether arguments match and then choose the variant pla - cmp VALTYP - bne_16 do_TYPE_MISMATCH_error + eor VALTYP + bmi_16 do_TYPE_MISMATCH_error lda VALTYP bmi oper_add_strings From 07674b4e23cb9b5b2c0394a24496480e928accb2 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Thu, 30 Jul 2020 22:54:00 +0200 Subject: [PATCH 110/130] tokenizer speedup in some cases --- src/basic/engine_editor/tk_pack.s | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/basic/engine_editor/tk_pack.s b/src/basic/engine_editor/tk_pack.s index 26114fde..25c9cae9 100644 --- a/src/basic/engine_editor/tk_pack.s +++ b/src/basic/engine_editor/tk_pack.s @@ -142,8 +142,14 @@ tk_pack_loop_next: lda tk__len_unpacked cmp #TK__MAX_KEYWORD_LEN - bne tk_pack_loop + beq !+ // if max length reached - quit + // Check for characters that can only end the token + + lda BUF-1, x + cmp #$41 + bcs tk_pack_loop +!: rts tk_pack_1n_new_byte: From dd85061c479db2acf6c0d9d86bc575745f074710 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 31 Jul 2020 16:48:35 +0200 Subject: [PATCH 111/130] code size optimization in BASIC --- src/basic/engine_editor/tk_pack.s | 2 +- src/basic/engine_runtime/injest_assign.s | 17 +----- src/basic/engine_variables/array_create.s | 12 +---- src/basic/engine_variables/assign_variable.s | 52 +++++++++++++------ .../engine_variables/fetch_variable_arr.s | 16 ++---- .../engine_variables/helper_fetch_arr_coord.s | 42 +++++++++++++++ 6 files changed, 86 insertions(+), 55 deletions(-) create mode 100644 src/basic/engine_variables/helper_fetch_arr_coord.s diff --git a/src/basic/engine_editor/tk_pack.s b/src/basic/engine_editor/tk_pack.s index 25c9cae9..56d3db31 100644 --- a/src/basic/engine_editor/tk_pack.s +++ b/src/basic/engine_editor/tk_pack.s @@ -144,7 +144,7 @@ tk_pack_loop_next: cmp #TK__MAX_KEYWORD_LEN beq !+ // if max length reached - quit - // Check for characters that can only end the token + // Check for characters that can only end the keyword lda BUF-1, x cmp #$41 diff --git a/src/basic/engine_runtime/injest_assign.s b/src/basic/engine_runtime/injest_assign.s index efc9bea0..56456299 100644 --- a/src/basic/engine_runtime/injest_assign.s +++ b/src/basic/engine_runtime/injest_assign.s @@ -3,7 +3,7 @@ // #LAYOUT# * * #IGNORE // -// Consummes assign operator in a BASIC code, Carry set if not found. Injests all spaces. +// Consummes assign operator in a BASIC code, triggers error if not found // @@ -11,19 +11,6 @@ injest_assign: jsr fetch_character_skip_spaces cmp #$B2 // assign operator character - beq injest_assign_found - - // Not found -#if !HAS_OPCODES_65CE02 - jsr unconsume_character -#else - dew TXTPTR -#endif + bne_16 do_SYNTAX_error - sec - rts - -injest_assign_found: - - clc rts diff --git a/src/basic/engine_variables/array_create.s b/src/basic/engine_variables/array_create.s index b8fc146a..15a0f982 100644 --- a/src/basic/engine_variables/array_create.s +++ b/src/basic/engine_variables/array_create.s @@ -47,15 +47,10 @@ array_create_fetch_dims_loop: inx - // Check if the stack has reasonable space free - - jsr check_stack_space - // Fetch the dimension, increment it by 1, and put it on the stack; // confirmed with original ROM, that it also stores dimensions in the reverse order - jsr fetch_uint16 - bcs_16 do_SYNTAX_error + jsr helper_fetch_arr_coord #if !HAS_OPCODES_65CE02 inc LINNUM+0 @@ -75,11 +70,8 @@ array_create_fetch_dims_loop: // Check if more dimensions are given - jsr fetch_character_skip_spaces - cmp #$2C // ',' + cpy #$00 beq array_create_fetch_dims_loop - cmp #$29 // ')' - bne_16 do_SYNTAX_error // FALLTROUGH diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 0328ee66..fdf4fb72 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -5,26 +5,35 @@ assign_variable: - // Fetch variable name, should be followed by assign operator + // Fetch variable/array name jsr fetch_variable_name - -#if HAS_OPCODES_65CE02 - - bcs_16 do_SYNTAX_error - jsr injest_assign bcs_16 do_SYNTAX_error -#else - - bcs !+ jsr injest_assign - bcc !++ -!: - jmp do_SYNTAX_error -!: -#endif + // Check for array + + lda DIMFLG + bpl assign_variable_not_array + + // Retrieve all the dimensions + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error + + // Fetch assignment operator and continue + + jsr injest_assign + + jmp_8 assign_variable_common + +assign_variable_not_array: + + // Require assignment operator + + jsr injest_assign // Check for special variables @@ -37,8 +46,14 @@ assign_variable: jsr is_var_ST beq_16 do_SYNTAX_error - // Push the VARNAM to the stack - it might get overridden + // FALLTROUGH +assign_variable_common: + + // Push the DIMFLG and VARNAM to the stack - it might get overridden + + lda DIMFLG + pha lda VARNAM+0 pha lda VARNAM+1 @@ -48,15 +63,18 @@ assign_variable: jsr FRMEVL - // Restore VARNAM + // Restore VARNAM and DIMFLG pla sta VARNAM+1 pla sta VARNAM+0 + pla + sta DIMFLG // XXX is it needed? + + // XXX add array handling here // Retrieve the variable address - // XXX add support for arrays jsr fetch_variable_find_addr diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 8c17b36e..32a2ae10 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -27,27 +27,19 @@ fetch_variable_arr_fetch_coords_loop: inx - // Check if the stack has reasonable space free + // Fetch the coordinate and put it on the stack - jsr check_stack_space - - // Fetch the dimension and put it on the stack - - jsr fetch_uint16 - bcs_16 do_SYNTAX_error + jsr helper_fetch_arr_coord lda LINNUM+0 pha lda LINNUM+1 pha - // Check if more dimensions are given + // If more coordinates given - next iteration - jsr fetch_character_skip_spaces - cmp #$2C // ',' + cpy #$00 beq fetch_variable_arr_fetch_coords_loop - cmp #$29 // ')' - bne_16 do_SYNTAX_error // FALLTROUGH diff --git a/src/basic/engine_variables/helper_fetch_arr_coord.s b/src/basic/engine_variables/helper_fetch_arr_coord.s new file mode 100644 index 00000000..6329fbde --- /dev/null +++ b/src/basic/engine_variables/helper_fetch_arr_coord.s @@ -0,0 +1,42 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine for fetching array coordinates +// +// If this was last coordinate, set .Y to $FF, otherwise to $00 +// + +helper_fetch_arr_coord: + + // Check if the stack has reasonable space free + + jsr check_stack_space + + // Fetch the dimension + + jsr fetch_uint16 + bcs !+ + + jsr fetch_character_skip_spaces + cmp #$2C // ',' + beq helper_fetch_arr_more + cmp #$29 // ')' + beq helper_fetch_arr_last + + // FALLTROUGH + +!: + + jmp do_SYNTAX_error + +helper_fetch_arr_more: + + ldy #$00 + rts + +helper_fetch_arr_last: + + ldy #$FF + rts From 2c0e9e9511cf235f83c8cc11b2a7f8e10172bcfb Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Fri, 31 Jul 2020 17:02:43 +0200 Subject: [PATCH 112/130] flag handling cleanup --- src/basic/engine_variables/assign_variable.s | 53 +++++++++++++++---- .../engine_variables/fetch_variable_name.s | 6 +-- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index fdf4fb72..e593457d 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -15,21 +15,37 @@ assign_variable: // Check for array lda DIMFLG - bpl assign_variable_not_array + bpl assign_variable_not_array_1 - // Retrieve all the dimensions + // Retrieve all the coordinates - // XXX implement this + ldx #$00 +!: + inx + jsr helper_fetch_arr_coord - jmp do_NOT_IMPLEMENTED_error + lda LINNUM+0 + pha + lda LINNUM+1 + pha + + // Check if more dimensions are given + + cpy #$00 + beq !+ + + // Push number of dimensions to stack + + phx_trash_a // Fetch assignment operator and continue jsr injest_assign - jmp_8 assign_variable_common + lda #$FF // force DIMFLG to be array + jmp_8 assign_variable_common_1 -assign_variable_not_array: +assign_variable_not_array_1: // Require assignment operator @@ -46,13 +62,14 @@ assign_variable_not_array: jsr is_var_ST beq_16 do_SYNTAX_error - // FALLTROUGH - -assign_variable_common: - // Push the DIMFLG and VARNAM to the stack - it might get overridden lda DIMFLG + + // FALLTROUGH + +assign_variable_common_1: + pha lda VARNAM+0 pha @@ -72,12 +89,28 @@ assign_variable_common: pla sta DIMFLG // XXX is it needed? + // Check if array + + bpl assign_variable_not_array_2 + + // // XXX add array handling here + // + + jmp do_NOT_IMPLEMENTED_error + + jmp_8 assign_variable_common_2 + +assign_variable_not_array_2: // Retrieve the variable address jsr fetch_variable_find_addr + // FALLTROUGH + +assign_variable_common_2: + // Determine variable type lda #$00 diff --git a/src/basic/engine_variables/fetch_variable_name.s b/src/basic/engine_variables/fetch_variable_name.s index a733fb1b..667c1436 100644 --- a/src/basic/engine_variables/fetch_variable_name.s +++ b/src/basic/engine_variables/fetch_variable_name.s @@ -4,7 +4,7 @@ // // Carry set = failure, not recognized variable name -// sets FOUR6 and DIMFLG ($80 for array, $00 for regular variable) +// sets FOUR6 and DIMFLG ($FF for array, $00 for regular variable) fetch_variable_name: @@ -89,7 +89,7 @@ fetch_variable_type_integer: fetch_variable_type_string: ldy #$03 - lda #$80 + lda #$FF !: sta VALTYP sty FOUR6 @@ -119,7 +119,7 @@ fetch_variable_name_check_array: !: // This is an array - lda #$80 + lda #$FF sta DIMFLG clc From 60e2bc5299e83d627b38299f977cba212daa0cee Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 12:50:27 +0200 Subject: [PATCH 113/130] various array related fixes --- src/basic/engine_variables/assign_variable.s | 22 +++++++++++-------- .../engine_variables/fetch_variable_arr.s | 8 +++---- .../engine_variables/helper_fetch_arr_coord.s | 2 -- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index e593457d..d3508295 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -10,14 +10,15 @@ assign_variable: jsr fetch_variable_name bcs_16 do_SYNTAX_error - jsr injest_assign - // Check for array lda DIMFLG bpl assign_variable_not_array_1 - // Retrieve all the coordinates + // This is an array - store FOUR6 on the stack, retrieve all the coordinates + + lda FOUR6 + pha ldx #$00 !: @@ -32,9 +33,9 @@ assign_variable: // Check if more dimensions are given cpy #$00 - beq !+ + beq !- - // Push number of dimensions to stack + // Store number of dimensions on the stack phx_trash_a @@ -93,12 +94,15 @@ assign_variable_common_1: bpl assign_variable_not_array_2 - // - // XXX add array handling here - // + // Yes, this is an array - fetch the number of dimensions - jmp do_NOT_IMPLEMENTED_error + pla + sta __FAC1+0 + tax + // Fetch the address of the variable +.break + jsr fetch_variable_arr_calc_pos jmp_8 assign_variable_common_2 assign_variable_not_array_2: diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 32a2ae10..ede9f16c 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -41,6 +41,10 @@ fetch_variable_arr_fetch_coords_loop: cpy #$00 beq fetch_variable_arr_fetch_coords_loop + // Store number of dimensions, will be needed later + + stx __FAC1+0 + // FALLTROUGH fetch_variable_arr_check_dimensions: @@ -69,10 +73,6 @@ fetch_variable_arr_check_dimensions: bne_16 do_BAD_SUBSCRIPT_error - // Store number of dimensions, will be needed later - - stx __FAC1+0 - // FALLTROUGH fetch_variable_arr_calc_pos: diff --git a/src/basic/engine_variables/helper_fetch_arr_coord.s b/src/basic/engine_variables/helper_fetch_arr_coord.s index 6329fbde..364b69ee 100644 --- a/src/basic/engine_variables/helper_fetch_arr_coord.s +++ b/src/basic/engine_variables/helper_fetch_arr_coord.s @@ -26,9 +26,7 @@ helper_fetch_arr_coord: beq helper_fetch_arr_last // FALLTROUGH - !: - jmp do_SYNTAX_error helper_fetch_arr_more: From 73553362b647c4c4f34c56caff26103195bcab46 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 13:40:09 +0200 Subject: [PATCH 114/130] more fixes to string array support --- src/basic/engine_variables/assign_variable.s | 18 +++++++++++++----- .../engine_variables/fetch_variable_arr.s | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index d3508295..19786541 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -15,11 +15,20 @@ assign_variable: lda DIMFLG bpl assign_variable_not_array_1 - // This is an array - store FOUR6 on the stack, retrieve all the coordinates + // This is an array - push return address to the stack, will be needed later + + lda #>(assign_variable_common_2-1) + pha + lda #<(assign_variable_common_2-1) + pha + + // Store FOUR6 on tha stack lda FOUR6 pha + // Retruieve all the coordinates + ldx #$00 !: inx @@ -101,9 +110,8 @@ assign_variable_common_1: tax // Fetch the address of the variable -.break - jsr fetch_variable_arr_calc_pos - jmp_8 assign_variable_common_2 + + jmp fetch_variable_arr_calc_pos // RTS goes to assign_variable_common_2 assign_variable_not_array_2: @@ -193,7 +201,7 @@ assign_float: jmp do_NOT_IMPLEMENTED_error assign_string: - +.break // Check if value type matches lda VALTYP diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index ede9f16c..3e1c6e70 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -156,6 +156,7 @@ fetch_variable_arr_calc_pos_loop_done: // Retrieve FOUR6, use it to calculate final offset pla + sta FOUR6 // XXX is it needed? sta __FAC1+3 stx __FAC1+4 // .X is 0 at this moment From 64e18985394e683996d56408e7f9ed4113496b4c Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 13:59:11 +0200 Subject: [PATCH 115/130] more work towards array support --- src/basic/engine_variables/assign_variable.s | 29 +++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 19786541..66b1c026 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -17,9 +17,9 @@ assign_variable: // This is an array - push return address to the stack, will be needed later - lda #>(assign_variable_common_2-1) + lda #>(assign_variable_arr_ret-1) pha - lda #<(assign_variable_common_2-1) + lda #<(assign_variable_arr_ret-1) pha // Store FOUR6 on tha stack @@ -103,6 +103,15 @@ assign_variable_common_1: bpl assign_variable_not_array_2 + // Preserve FAC1 values which might get overwritten + + ldx #$04 +!: + lda __FAC1,x + sta __FAC2,x + dex + bpl !- + // Yes, this is an array - fetch the number of dimensions pla @@ -111,7 +120,19 @@ assign_variable_common_1: // Fetch the address of the variable - jmp fetch_variable_arr_calc_pos // RTS goes to assign_variable_common_2 + jmp fetch_variable_arr_calc_pos // RTS goes to assign_variable_arr_ret + +assign_variable_arr_ret: + + // Restore FAC1 values + + ldx #$04 +!: + lda __FAC2,x + sta __FAC1,x + dex + bpl !- + bmi assign_variable_common_2 // branch always assign_variable_not_array_2: @@ -201,7 +222,7 @@ assign_float: jmp do_NOT_IMPLEMENTED_error assign_string: -.break + // Check if value type matches lda VALTYP From b047c456b143bfaf8b414c37cbfa385be7c0547c Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 15:20:31 +0200 Subject: [PATCH 116/130] assigning value to array element works now --- src/basic/engine_variables/assign_variable.s | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 66b1c026..da5bcf0a 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -27,7 +27,7 @@ assign_variable: lda FOUR6 pha - // Retruieve all the coordinates + // Retrieve all the coordinates ldx #$00 !: @@ -103,7 +103,7 @@ assign_variable_common_1: bpl assign_variable_not_array_2 - // Preserve FAC1 values which might get overwritten + // Yes, this is an array - preserve FAC1 values which might get overwritten ldx #$04 !: @@ -112,7 +112,11 @@ assign_variable_common_1: dex bpl !- - // Yes, this is an array - fetch the number of dimensions + // Get array address + + jsr find_array + + // Fetch the number of dimensions pla sta __FAC1+0 From 0d903a8c1627ecf47a385403b7998946c9627484 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 16:52:24 +0200 Subject: [PATCH 117/130] implemented some missing parts for 46K/50K/60K memory models --- src/basic/engine_variables/assign_variable.s | 7 ++++ .../engine_variables/fetch_variable_arr.s | 15 +++++---- .../helper_array_fetch_dimension_46K_50K.s | 32 +++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 src/basic/engine_variables/helper_array_fetch_dimension_46K_50K.s diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index da5bcf0a..be28c998 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -115,7 +115,14 @@ assign_variable_common_1: // Get array address jsr find_array + bcc !+ + // Array does not exist - we will have to create one with default parameters + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error +!: // Fetch the number of dimensions pla diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 3e1c6e70..f577eaf6 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -101,15 +101,18 @@ fetch_variable_arr_calc_pos_loop: #if CONFIG_MEMORY_MODEL_60K - // XXX - // XXX - // XXX + ldx # Date: Sat, 1 Aug 2020 19:07:25 +0200 Subject: [PATCH 118/130] fix for multidimensional arrays --- src/basic/engine_variables/assign_variable.s | 4 ++-- src/basic/engine_variables/fetch_variable_arr.s | 12 ++++++------ .../helper_array_fetch_dimension_46K_50K.s | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index be28c998..64f047aa 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -34,10 +34,10 @@ assign_variable: inx jsr helper_fetch_arr_coord - lda LINNUM+0 - pha lda LINNUM+1 pha + lda LINNUM+0 + pha // Check if more dimensions are given diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index f577eaf6..45228114 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -31,10 +31,10 @@ fetch_variable_arr_fetch_coords_loop: jsr helper_fetch_arr_coord - lda LINNUM+0 - pha lda LINNUM+1 pha + lda LINNUM+0 + pha // If more coordinates given - next iteration @@ -104,10 +104,10 @@ fetch_variable_arr_calc_pos_loop: ldx # Date: Sat, 1 Aug 2020 20:04:37 +0200 Subject: [PATCH 119/130] added array index range check --- .../engine_variables/fetch_variable_arr.s | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 45228114..9a574668 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -71,7 +71,7 @@ fetch_variable_arr_check_dimensions: #endif - bne_16 do_BAD_SUBSCRIPT_error + bne fetch_variable_arr_bad_subscript // FALLTROUGH @@ -94,6 +94,10 @@ fetch_variable_arr_calc_pos_loop: // Fetch the current dimension + // XXX + // XXX there is a bug, it should fetch from the opposite size! + // XXX + dex txa asl @@ -141,12 +145,17 @@ fetch_variable_arr_calc_pos_loop: adc __FAC1+2 sta __FAC1+2 - // Compare current coordinate with current dimension size + // Compare current coordinate (INDEX+0/+1) with current dimension size (__FAC1+3/+4) - // XXX - // XXX implement this - // XXX + lda INDEX+1 + cmp __FAC1+4 + bcc !+ + bne fetch_variable_arr_bad_subscript + lda INDEX+0 + cmp __FAC1+3 + bcs fetch_variable_arr_bad_subscript +!: // Check if there are more dimensions to handle cpx #$00 @@ -183,3 +192,7 @@ fetch_variable_arr_calc_pos_loop_done: sta VARPNT+1 rts + +fetch_variable_arr_bad_subscript: + + jmp do_BAD_SUBSCRIPT_error From c5a16a9a854940683630bc3a0c4c736451550887 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 20:11:57 +0200 Subject: [PATCH 120/130] one more multidimensional array fix --- src/basic/engine_variables/fetch_variable.s | 6 +++--- src/basic/engine_variables/fetch_variable_arr.s | 14 ++++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 083142ba..1fecbc28 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -120,20 +120,20 @@ fetch_variable_alocate_space_OK: #if CONFIG_MEMORY_MODEL_60K - // XXX + // XXX! // XXX: implement this for arrays // XXX #elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K // XXX consider optimized version without multiple JSRs - // XXX + // XXX! // XXX: implement this for arrays // XXX #else // CONFIG_MEMORY_MODEL_38K - // XXX + // XXX! // XXX: implement this for arrays // XXX diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 9a574668..61271f6a 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -53,13 +53,13 @@ fetch_variable_arr_check_dimensions: #if CONFIG_MEMORY_MODEL_60K - // XXX + // XXX! // XXX // XXX #elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX + // XXX! // XXX // XXX @@ -88,18 +88,16 @@ fetch_variable_arr_calc_pos: sta __FAC1+1 sta __FAC1+2 + ldx #$00 + // FALLTROUGH fetch_variable_arr_calc_pos_loop: // Fetch the current dimension - // XXX - // XXX there is a bug, it should fetch from the opposite size! - // XXX - - dex txa + inx asl tay @@ -158,7 +156,7 @@ fetch_variable_arr_calc_pos_loop: !: // Check if there are more dimensions to handle - cpx #$00 + cpx __FAC1+0 bne fetch_variable_arr_calc_pos_loop // FALLTROUGH From 2f4d50454c1ddc30a610d2cb81fa8d5058c20350 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sat, 1 Aug 2020 21:39:12 +0200 Subject: [PATCH 121/130] added more array-related 46K/50K/60K code --- .../engine_variables/fetch_variable_arr.s | 14 +++++----- .../helper_array_check_no_dims_46K_50K.s | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 src/basic/engine_variables/helper_array_check_no_dims_46K_50K.s diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index 61271f6a..b2952ecf 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -53,15 +53,17 @@ fetch_variable_arr_check_dimensions: #if CONFIG_MEMORY_MODEL_60K - // XXX! - // XXX - // XXX + phx_trash_a + ldx # Date: Sat, 1 Aug 2020 22:12:47 +0200 Subject: [PATCH 122/130] added code to move array area, if needed --- src/basic/engine_variables/assign_variable.s | 2 + src/basic/engine_variables/fetch_variable.s | 42 +++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/basic/engine_variables/assign_variable.s b/src/basic/engine_variables/assign_variable.s index 64f047aa..f052869e 100644 --- a/src/basic/engine_variables/assign_variable.s +++ b/src/basic/engine_variables/assign_variable.s @@ -104,6 +104,7 @@ assign_variable_common_1: bpl assign_variable_not_array_2 // Yes, this is an array - preserve FAC1 values which might get overwritten + // XXX adapt this for floats! ldx #$04 !: @@ -136,6 +137,7 @@ assign_variable_common_1: assign_variable_arr_ret: // Restore FAC1 values + // XXX adapt this for floats! ldx #$04 !: diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 1fecbc28..edb8d0dc 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -116,7 +116,43 @@ fetch_variable_alocate: fetch_variable_alocate_space_OK: - // If needed, move all the arrays up + // If arrays exist, we need to move them upwards + + sec + lda STREND+0 + sta memmove__src+0 + sbc ARYTAB+0 + sta memmove__size+0 + lda STREND+1 + sta memmove__src+1 + sbc ARYTAB+1 + sta memmove__size+1 + + ora memmove__size+0 + beq fetch_variable_alocate_adjust_vars + + // Indeed, there are arrays - adjust size, calculate the destination and perform copytin + +#if !HAS_OPCODES_65CE02 + inc memmove__size+0 + bne !+ + inc memmove__size+1 +!: +#else // HAS_OPCODES_65CE02 + inw memmove__size +#endif + + clc + lda memmove__src+0 + adc #$07 + sta memmove__dst+0 + lda memmove__src+1 + adc #$00 + sta memmove__dst+1 + + jsr shift_mem_up + + // Now, we need to recreate the back-pointers #if CONFIG_MEMORY_MODEL_60K @@ -139,6 +175,10 @@ fetch_variable_alocate_space_OK: #endif + // FALLTROUGH + +fetch_variable_alocate_adjust_vars: + // Adjust ARYTAB and STREND clc From 1682cc8934f6248ca4db0f061dca706e8794fc81 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 12:05:34 +0200 Subject: [PATCH 123/130] started work on backpointer refresh --- src/basic/engine_variables/fetch_variable.s | 34 ++--- .../helper_array_refresh_bptrs.s | 122 ++++++++++++++++++ 2 files changed, 132 insertions(+), 24 deletions(-) create mode 100644 src/basic/engine_variables/helper_array_refresh_bptrs.s diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index edb8d0dc..7678a458 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -152,29 +152,6 @@ fetch_variable_alocate_space_OK: jsr shift_mem_up - // Now, we need to recreate the back-pointers - -#if CONFIG_MEMORY_MODEL_60K - - // XXX! - // XXX: implement this for arrays - // XXX - -#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - // XXX consider optimized version without multiple JSRs - - // XXX! - // XXX: implement this for arrays - // XXX - -#else // CONFIG_MEMORY_MODEL_38K - - // XXX! - // XXX: implement this for arrays - // XXX - -#endif - // FALLTROUGH fetch_variable_alocate_adjust_vars: @@ -198,7 +175,16 @@ fetch_variable_alocate_adjust_vars: !: // VARPNT already points to the start of the variable descriptor - // Fill-in the new variable name, descriptor (it is enough to zero first 2 bytes of content) + // We need to recreate the back-pointers to string arrays + + lda ARYTAB+0 + sta INDEX+0 + lda ARYTAB+1 + sta INDEX+1 + + jsr helper_array_refresh_bptrs + + // Fill-in the new variable name and descriptor (it is enough to zero first 2 bytes of content) ldy #$00 diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs.s b/src/basic/engine_variables/helper_array_refresh_bptrs.s new file mode 100644 index 00000000..3473d866 --- /dev/null +++ b/src/basic/engine_variables/helper_array_refresh_bptrs.s @@ -0,0 +1,122 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Refresh back-pointer to arrays +// + + +#if CONFIG_MEMORY_MODEL_38K // XXX! create versions for other memory models + +helper_array_refresh_bptrs: + + // Refresh back-pointers to arrays + + lda ARYTAB+0 + sta INDEX+0 + lda ARYTAB+1 + sta INDEX+1 + + // FALLTROUGH + +helper_array_refresh_bptrs_loop_1: + + // Check if we reached end of arays + + lda INDEX+1 + cmp STREND+1 + bne !+ + lda INDEX+0 + cmp STREND+0 + beq helper_array_refresh_bptrs_end +!: + // Calculate start address of the next array, store it in INDEX+2/+3 + + ldy #$02 + + lda (INDEX+0), y // XXX + clc + adc INDEX+0 + sta INDEX+2 + iny + lda (INDEX+0), y // XXX + adc INDEX+1 + sta INDEX+3 + + // Check if the current array is a string - if not, go to next array + + ldy #$00 + lda (INDEX+0), y // XXX + bmi helper_array_refresh_bptrs_loop_next + iny + lda (INDEX+0), y // XXX + bpl helper_array_refresh_bptrs_loop_next + + // It's a string array - scroll INDEX+0/+1 to the first descriptor + + ldy #$04 + lda (INDEX+0), y // XXX + asl + clc + adc #$05 + jsr helper_INDEX_up_A + + // FALLTROUGH + +helper_array_refresh_bptrs_loop_2: + + // Recreate the back-pointer + + ldy #$00 + lda (INDEX+0), y // XXX + beq helper_array_refresh_bptrs_skip // skip empty strings + + iny + clc + adc (INDEX+0), y // XXX + sta INDEX+4 + iny + lda #$00 + adc (INDEX+0), y // XXX + sta INDEX+5 + + ldy #$00 + lda INDEX+0 + sta (INDEX+4), y // XXX + iny + lda INDEX+1 + sta (INDEX+4), y // XXX + + // FALLTROUGH + +helper_array_refresh_bptrs_skip: + + // Shift INDEX+0/+1 to the next string + + lda #$03 + jsr helper_INDEX_up_A + + // Check if this is the last string of the array + + lda INDEX+0 + cmp INDEX+2 + bne helper_array_refresh_bptrs_loop_2 + lda INDEX+1 + cmp INDEX+3 + bne helper_array_refresh_bptrs_loop_2 + +helper_array_refresh_bptrs_loop_next: + + lda INDEX+3 + sta INDEX+1 + lda INDEX+2 + sta INDEX+0 + + jmp_8 helper_array_refresh_bptrs_loop_1 + +helper_array_refresh_bptrs_end: + + rts + +#endif From dcbe9d6c5eb0f3f4333c9f368f4cc2d232406cd4 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 12:21:50 +0200 Subject: [PATCH 124/130] added backpointer rewrite for memory models 46K/50K --- src/basic/engine_variables/fetch_variable.s | 5 -- .../helper_array_refresh_bptrs.s | 32 +++++++++--- ...helper_array_refresh_bptrs_part1_46K_50K.s | 51 +++++++++++++++++++ ...helper_array_refresh_bptrs_part2_46K_50K.s | 43 ++++++++++++++++ 4 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 src/basic/engine_variables/helper_array_refresh_bptrs_part1_46K_50K.s create mode 100644 src/basic/engine_variables/helper_array_refresh_bptrs_part2_46K_50K.s diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 7678a458..89e40bd1 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -177,11 +177,6 @@ fetch_variable_alocate_adjust_vars: // We need to recreate the back-pointers to string arrays - lda ARYTAB+0 - sta INDEX+0 - lda ARYTAB+1 - sta INDEX+1 - jsr helper_array_refresh_bptrs // Fill-in the new variable name and descriptor (it is enough to zero first 2 bytes of content) diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs.s b/src/basic/engine_variables/helper_array_refresh_bptrs.s index 3473d866..20882012 100644 --- a/src/basic/engine_variables/helper_array_refresh_bptrs.s +++ b/src/basic/engine_variables/helper_array_refresh_bptrs.s @@ -6,9 +6,6 @@ // Refresh back-pointer to arrays // - -#if CONFIG_MEMORY_MODEL_38K // XXX! create versions for other memory models - helper_array_refresh_bptrs: // Refresh back-pointers to arrays @@ -33,6 +30,17 @@ helper_array_refresh_bptrs_loop_1: !: // Calculate start address of the next array, store it in INDEX+2/+3 +#if CONFIG_MEMORY_MODEL_60K + + // XXX! + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + jsr helper_array_refresh_bptrs_part1 + bcs helper_array_refresh_bptrs_loop_next + +#else // CONFIG_MEMORY_MODEL_38K + ldy #$02 lda (INDEX+0), y // XXX @@ -62,15 +70,27 @@ helper_array_refresh_bptrs_loop_1: adc #$05 jsr helper_INDEX_up_A +#endif + // FALLTROUGH helper_array_refresh_bptrs_loop_2: // Recreate the back-pointer +#if CONFIG_MEMORY_MODEL_60K + + // XXX! + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + jsr helper_array_refresh_bptrs_part2 + +#else // CONFIG_MEMORY_MODEL_38K + ldy #$00 lda (INDEX+0), y // XXX - beq helper_array_refresh_bptrs_skip // skip empty strings + beq !+ // skip empty strings iny clc @@ -87,6 +107,8 @@ helper_array_refresh_bptrs_loop_2: iny lda INDEX+1 sta (INDEX+4), y // XXX +!: +#endif // FALLTROUGH @@ -118,5 +140,3 @@ helper_array_refresh_bptrs_loop_next: helper_array_refresh_bptrs_end: rts - -#endif diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs_part1_46K_50K.s b/src/basic/engine_variables/helper_array_refresh_bptrs_part1_46K_50K.s new file mode 100644 index 00000000..46b7e048 --- /dev/null +++ b/src/basic/engine_variables/helper_array_refresh_bptrs_part1_46K_50K.s @@ -0,0 +1,51 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_array_refresh_bptrs_part1: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Calculate start address of the next array, store it in INDEX+2/+3 + + ldy #$02 + + lda (INDEX+0), y // XXX + clc + adc INDEX+0 + sta INDEX+2 + iny + lda (INDEX+0), y // XXX + adc INDEX+1 + sta INDEX+3 + + // Check if the current array is a string - if not, go to next array + + ldy #$00 + lda (INDEX+0), y // XXX + bmi_16 remap_BASIC_sec_rts + iny + lda (INDEX+0), y // XXX + bpl_16 remap_BASIC_sec_rts + + // It's a string array - scroll INDEX+0/+1 to the first descriptor + + ldy #$04 + lda (INDEX+0), y // XXX + asl + clc + adc #$05 + jsr helper_INDEX_up_A +!: + // Restore default memory mapping + + jmp remap_BASIC_clc_rts + +#endif diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs_part2_46K_50K.s b/src/basic/engine_variables/helper_array_refresh_bptrs_part2_46K_50K.s new file mode 100644 index 00000000..d37c7d4b --- /dev/null +++ b/src/basic/engine_variables/helper_array_refresh_bptrs_part2_46K_50K.s @@ -0,0 +1,43 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_array_refresh_bptrs_part2: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Write new back-pointer + + ldy #$00 + lda (INDEX+0), y + beq !+ + + iny + clc + adc (INDEX+0), y + sta INDEX+4 + iny + lda #$00 + adc (INDEX+0), y + sta INDEX+5 + + ldy #$00 + lda INDEX+0 + sta (INDEX+4), y + iny + lda INDEX+1 + sta (INDEX+4), y + +!: + // Restore default memory mapping + + jmp remap_BASIC + +#endif From 37e28398dc48478ed9e03018795172f21d7e5ec5 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 14:09:39 +0200 Subject: [PATCH 125/130] fixed regression with array element position calculation --- src/basic/engine_variables/fetch_variable_arr.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/basic/engine_variables/fetch_variable_arr.s b/src/basic/engine_variables/fetch_variable_arr.s index b2952ecf..3c19bbc4 100644 --- a/src/basic/engine_variables/fetch_variable_arr.s +++ b/src/basic/engine_variables/fetch_variable_arr.s @@ -171,7 +171,8 @@ fetch_variable_arr_calc_pos_loop_done: sta FOUR6 // XXX is it needed? sta __FAC1+3 - stx __FAC1+4 // .X is 0 at this moment + lda #$00 + sta __FAC1+4 // .X is 0 at this moment jsr helper_array_create_mul From 153e17689a07419f3c72bd2459064ff25a585a5a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 14:18:40 +0200 Subject: [PATCH 126/130] fixed some Mega65 compilation problems --- src/basic/engine_variables/fetch_variable.s | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index 89e40bd1..d5af69d3 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -133,14 +133,9 @@ fetch_variable_alocate_space_OK: // Indeed, there are arrays - adjust size, calculate the destination and perform copytin -#if !HAS_OPCODES_65CE02 inc memmove__size+0 bne !+ inc memmove__size+1 -!: -#else // HAS_OPCODES_65CE02 - inw memmove__size -#endif clc lda memmove__src+0 @@ -214,4 +209,4 @@ fetch_variable_alocate_adjust_vars: // Adjust variable pointer and quit - jmp_8 fetch_variable_adjust_VARPNT + jmp fetch_variable_adjust_VARPNT From 98bd1cc78cac7d66ef5e41b5be9b9e53606b35aa Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 14:29:45 +0200 Subject: [PATCH 127/130] small build segment tool improvement --- tools/build_segment.cc | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/build_segment.cc b/tools/build_segment.cc index d160f055..ab6c41ed 100644 --- a/tools/build_segment.cc +++ b/tools/build_segment.cc @@ -874,10 +874,26 @@ void BinningProblem::placeHighRoutines(DualStream &logOutput) while (!floatingRoutines.empty()) { - // Try to find any high routine + // Find the largest high routine - auto iterRoutine = floatingRoutines.begin(); - while (iterRoutine != floatingRoutines.end() && !(*iterRoutine)->high) iterRoutine++; + auto iterRoutine = floatingRoutines.end(); + + for (auto iter = floatingRoutines.begin(); iter < floatingRoutines.end(); iter++) + { + if (!(*iter)->high) continue; + + if (iterRoutine == floatingRoutines.end() || + (*iterRoutine)->codeLength < (*iter)->codeLength) + { + iterRoutine = iter; + continue; + } + + if ((*iterRoutine)->codeLength < (*iter)->codeLength) + { + iterRoutine = iter; + } + } if (iterRoutine == floatingRoutines.end()) break; From 9dbc1ced658e04026f65c46c73cc9f7ccdc0dd5a Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 14:54:15 +0200 Subject: [PATCH 128/130] regression fix, documentation updates --- STATUS.md | 5 ++--- src/basic/engine_variables/fetch_variable.s | 3 ++- src/basic/engine_variables/helper_array_refresh_bptrs.s | 7 ++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/STATUS.md b/STATUS.md index 66547f2a..ed8966a0 100644 --- a/STATUS.md +++ b/STATUS.md @@ -42,9 +42,8 @@ The following ROM features are currently missing and are not planned due to spac The following ROM features are currently missing: * most BASIC commands -* BASIC variables (work in progress, strings partially work now) -* BASIC expression handling -* most floating point routines +* BASIC integer/float variables/arrays (strings work now, with the exception of undefined arrays) +* BASIC expression handling (again, strings should work now) * RS-232 support * NMI handling is incomplete diff --git a/src/basic/engine_variables/fetch_variable.s b/src/basic/engine_variables/fetch_variable.s index d5af69d3..146f5ed5 100644 --- a/src/basic/engine_variables/fetch_variable.s +++ b/src/basic/engine_variables/fetch_variable.s @@ -131,11 +131,12 @@ fetch_variable_alocate_space_OK: ora memmove__size+0 beq fetch_variable_alocate_adjust_vars - // Indeed, there are arrays - adjust size, calculate the destination and perform copytin + // Indeed, there are arrays - adjust size, calculate the destination and perform copying inc memmove__size+0 bne !+ inc memmove__size+1 +!: clc lda memmove__src+0 diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs.s b/src/basic/engine_variables/helper_array_refresh_bptrs.s index 20882012..90941d2e 100644 --- a/src/basic/engine_variables/helper_array_refresh_bptrs.s +++ b/src/basic/engine_variables/helper_array_refresh_bptrs.s @@ -26,7 +26,8 @@ helper_array_refresh_bptrs_loop_1: bne !+ lda INDEX+0 cmp STREND+0 - beq helper_array_refresh_bptrs_end + bne !+ + rts !: // Calculate start address of the next array, store it in INDEX+2/+3 @@ -136,7 +137,3 @@ helper_array_refresh_bptrs_loop_next: sta INDEX+0 jmp_8 helper_array_refresh_bptrs_loop_1 - -helper_array_refresh_bptrs_end: - - rts From ef8f9009545872b0c4f68b41d9c804ebb7dd9e74 Mon Sep 17 00:00:00 2001 From: FeralChild64 Date: Sun, 2 Aug 2020 15:18:57 +0200 Subject: [PATCH 129/130] added missing 60K memory model code, updated binaries --- bin/basic_generic.rom | Bin 8192 -> 8192 bytes bin/basic_ultimate64.rom | Bin 8192 -> 8192 bytes bin/kernal_generic.rom | Bin 8192 -> 8192 bytes bin/kernal_ultimate64.rom | Bin 8192 -> 8192 bytes bin/mega65.rom | Bin 131072 -> 131072 bytes bin/mega65_pxlfont.rom | Bin 131072 -> 131072 bytes .../helper_array_refresh_bptrs.s | 73 ++++++++++++++++-- 7 files changed, 66 insertions(+), 7 deletions(-) diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index d0f19bd4eb4f392d95d442d5d69876988495327e..447fd20d91258d74074679afce49c948b3cf2ef3 100644 GIT binary patch delta 5971 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 delta 3459 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 diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index 7162b1f8170d5d46aa23db5c2fa68d597c6f14ae..76f62af36c56a40166a182d2db862468bfe995f8 100644 GIT binary patch delta 3424 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 PO0l0NE_VJpvd;d0ir*PA diff --git a/bin/mega65.rom b/bin/mega65.rom index f4c2022862fbcb5bd7befbffca32c85a16e8664e..643e1484a0aeaa061bd11df03234ad5a24472fb0 100644 GIT binary patch delta 7659 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 OURbXZ|M#y@CH)_jst7Rv diff --git a/bin/mega65_pxlfont.rom b/bin/mega65_pxlfont.rom index 70961d3f240dcd2c1a48b5f158ad272c797e2655..92655da7b7f8724fe953f3889d42de09196276c7 100644 GIT binary patch delta 7659 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 OURbXZ|M#y@CH)_jst7Rv diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs.s b/src/basic/engine_variables/helper_array_refresh_bptrs.s index 90941d2e..616ed146 100644 --- a/src/basic/engine_variables/helper_array_refresh_bptrs.s +++ b/src/basic/engine_variables/helper_array_refresh_bptrs.s @@ -33,7 +33,40 @@ helper_array_refresh_bptrs_loop_1: #if CONFIG_MEMORY_MODEL_60K - // XXX! + ldx # Date: Wed, 5 Aug 2020 22:20:20 +0200 Subject: [PATCH 130/130] explained all similarities >3 --- strings/00000003 | 4 ++++ strings/00E6A2D006E6A1D002E6A0 | 3 +++ strings/018562B0 | 3 +++ strings/026090051C9F9C1E1F9E8195969798999A9B | 3 +++ strings/02852DA52C6900852E20 | 3 +++ strings/06142615 | 3 +++ strings/148514A5 | 3 +++ strings/1548A51448 | 3 +++ strings/1548A5144820 | 3 +++ strings/18652285 | 3 +++ strings/1865228524 | 3 +++ strings/2033A54C | 3 +++ strings/20B9ED20 | 3 +++ strings/20BAFF20 | 3 +++ strings/25A000B1 | 4 ++++ strings/3020D2FF | 3 +++ strings/38A533E5 | 3 +++ strings/38A533E531 | 3 +++ strings/46C954D0 | 3 +++ strings/488A4820 | 3 +++ strings/48A51448 | 3 +++ strings/48A54548 | 3 +++ strings/48A54648 | 3 +++ strings/48A56248A5 | 3 +++ strings/48A57B48A5 | 3 +++ strings/60A561F0FB | 3 +++ strings/62666366646665667060A5 | 3 +++ strings/64A90085 | 3 +++ strings/65148514 | 3 +++ strings/65148514A5 | 3 +++ strings/65158515 | 3 +++ strings/65228522 | 3 +++ strings/65228524 | 3 +++ strings/65338533 | 3 +++ strings/686868AA | 3 +++ strings/6885456885 | 3 +++ strings/68854668 | 3 +++ strings/7A48A57B | 3 +++ strings/810000000020 | 3 +++ strings/85228623 | 3 +++ strings/85229002 | 3 +++ strings/85339002E634 | 3 +++ strings/85628563 | 3 +++ strings/8562C8B1 | 3 +++ strings/856385648565 | 3 +++ strings/86706020 | 3 +++ strings/8810F820 | 3 +++ strings/A0006891 | 3 +++ strings/A000A54591 | 3 +++ strings/A51548A51448 | 3 +++ strings/A533E531 | 3 +++ strings/A534E532 | 3 +++ strings/A54648A54548 | 3 +++ strings/A57A48A5 | 3 +++ strings/A57B48A5 | 3 +++ strings/A9A8A0AE20 | 3 +++ strings/B1474888 | 3 +++ strings/B1B2C905 | 3 +++ strings/C8A54691 | 3 +++ strings/C8B12265 | 3 +++ strings/C8C006D0 | 3 +++ strings/C922F056 | 3 +++ strings/C929F006 | 3 +++ strings/E7FFA537 | 3 +++ 64 files changed, 194 insertions(+) create mode 100644 strings/00000003 create mode 100644 strings/00E6A2D006E6A1D002E6A0 create mode 100644 strings/018562B0 create mode 100644 strings/026090051C9F9C1E1F9E8195969798999A9B create mode 100644 strings/02852DA52C6900852E20 create mode 100644 strings/06142615 create mode 100644 strings/148514A5 create mode 100644 strings/1548A51448 create mode 100644 strings/1548A5144820 create mode 100644 strings/18652285 create mode 100644 strings/1865228524 create mode 100644 strings/2033A54C create mode 100644 strings/20B9ED20 create mode 100644 strings/20BAFF20 create mode 100644 strings/25A000B1 create mode 100644 strings/3020D2FF create mode 100644 strings/38A533E5 create mode 100644 strings/38A533E531 create mode 100644 strings/46C954D0 create mode 100644 strings/488A4820 create mode 100644 strings/48A51448 create mode 100644 strings/48A54548 create mode 100644 strings/48A54648 create mode 100644 strings/48A56248A5 create mode 100644 strings/48A57B48A5 create mode 100644 strings/60A561F0FB create mode 100644 strings/62666366646665667060A5 create mode 100644 strings/64A90085 create mode 100644 strings/65148514 create mode 100644 strings/65148514A5 create mode 100644 strings/65158515 create mode 100644 strings/65228522 create mode 100644 strings/65228524 create mode 100644 strings/65338533 create mode 100644 strings/686868AA create mode 100644 strings/6885456885 create mode 100644 strings/68854668 create mode 100644 strings/7A48A57B create mode 100644 strings/810000000020 create mode 100644 strings/85228623 create mode 100644 strings/85229002 create mode 100644 strings/85339002E634 create mode 100644 strings/85628563 create mode 100644 strings/8562C8B1 create mode 100644 strings/856385648565 create mode 100644 strings/86706020 create mode 100644 strings/8810F820 create mode 100644 strings/A0006891 create mode 100644 strings/A000A54591 create mode 100644 strings/A51548A51448 create mode 100644 strings/A533E531 create mode 100644 strings/A534E532 create mode 100644 strings/A54648A54548 create mode 100644 strings/A57A48A5 create mode 100644 strings/A57B48A5 create mode 100644 strings/A9A8A0AE20 create mode 100644 strings/B1474888 create mode 100644 strings/B1B2C905 create mode 100644 strings/C8A54691 create mode 100644 strings/C8B12265 create mode 100644 strings/C8C006D0 create mode 100644 strings/C922F056 create mode 100644 strings/C929F006 create mode 100644 strings/E7FFA537 diff --git a/strings/00000003 b/strings/00000003 new file mode 100644 index 00000000..4870347c --- /dev/null +++ b/strings/00000003 @@ -0,0 +1,4 @@ +couple of 0's followed by $03 + +In original ROMs this is a part of floating point constant, in OpenROMs, it can even by a result of code not filling-in the ROM completely. Trivial - not copyrightable. + diff --git a/strings/00E6A2D006E6A1D002E6A0 b/strings/00E6A2D006E6A1D002E6A0 new file mode 100644 index 00000000..7044c8af --- /dev/null +++ b/strings/00E6A2D006E6A1D002E6A0 @@ -0,0 +1,3 @@ +$00 + INC $A2 + BNE (address matches) + INC $A1 + BNE (address matches) + INC $A0 + +Incrementing 24-bit zeropage variable (TIME) by 1 (+ one byte from another instruction) - trivial, not copyrightable. diff --git a/strings/018562B0 b/strings/018562B0 new file mode 100644 index 00000000..95692b87 --- /dev/null +++ b/strings/018562B0 @@ -0,0 +1,3 @@ +$01 + STA $62 + BCS (offset does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/026090051C9F9C1E1F9E8195969798999A9B b/strings/026090051C9F9C1E1F9E8195969798999A9B new file mode 100644 index 00000000..79d39cad --- /dev/null +++ b/strings/026090051C9F9C1E1F9E8195969798999A9B @@ -0,0 +1,3 @@ +$02 + RTS + PETSCII color table + +Part of some instruction (just one byte) + a list of facts - not copyrightable. diff --git a/strings/02852DA52C6900852E20 b/strings/02852DA52C6900852E20 new file mode 100644 index 00000000..61b695ca --- /dev/null +++ b/strings/02852DA52C6900852E20 @@ -0,0 +1,3 @@ +$02 + STA $2D + LDA $2C + ADC #$00 + STA $2E + JSR (address does not match) + +Part of the NEW command implementation resetting various pointers to default values - not creative, not copyrightable. diff --git a/strings/06142615 b/strings/06142615 new file mode 100644 index 00000000..59e554e2 --- /dev/null +++ b/strings/06142615 @@ -0,0 +1,3 @@ +ASL $14 + ROL $15 + +Multiplication of 16-bit zeropage variable by 2 - trivial, not copyrightable. diff --git a/strings/148514A5 b/strings/148514A5 new file mode 100644 index 00000000..4e1b0ad9 --- /dev/null +++ b/strings/148514A5 @@ -0,0 +1,3 @@ +$14 + STA $14 + LDA (zeropage address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/1548A51448 b/strings/1548A51448 new file mode 100644 index 00000000..56c58455 --- /dev/null +++ b/strings/1548A51448 @@ -0,0 +1,3 @@ +$15 + PHA + LDA $14 + PHA + +Part of code stroing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/1548A5144820 b/strings/1548A5144820 new file mode 100644 index 00000000..93061cbb --- /dev/null +++ b/strings/1548A5144820 @@ -0,0 +1,3 @@ +$15 + PHA + LDA $14 + PHA + JSR (address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order (+ a part of another instruction) - trivial, not copyrightable. diff --git a/strings/18652285 b/strings/18652285 new file mode 100644 index 00000000..a8291728 --- /dev/null +++ b/strings/18652285 @@ -0,0 +1,3 @@ +CLC + ADC $22 + STA (zeropage address does not match) + +Subtracting two zeropage variables (not even the same ones) - trivial, not copyrightable. diff --git a/strings/1865228524 b/strings/1865228524 new file mode 100644 index 00000000..d0919e3f --- /dev/null +++ b/strings/1865228524 @@ -0,0 +1,3 @@ +CLC + ADC $22 + STA $24 + +Adding two zeropage variables - trivial, not copyrightable. diff --git a/strings/2033A54C b/strings/2033A54C new file mode 100644 index 00000000..88782adf --- /dev/null +++ b/strings/2033A54C @@ -0,0 +1,3 @@ +JSR $A533 (relink program) + JMP (address does not match) + +Call of a well-known subroutine + part of another instruction. Trivial - not copyrightable. diff --git a/strings/20B9ED20 b/strings/20B9ED20 new file mode 100644 index 00000000..84d9467a --- /dev/null +++ b/strings/20B9ED20 @@ -0,0 +1,3 @@ +JSR $EDB9 (LISTEN) + JSR (address does not match) + +Call of a well-known subroutine + part of another instruction. Trivial - not copyrightable. diff --git a/strings/20BAFF20 b/strings/20BAFF20 new file mode 100644 index 00000000..e1ab3c0a --- /dev/null +++ b/strings/20BAFF20 @@ -0,0 +1,3 @@ +JSR $FFBA (SETLFS) + JSR (address does not match) + +Call of a well-known subroutine + part of another instruction. Trivial - not copyrightable. diff --git a/strings/25A000B1 b/strings/25A000B1 new file mode 100644 index 00000000..b6a5fbfe --- /dev/null +++ b/strings/25A000B1 @@ -0,0 +1,4 @@ + $25 + LDY #$00 + LDA (zeropage address does not match),Y + + Instruction + some parts - trivial, not copyrightable. + diff --git a/strings/3020D2FF b/strings/3020D2FF new file mode 100644 index 00000000..80ff7548 --- /dev/null +++ b/strings/3020D2FF @@ -0,0 +1,3 @@ +$30 + JSR $FFD2 (CHROUT) + +Instruction (call of a well-known routine) + some part. Trivial - not copyrightable. diff --git a/strings/38A533E5 b/strings/38A533E5 new file mode 100644 index 00000000..b35d7953 --- /dev/null +++ b/strings/38A533E5 @@ -0,0 +1,3 @@ +SEC + LDA $33 + SBC (zeropage address does not match) + +Subtracting two zeropage variables (not even both the same ones) - trivial, not copyrightable. diff --git a/strings/38A533E531 b/strings/38A533E531 new file mode 100644 index 00000000..7f590ec5 --- /dev/null +++ b/strings/38A533E531 @@ -0,0 +1,3 @@ +SEC + LDA $33 + SBC $31 + +Subtracting two zeropage variables - trivial, not copyrightable. diff --git a/strings/46C954D0 b/strings/46C954D0 new file mode 100644 index 00000000..40330ac8 --- /dev/null +++ b/strings/46C954D0 @@ -0,0 +1,3 @@ +$46 + CMP #$54 + BNE (offset does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/488A4820 b/strings/488A4820 new file mode 100644 index 00000000..d3b130ef --- /dev/null +++ b/strings/488A4820 @@ -0,0 +1,3 @@ +PHA + TXA + PHA + JSR (address does not match) + +Part of code storing registers on the stack (+ a part of another instruction) - trivial, not copyrightable. diff --git a/strings/48A51448 b/strings/48A51448 new file mode 100644 index 00000000..60fec655 --- /dev/null +++ b/strings/48A51448 @@ -0,0 +1,3 @@ +PHA + LDA $14 + PHA + +Part of code retrieving values from stack - trivial, not copyrightable. diff --git a/strings/48A54548 b/strings/48A54548 new file mode 100644 index 00000000..61b91bdf --- /dev/null +++ b/strings/48A54548 @@ -0,0 +1,3 @@ +PHA + LDA $45 + PHA + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/48A54648 b/strings/48A54648 new file mode 100644 index 00000000..4ecdbdbe --- /dev/null +++ b/strings/48A54648 @@ -0,0 +1,3 @@ +PHA + LDA $46 + PHA + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/48A56248A5 b/strings/48A56248A5 new file mode 100644 index 00000000..3fe300a3 --- /dev/null +++ b/strings/48A56248A5 @@ -0,0 +1,3 @@ +PHA + LDA $62 + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/48A57B48A5 b/strings/48A57B48A5 new file mode 100644 index 00000000..4d0b7853 --- /dev/null +++ b/strings/48A57B48A5 @@ -0,0 +1,3 @@ +PHA + LDA $7B + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/60A561F0FB b/strings/60A561F0FB new file mode 100644 index 00000000..4cfa30ac --- /dev/null +++ b/strings/60A561F0FB @@ -0,0 +1,3 @@ +RTS + LDA $61 + BEQ (offset matches) + +End of previous subroutine + beginning of a new one, performing different action depending whether zeropage variable is 0 or not. Trivial - not copyrightable. diff --git a/strings/62666366646665667060A5 b/strings/62666366646665667060A5 new file mode 100644 index 00000000..a6e4874f --- /dev/null +++ b/strings/62666366646665667060A5 @@ -0,0 +1,3 @@ +$62 + ROR $63 + ROR $64 + ROR $65 + ROR $70 + RTS + LDA (zeropage addres does not match) + +Part of code multiplying by 2 a well-known multibyte zeropage variable + a part of another instruction. Not creative - not copyrightable. diff --git a/strings/64A90085 b/strings/64A90085 new file mode 100644 index 00000000..5ab38b51 --- /dev/null +++ b/strings/64A90085 @@ -0,0 +1,3 @@ +$64 + LDA #$00 + STA (zeropage address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/65148514 b/strings/65148514 new file mode 100644 index 00000000..17a51e64 --- /dev/null +++ b/strings/65148514 @@ -0,0 +1,3 @@ +ADC $14 + STA $14 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/65148514A5 b/strings/65148514A5 new file mode 100644 index 00000000..33e55d20 --- /dev/null +++ b/strings/65148514A5 @@ -0,0 +1,3 @@ +ADC $14 + STA $14 + LDA (zeropage address does not match) + +Adding a value to a zeropage variable + some part of another instruction - trivial, not copyrightable. diff --git a/strings/65158515 b/strings/65158515 new file mode 100644 index 00000000..f51f4475 --- /dev/null +++ b/strings/65158515 @@ -0,0 +1,3 @@ +ADC $15 + STA $15 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/65228522 b/strings/65228522 new file mode 100644 index 00000000..d98ad093 --- /dev/null +++ b/strings/65228522 @@ -0,0 +1,3 @@ +ADC $22 + STA $22 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/65228524 b/strings/65228524 new file mode 100644 index 00000000..2ffbe09e --- /dev/null +++ b/strings/65228524 @@ -0,0 +1,3 @@ +ADC $22 + STA $24 + +Adding a zeropage value to .A, storing result in another zeropage location - trivial, not copyrightable. diff --git a/strings/65338533 b/strings/65338533 new file mode 100644 index 00000000..9fe74632 --- /dev/null +++ b/strings/65338533 @@ -0,0 +1,3 @@ +ADC $33 + STA $33 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/686868AA b/strings/686868AA new file mode 100644 index 00000000..cc4b6c84 --- /dev/null +++ b/strings/686868AA @@ -0,0 +1,3 @@ +PLA + PLA + PLA + TAX + +Drop 2 values from the stack, fetch the next one into .X register - trivial, not copyrightable. diff --git a/strings/6885456885 b/strings/6885456885 new file mode 100644 index 00000000..37afe558 --- /dev/null +++ b/strings/6885456885 @@ -0,0 +1,3 @@ +PLA + STA $45 + PLA + STA (zeropage address does not match) + +Part of code retrieving zeropage variables from the stack (not even exactly the same ones) - trivial, not copyrightable. diff --git a/strings/68854668 b/strings/68854668 new file mode 100644 index 00000000..ffb6c888 --- /dev/null +++ b/strings/68854668 @@ -0,0 +1,3 @@ +PLA + STA $46 + PLA + +Part of code retrieving values from the stack - trivial, not copyrightable. diff --git a/strings/7A48A57B b/strings/7A48A57B new file mode 100644 index 00000000..1e29c3d5 --- /dev/null +++ b/strings/7A48A57B @@ -0,0 +1,3 @@ +$7A + PHA + LDA $7B + +Small part of code storing zeropage variables on the stack - trivial, not copyrightable. diff --git a/strings/810000000020 b/strings/810000000020 new file mode 100644 index 00000000..c8e599eb --- /dev/null +++ b/strings/810000000020 @@ -0,0 +1,3 @@ +floating point value 1.0 + $20 byte + +A trivial floating point value + some part - not creative, not copyrightable. diff --git a/strings/85228623 b/strings/85228623 new file mode 100644 index 00000000..3584674c --- /dev/null +++ b/strings/85228623 @@ -0,0 +1,3 @@ +STA $22 + STX $23 + +Storing two registers in a 16-bit zeropage variable - trivial, not copyrightable. diff --git a/strings/85229002 b/strings/85229002 new file mode 100644 index 00000000..3bdcc5fe --- /dev/null +++ b/strings/85229002 @@ -0,0 +1,3 @@ +STA $22 + BCC (offset matches) + +Storing .A in zeropage variable + conditional jump - trivial; not copyrightable. diff --git a/strings/85339002E634 b/strings/85339002E634 new file mode 100644 index 00000000..5c192acf --- /dev/null +++ b/strings/85339002E634 @@ -0,0 +1,3 @@ +STA $33 + BCC (offset matches) + INC $34 + +Small part of the code to add .A to a 16 bit seropage variable - trivial, not copyrightable. diff --git a/strings/85628563 b/strings/85628563 new file mode 100644 index 00000000..b4687a55 --- /dev/null +++ b/strings/85628563 @@ -0,0 +1,3 @@ +STA $62 + STA $63 + +Storing accumulator in two zeropage locations - trivial, not copyrightable. diff --git a/strings/8562C8B1 b/strings/8562C8B1 new file mode 100644 index 00000000..476fdb7b --- /dev/null +++ b/strings/8562C8B1 @@ -0,0 +1,3 @@ +STA $62 + INY + LDA (zeropage address does not match),Y + +Store value on zeropage, fetch new from memory location determined by pointer (not even the same one) - not creative, not copyrightable. diff --git a/strings/856385648565 b/strings/856385648565 new file mode 100644 index 00000000..1c1f884c --- /dev/null +++ b/strings/856385648565 @@ -0,0 +1,3 @@ +STA $63 + STA $64 + STA $65 + +Storing a value (0) in a multibyte zeropage variable - trivial, not copyrightable. diff --git a/strings/86706020 b/strings/86706020 new file mode 100644 index 00000000..abd1ad3b --- /dev/null +++ b/strings/86706020 @@ -0,0 +1,3 @@ +STX $70 + RTS + JSR (addres does not match) + +Routine ending by storing .X to zeropage variable + one byte (start of the instruction) of the next one - trivial, not copyrightable. diff --git a/strings/8810F820 b/strings/8810F820 new file mode 100644 index 00000000..54c6c4ce --- /dev/null +++ b/strings/8810F820 @@ -0,0 +1,3 @@ +DEY + BPL (offset matches) + JSR (address does not match) + +Small part of the loop by .Y register - trivial and not creative, not copyrightable. diff --git a/strings/A0006891 b/strings/A0006891 new file mode 100644 index 00000000..be6d0aaf --- /dev/null +++ b/strings/A0006891 @@ -0,0 +1,3 @@ +LDY #$00 + PLA + STA (zeropage address does not match),Y + +Store value from the stack on the location determined by pointer (not even the same one) - not creative, not copyrightable. diff --git a/strings/A000A54591 b/strings/A000A54591 new file mode 100644 index 00000000..8e706b98 --- /dev/null +++ b/strings/A000A54591 @@ -0,0 +1,3 @@ +LDY #$00 + LDA $45 + STA (zeropage address does not match),Y + +Copying value from zeropage variablle to memory location determined by pointer (not even the same one) - trivial, not copyrightable. diff --git a/strings/A51548A51448 b/strings/A51548A51448 new file mode 100644 index 00000000..8ca219eb --- /dev/null +++ b/strings/A51548A51448 @@ -0,0 +1,3 @@ +LDA $15 + PHA + LDA $14 + PHA + +Store 16-bit zeropage value on the stack - trivial, not copyrightable. diff --git a/strings/A533E531 b/strings/A533E531 new file mode 100644 index 00000000..ece3131f --- /dev/null +++ b/strings/A533E531 @@ -0,0 +1,3 @@ +LDA $33 + SBC $31 + +Subtraction of two zeropage variables - trivial, not copyrightable. diff --git a/strings/A534E532 b/strings/A534E532 new file mode 100644 index 00000000..56808cf9 --- /dev/null +++ b/strings/A534E532 @@ -0,0 +1,3 @@ +LDA $34 + SBC $32 + +Subtracting two zeropage variables - trivial, not copyrightable. diff --git a/strings/A54648A54548 b/strings/A54648A54548 new file mode 100644 index 00000000..e7ef4095 --- /dev/null +++ b/strings/A54648A54548 @@ -0,0 +1,3 @@ +LDA $46 + PHA + LDA $45 + PHA + +Store 16-bit zeropage value on the stack - trivial, not copyrightable. diff --git a/strings/A57A48A5 b/strings/A57A48A5 new file mode 100644 index 00000000..c4f8b4ae --- /dev/null +++ b/strings/A57A48A5 @@ -0,0 +1,3 @@ +LDA $7A + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/A57B48A5 b/strings/A57B48A5 new file mode 100644 index 00000000..5cde415f --- /dev/null +++ b/strings/A57B48A5 @@ -0,0 +1,3 @@ +LDA $7B + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/A9A8A0AE20 b/strings/A9A8A0AE20 new file mode 100644 index 00000000..ef4c0734 --- /dev/null +++ b/strings/A9A8A0AE20 @@ -0,0 +1,3 @@ +LDA #$A8 + LDY #$AE + JSR (address does not match) + +A small piece of code calling a subroutine to fetch PI value - trivial, not copyrightable. diff --git a/strings/B1474888 b/strings/B1474888 new file mode 100644 index 00000000..0cad4280 --- /dev/null +++ b/strings/B1474888 @@ -0,0 +1,3 @@ +LDA ($47),Y + PHA + DEY + +Small part of a code pushing memory to stack - not creative, not copyrightable. diff --git a/strings/B1B2C905 b/strings/B1B2C905 new file mode 100644 index 00000000..89b22fea --- /dev/null +++ b/strings/B1B2C905 @@ -0,0 +1,3 @@ +LDA ($B2),Y + CMP (value does not match) + +Instruction + some part. Trivial - not copyrightable. diff --git a/strings/C8A54691 b/strings/C8A54691 new file mode 100644 index 00000000..afc36c82 --- /dev/null +++ b/strings/C8A54691 @@ -0,0 +1,3 @@ +INY + LDA $46 + STA (zeropage address does not match),Y + +Copy zeopage value to a memory location determined by pointer (not even the same one) - trivial, not copyrightable. diff --git a/strings/C8B12265 b/strings/C8B12265 new file mode 100644 index 00000000..ca315950 --- /dev/null +++ b/strings/C8B12265 @@ -0,0 +1,3 @@ +INY + LDA ($22),Y + ADC (zeropage address does not match) + +Fetch value determined by pointer, add content of zeropage variable (not even the same one) - trivial, not copyrightable. diff --git a/strings/C8C006D0 b/strings/C8C006D0 new file mode 100644 index 00000000..c2916d5a --- /dev/null +++ b/strings/C8C006D0 @@ -0,0 +1,3 @@ +INY + CPY #$06 + BNE (offset does not match) + +Ending part of the loop by .Y, counting to 6 - not creative, not copyrightable. diff --git a/strings/C922F056 b/strings/C922F056 new file mode 100644 index 00000000..91498fac --- /dev/null +++ b/strings/C922F056 @@ -0,0 +1,3 @@ +CMP #$22 ('"') + BEQ (offset matches) + +Decision based on accumulator value - trivial, not copyrightable. diff --git a/strings/C929F006 b/strings/C929F006 new file mode 100644 index 00000000..a06a9194 --- /dev/null +++ b/strings/C929F006 @@ -0,0 +1,3 @@ +CMP #$29 + BEQ (offset matches) + +Decision based on accumulator value - trivial, not copyrightable. diff --git a/strings/E7FFA537 b/strings/E7FFA537 new file mode 100644 index 00000000..c059fa0c --- /dev/null +++ b/strings/E7FFA537 @@ -0,0 +1,3 @@ +$FFE7 + LDA $37 + +Address of a well-known routine (CLALL) + a single instruction. Trivial - not copyrightable.