diff --git a/CONFIG.md b/CONFIG.md index f548ee4f..9c1fa54c 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -3,11 +3,11 @@ It's not possible to provide ROM builds that suit everyone needs - therefore configuration files were introduced, few predefined configurations are provided with sane defaults: -* [`c64/,,config_custom.s`](c64/,,config_custom.s) -* [`c64/,,config_generic.s`](c64/,,config_generic.s) -* [`c64/,,config_mega65.s`](c64/,,config_mega65.s) -* [`c64/,,config_ultimate64.s`](c64/,,config_ultimate64.s) -* [`c64/,,config_testing.s`](c64/,,config_testing.s) +* [`src/,,config_custom.s`](src/,,config_custom.s) +* [`src/,,config_generic.s`](src/,,config_generic.s) +* [`src/,,config_mega65.s`](src/,,config_mega65.s) +* [`src/,,config_ultimate64.s`](src/,,config_ultimate64.s) +* [`src/,,config_testing.s`](src/,,config_testing.s) Just edit them and recompile the project. To enable particular option - uncomment it by removing leading `//` from before `#define` directive (as you probably guessed, commenting out disables it). Some options are followed by constants - you can change them too to further fine-tune the build. @@ -105,12 +105,14 @@ Memory model the original machine uses - memory available for BASIC ends at `$9F ### `CONFIG_MEMORY_MODEL_46K` and `CONFIG_MEMORY_MODEL_50K` -Planned for the future - not available yet. +These models additionaly use RAM under BASIC, and the 50K additionally takes over `$C000`-`$CFFF` range. They should still be highly compatible (no additional RAM for helper routines is needed), and the performance penalty should be much lower than 60K model. ### `CONFIG_MEMORY_MODEL_60K` Uses RAM under BASIC, I/O and KERNAL, takes over `$C000`-`$CFFF` area requires special helper routines installed in `$2A7`-`$2FF` area (normally unused and free for the user). Gives the most free memory for BASIC programs, but it's the slowest (for example, forces disabling optimized LOAD loop for JiffyDOS) and the least compatible model. +It is currently not compatible with Mega65 extended ROMs. + Comparing to standard memory model, it needs about 180 bytes in BASIC segment and 80 bytes in KERNAL segment - at the moment of doing the test, these values are expected to change often. ## IEC devices @@ -283,9 +285,15 @@ Feature needs about 330 bytes in BASIC segment. If unsure - enable. ### `CONFIG_TAPE_WEDGE` -If enabled, a simple DOS wedge is available from the direct mode for turbo tape loading - supports `←L` only +If enabled, a simple DOS wedge is available from the direct mode for tape loading - supports `←L` only. -Feature needs about 5 bytes in BASIC segment. If unsure - enable. +Feature needs few bytes in BASIC segment. If unsure - enable. + +### `CONFIG_TAPE_HEAD_ALIGN` + +If enabled, embeds a tape head align tool into the ROM, it can be started with `←H`. Requires `CONFIG_TAPE_WEDGE`. + +Feature needs about 800 bytes in KERNAL segment. Only recomended for machines with extended ROM, like Mega65. ### `CONFIG_BCD_SAFE_INTERRUPTS` @@ -307,16 +315,10 @@ Richer banners need more BASIC segment, varies between brands. ### `CONFIG_SHOW_FEATURES` -If enabled, shows the most important compiled-in features on the startup screen. +If enabled, shows the most important compiled-in features on the startup screen. Also shows the video system (PAL/NTSC). It is recommended to keep it enabled for informational purposes. -### `CONFIG_BANNER_PAL_NTSC` - -If enabled, prints video system on startup banner. Eye candy only. - -Feature needs few bytes in BASIC and about 25 bytes in KERNAL segment. - ## Debug options Options in this section are for debug purposes only. If unsure - disable. @@ -328,3 +330,9 @@ Replaces `RTS` stubbed routines implementation with one causing a break. ### `CONFIG_DBG_PRINTF` Makes `printf` routine available. + +## Other options + +### `CONFIG_COMPRESSION_LVL_2` + +Adds additional step in compressing BASIC interpreter strings - a dictionary compression. Not tested extensively - and for now it won't bring any improvement (it will even increase the code/data size) as we do not have enough strings yet to make this method useful. Do not use! diff --git a/Makefile b/Makefile index 2181f8c2..92dff008 100644 --- a/Makefile +++ b/Makefile @@ -6,43 +6,51 @@ TESTTAPE = testsuite/testtape-c64-pal-turbo.tap # Source files -SRCDIR_COMMON = c64/aliases +SRCDIR_COMMON = src/aliases SRCDIR_BASIC = $(SRCDIR_COMMON) \ - c64/basic \ - c64/basic/,stubs \ - c64/basic/,stubs_math \ - c64/basic/assets \ - c64/basic/board_m65 \ - c64/basic/board_x16 \ - c64/basic/commands \ - c64/basic/init \ - c64/basic/math \ - c64/basic/math_consts \ - c64/basic/math_mov \ - c64/basic/print \ - c64/basic/rom_revision + src/basic \ + src/basic/,stubs \ + src/basic/,stubs_math \ + src/basic/assets \ + src/basic/basic_commands \ + src/basic/basic_commands_CC \ + src/basic/basic_commands_CD \ + src/basic/basic_operators \ + src/basic/basic_functions \ + src/basic/board_m65 \ + src/basic/board_x16 \ + src/basic/engine \ + src/basic/init \ + src/basic/math \ + src/basic/math_consts \ + src/basic/math_mov \ + src/basic/memory \ + src/basic/print \ + src/basic/rom_revision \ + src/basic/tokenizer \ + src/basic/wedge SRCDIR_KERNAL = $(SRCDIR_COMMON) \ - c64/kernal \ - c64/kernal/,stubs \ - c64/kernal/assets \ - c64/kernal/board_m65 \ - c64/kernal/board_x16 \ - c64/kernal/iec \ - c64/kernal/iec_fast \ - c64/kernal/init \ - c64/kernal/interrupts \ - c64/kernal/iostack \ - c64/kernal/jumptable \ - c64/kernal/keyboard \ - c64/kernal/memory \ - c64/kernal/print \ - c64/kernal/rom_revision \ - c64/kernal/rs232 \ - c64/kernal/screen \ - c64/kernal/tape \ - c64/kernal/time + src/kernal \ + src/kernal/,stubs \ + src/kernal/assets \ + src/kernal/board_m65 \ + src/kernal/board_x16 \ + src/kernal/iec \ + src/kernal/iec_fast \ + src/kernal/init \ + src/kernal/interrupts \ + src/kernal/iostack \ + src/kernal/jumptable \ + src/kernal/keyboard \ + src/kernal/memory \ + src/kernal/print \ + src/kernal/rom_revision \ + src/kernal/rs232 \ + src/kernal/screen \ + src/kernal/tape \ + src/kernal/time SRC_BASIC = $(foreach dir,$(SRCDIR_BASIC),$(wildcard $(dir)/*.s)) SRC_KERNAL = $(foreach dir,$(SRCDIR_KERNAL),$(wildcard $(dir)/*.s)) @@ -50,7 +58,7 @@ SRC_TOOLS = $(wildcard tools/*.c,tools/*.cc) # Generated files -GEN_BASIC = build/,generated/packed_messages.s build/,generated/float_constants.s +GEN_BASIC = build/,generated/float_constants.s GEN_KERNAL = # List of build directories @@ -64,23 +72,32 @@ DIR_X16 = build/target_cx16 # List of config files -CFG_CUS = c64/,,config_custom.s -CFG_GEN = c64/,,config_generic.s -CFG_TST = c64/,,config_testing.s -CFG_M65 = c64/,,config_mega65.s -CFG_U64 = c64/,,config_ultimate64.s -CFG_X16 = c64/,,config_cx16.s +CFG_CUS = src/,,config_custom.s +CFG_GEN = src/,,config_generic.s +CFG_TST = src/,,config_testing.s +CFG_M65 = src/,,config_mega65.s +CFG_U64 = src/,,config_ultimate64.s +CFG_X16 = src/,,config_cx16.s + +# List of files with generated strings + +GEN_STR_CUS = $(DIR_CUS)/,generated/packed_strings.s +GEN_STR_GEN = $(DIR_GEN)/,generated/packed_strings.s +GEN_STR_TST = $(DIR_TST)/,generated/packed_strings.s +GEN_STR_M65 = $(DIR_M65)/,generated/packed_strings.s +GEN_STR_U64 = $(DIR_U64)/,generated/packed_strings.s +GEN_STR_X16 = $(DIR_X16)/,generated/packed_strings.s # Dependencies - helper variables -DEP_BASIC = $(SRC_BASIC) $(SRCDIR_BASIC) $(GEN_BASIC) -DEP_KERNAL = $(SRC_KERNAL) $(SRCDIR_KERNAL) $(GEN_KERNAL) +DEP_BASIC = $(SRC_BASIC) $(SRCDIR_BASIC) $(GEN_BASIC) +DEP_KERNAL = $(SRC_KERNAL) $(SRCDIR_KERNAL) $(GEN_KERNAL) # List of tools TOOL_COLLECT_DATA = build/tools/collect_data -TOOL_COMPRESS_TEXT = build/tools/compress_text TOOL_GENERATE_CONSTANTS = build/tools/generate_constants +TOOL_GENERATE_STRINGS = build/tools/generate_strings TOOL_PATCH_CHARGEN = build/tools/patch_chargen TOOL_PNGPREPARE = build/tools/pngprepare TOOL_BUILD_SEGMENT = build/tools/build_segment @@ -130,7 +147,7 @@ SEG_LIST_X16 = $(DIR_X16)/basic.seg_0 \ $(DIR_X16)/kernal.seg_0 \ $(DIR_X16)/kernal.seg_1 -REL_TARGET_LIST = $(TARGET_LIST_GEN) $(TARGET_LIST_TST) $(TARGET_M65_x) $(TARGET_M65_x_PXL) $(TARGET_LIST_U64) +REL_TARGET_LIST = $(TARGET_LIST_GEN) $(TARGET_M65_x) $(TARGET_M65_x_PXL) $(TARGET_LIST_U64) # Misc strings @@ -151,7 +168,7 @@ fast: $(MAKE) -j64 --output-sync=target $(TARGET_LIST) $(EXT_TARGET_LIST) clean: - @rm -rf build c64/basic/combined.s c64/kernal/combined.s + @rm -rf build src/basic/combined.s src/kernal/combined.s updatebin: $(MAKE) -j64 --output-sync=target $(TARGET_LIST) $(TOOL_RELEASE) @@ -164,10 +181,6 @@ $(TOOL_PNGPREPARE): tools/pngprepare.c @mkdir -p build/tools $(CC) -O2 -Wall -I/usr/local/include -L/usr/local/lib -o $@ $< -lpng -$(TOOL_COMPRESS_TEXT): tools/compress_text.c - @mkdir -p build/tools - $(CC) -O2 -Wall -I/usr/local/include -L/usr/local/lib -o $@ $< -lm - build/tools/%: tools/%.c @mkdir -p build/tools $(CC) -O2 -Wall -o $@ $< @@ -193,42 +206,42 @@ build/chargen_pxlfont.patched: $(TOOL_PATCH_CHARGEN) build/chargen_pxlfont.rom # Dependencies - BASIC and KERNAL $(DIR_CUS)/OUTB_x.BIN $(DIR_CUS)/BASIC_combined.vs: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_CUS) $(DIR_CUS)/KERNAL_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_CUS) $(GEN_STR_CUS) $(DIR_CUS)/KERNAL_combined.sym $(DIR_GEN)/OUTB_x.BIN $(DIR_GEN)/BASIC_combined.vs: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_GEN) $(DIR_GEN)/KERNAL_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_GEN) $(GEN_STR_GEN) $(DIR_GEN)/KERNAL_combined.sym $(DIR_TST)/OUTB_x.BIN $(DIR_TST)/BASIC_combined.vs: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_TST) $(DIR_TST)/KERNAL_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_TST) $(GEN_STR_TST) $(DIR_TST)/KERNAL_combined.sym $(DIR_U64)/OUTB_x.BIN $(DIR_U64)/BASIC_combined.vs: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_U64) $(DIR_U64)/KERNAL_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_U64) $(GEN_STR_U64) $(DIR_U64)/KERNAL_combined.sym $(DIR_CUS)/OUTK_x.BIN $(DIR_CUS)/KERNAL_combined.vs $(DIR_CUS)/KERNAL_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_CUS) + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_CUS) $(GEN_STR_CUS) $(DIR_GEN)/OUTK_x.BIN $(DIR_GEN)/KERNAL_combined.vs $(DIR_GEN)/KERNAL_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_GEN) + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_GEN) $(GEN_STR_GEN) $(DIR_TST)/OUTK_x.BIN $(DIR_TST)/KERNAL_combined.vs $(DIR_TST)/KERNAL_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_TST) + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_TST) $(GEN_STR_TST) $(DIR_U64)/OUTK_x.BIN $(DIR_U64)/KERNAL_combined.vs $(DIR_U64)/KERNAL_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_U64) + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_U64) $(GEN_STR_U64) $(DIR_M65)/OUTB_0.BIN $(DIR_M65)/BASIC_0_combined.vs $(DIR_M65)/BASIC_0_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_M65) $(DIR_M65)/KERNAL_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_M65) $(GEN_STR_M65) $(DIR_M65)/KERNAL_0_combined.sym $(DIR_M65)/OUTK_0.BIN $(DIR_M65)/KERNAL_0_combined.vs $(DIR_M65)/KERNAL_0_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_M65) + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_M65) $(GEN_STR_M65) $(DIR_X16)/OUTB_0.BIN $(DIR_X16)/BASIC_0_combined.vs $(DIR_X16)/BASIC_0_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_X16) $(DIR_X16)/KERNAL_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_X16) $(GEN_STR_X16) $(DIR_X16)/KERNAL_0_combined.sym $(DIR_X16)/OUTK_0.BIN $(DIR_X16)/KERNAL_0_combined.vs $(DIR_X16)/KERNAL_0_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_X16) + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_X16) $(GEN_STR_X16) $(DIR_M65)/basic.seg_1 $(DIR_M65)/BASIC_1_combined.vs $(DIR_M65)/BASIC_1_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_M65) $(DIR_M65)/KERNAL_0_combined.sym $(DIR_M65)/BASIC_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_M65) $(GEN_STR_M65) $(DIR_M65)/KERNAL_0_combined.sym $(DIR_M65)/BASIC_0_combined.sym $(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1_combined.vs $(DIR_M65)/KERNAL_1_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_M65) $(DIR_M65)/KERNAL_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_M65) $(GEN_STR_M65) $(DIR_M65)/KERNAL_0_combined.sym $(DIR_X16)/basic.seg_1 $(DIR_X16)/BASIC_1_combined.vs $(DIR_X16)/BASIC_1_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_X16) $(DIR_X16)/KERNAL_0_combined.sym $(DIR_X16)/BASIC_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_X16) $(GEN_STR_X16) $(DIR_X16)/KERNAL_0_combined.sym $(DIR_X16)/BASIC_0_combined.sym $(DIR_X16)/kernal.seg_1 $(DIR_X16)/KERNAL_1_combined.vs $(DIR_X16)/KERNAL_1_combined.sym: \ - $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_X16) $(DIR_X16)/KERNAL_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_X16) $(GEN_STR_X16) $(DIR_X16)/KERNAL_0_combined.sym $(DIR_CUS)/OUTx_x.BIN: $(DIR_CUS)/OUTB_x.BIN $(DIR_CUS)/OUTK_x.BIN $(DIR_GEN)/OUTx_x.BIN: $(DIR_GEN)/OUTB_x.BIN $(DIR_GEN)/OUTK_x.BIN @@ -254,69 +267,96 @@ build/symbols_ultimate64.vs: $(DIR_U64)/BASIC_combined.vs $(DIR_U64)/KER # Rules - BASIC and KERNAL intermediate files -build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT) - @mkdir -p build/,generated - $(TOOL_COMPRESS_TEXT) > build/,generated/packed_messages.s +$(GEN_STR_CUS): $(TOOL_GENERATE_STRINGS) $(CFG_CUS) + @mkdir -p $(DIR_CUS)/,generated + $(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_CUS) + +$(GEN_STR_GEN): $(TOOL_GENERATE_STRINGS) $(CFG_GEN) + @mkdir -p $(DIR_GEN)/,generated + $(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_GEN) + +$(GEN_STR_TST): $(TOOL_GENERATE_STRINGS) $(CFG_TST) + @mkdir -p $(DIR_TST)/,generated + $(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_TST) + +$(GEN_STR_M65): $(TOOL_GENERATE_STRINGS) $(CFG_M65) + @mkdir -p $(DIR_M65)/,generated + $(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_M65) + +$(GEN_STR_U64): $(TOOL_GENERATE_STRINGS) $(CFG_U64) + @mkdir -p $(DIR_U64)/,generated + $(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_U64) + +$(GEN_STR_X16): $(TOOL_GENERATE_STRINGS) $(CFG_X16) + @mkdir -p $(DIR_X16)/,generated + $(TOOL_GENERATE_STRINGS) -o $@ -c $(CFG_X16) build/,generated/float_constants.s: $(TOOL_GENERATE_CONSTANTS) @mkdir -p build/,generated $(TOOL_GENERATE_CONSTANTS) -o build/,generated/float_constants.s +GEN_STR_custom = $(GEN_STR_CUS) +GEN_STR_generic = $(GEN_STR_GEN) +GEN_STR_testing = $(GEN_STR_TST) +GEN_STR_mega65 = $(GEN_STR_M65) +GEN_STR_ultimate64 = $(GEN_STR_U64) +GEN_STR_cx16 = $(GEN_STR_X16) + .PRECIOUS: build/target_%/OUTB_x.BIN build/target_%/BASIC_combined.vs build/target_%/OUTB_x.BIN build/target_%/BASIC_combined.vs: @mkdir -p build/target_$* @rm -f $@* build/target_$*/BASIC* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r STD -s BASIC -i BASIC-$* -o OUTB_x.BIN -d build/target_$* -l a000 -h e4d2 c64/,,config_$*.s $(SRCDIR_BASIC) $(GEN_BASIC) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r STD -s BASIC -i BASIC-$* -o OUTB_x.BIN -d build/target_$* -l a000 -h e4d2 src/,,config_$*.s $(SRCDIR_BASIC) $(GEN_BASIC) $(GEN_STR_$*) .PRECIOUS: build/target_%/OUTK_x.BIN build/target_%/KERNAL_combined.vs build/target_%/KERNAL_combined.sym build/target_%/OUTK_x.BIN build/target_%/KERNAL_combined.vs build/target_%/KERNAL_combined.sym: @mkdir -p build/target_$* @rm -f $@* build/target_$*/KERNAL* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r STD -s KERNAL -i KERNAL-$* -o OUTK_x.BIN -d build/target_$* -l e4d3 -h ffff c64/,,config_$*.s $(SRCDIR_KERNAL) $(GEN_KERNAL) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r STD -s KERNAL -i KERNAL-$* -o OUTK_x.BIN -d build/target_$* -l e4d3 -h ffff src/,,config_$*.s $(SRCDIR_KERNAL) $(GEN_KERNAL) $(GEN_STR_$*) # Rules - BASIC and KERNAL intermediate files, for Mega65 $(DIR_M65)/OUTB_0.BIN $(DIR_M65)/BASIC_0_combined.vs $(DIR_M65)/BASIC_0_combined.sym: @mkdir -p $(DIR_M65) @rm -f $@* $(DIR_M65)/BASIC_0* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s BASIC_0 -i BASIC_0-mega65 -o OUTB_0.BIN -d $(DIR_M65) -l a000 -h e4d2 $(CFG_M65) $(SRCDIR_BASIC) $(GEN_BASIC) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s BASIC_0 -i BASIC_0-mega65 -o OUTB_0.BIN -d $(DIR_M65) -l a000 -h e4d2 $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_BASIC) $(GEN_BASIC) $(DIR_M65)/OUTK_0.BIN $(DIR_M65)/KERNAL_0_combined.vs $(DIR_M65)/KERNAL_0_combined.sym: @mkdir -p $(DIR_M65) @rm -f $@* $(DIR_M65)/KERNAL_0* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s KERNAL_0 -i KERNAL_0-mega65 -o OUTK_0.BIN -d $(DIR_M65) -l e4d3 -h ffff $(CFG_M65) $(SRCDIR_KERNAL) $(GEN_KERNAL) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s KERNAL_0 -i KERNAL_0-mega65 -o OUTK_0.BIN -d $(DIR_M65) -l e4d3 -h ffff $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_KERNAL) $(GEN_KERNAL) $(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) $(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 5fff $(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) @rm -f $@* $(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s KERNAL_1 -i KERNAL_1-mega65 -o kernal.seg_1 -d $(DIR_M65) -l 4000 -h 5fff $(CFG_M65) $(SRCDIR_KERNAL) $(GEN_KERNAL) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s KERNAL_1 -i KERNAL_1-mega65 -o kernal.seg_1 -d $(DIR_M65) -l 4000 -h 5fff $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_KERNAL) $(GEN_KERNAL) # Rules - BASIC and KERNAL intermediate files, for Commander X16 $(DIR_X16)/OUTB_0.BIN $(DIR_X16)/BASIC_0_combined.vs $(DIR_X16)/BASIC_0_combined.sym: @mkdir -p $(DIR_X16) @rm -f $@* $(DIR_X16)/BASIC_0* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s BASIC_0 -i BASIC_0-x16 -o OUTB_0.BIN -d $(DIR_X16) -l c000 -h e4d2 $(CFG_X16) $(SRCDIR_BASIC) $(GEN_BASIC) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s BASIC_0 -i BASIC_0-x16 -o OUTB_0.BIN -d $(DIR_X16) -l c000 -h e4d2 $(CFG_X16) $(GEN_STR_X16) $(SRCDIR_BASIC) $(GEN_BASIC) $(DIR_X16)/OUTK_0.BIN $(DIR_X16)/KERNAL_0_combined.vs $(DIR_X16)/KERNAL_0_combined.sym: @mkdir -p $(DIR_X16) @rm -f $@* $(DIR_X16)/KERNAL_0* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s KERNAL_0 -i KERNAL_0-x16 -o OUTK_0.BIN -d $(DIR_X16) -l e4d3 -h ffff $(CFG_X16) $(SRCDIR_KERNAL) $(GEN_KERNAL) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s KERNAL_0 -i KERNAL_0-x16 -o OUTK_0.BIN -d $(DIR_X16) -l e4d3 -h ffff $(CFG_X16) $(GEN_STR_X16) $(SRCDIR_KERNAL) $(GEN_KERNAL) $(DIR_X16)/basic.seg_1 $(DIR_X16)/BASIC_1_combined.vs $(DIR_X16)/BASIC_1_combined.sym: @mkdir -p $(DIR_X16) @rm -f $@* $(DIR_X16)/basic.seg_1 $(DIR_X16)/BASIC_1* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s BASIC_1 -i BASIC_1-x16 -o basic.seg_1 -d $(DIR_X16) -l a000 -h bfff $(CFG_X16) $(SRCDIR_BASIC) $(GEN_BASIC) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s BASIC_1 -i BASIC_1-x16 -o basic.seg_1 -d $(DIR_X16) -l a000 -h bfff $(CFG_X16) $(GEN_STR_X16) $(SRCDIR_BASIC) $(GEN_BASIC) $(DIR_X16)/kernal.seg_1 $(DIR_X16)/KERNAL_1_combined.vs $(DIR_X16)/KERNAL_1_combined.sym: @mkdir -p $(DIR_X16) @rm -f $@* $(DIR_X16)/kernal.seg_1 $(DIR_X16)/KERNAL_1* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s KERNAL_1 -i KERNAL_1-x16 -o kernal.seg_1 -d $(DIR_X16) -l a000 -h bfff $(CFG_X16) $(SRCDIR_KERNAL) $(GEN_KERNAL) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r X16 -s KERNAL_1 -i KERNAL_1-x16 -o kernal.seg_1 -d $(DIR_X16) -l a000 -h bfff $(CFG_X16) $(GEN_STR_X16) $(SRCDIR_KERNAL) $(GEN_KERNAL) # Rules - BASIC and KERNAL @@ -368,40 +408,39 @@ build/symbols_hybrid.vs: $(DIR_GEN)/KERNAL_combined.vs # Rules - platform 'Mega65' specific -$(TARGET_M65_x) $(TARGET_M65_x_PXL): $(SEG_LIST_M65) build/chargen_openroms.rom build/chargen_openroms.patched build/chargen_pxlfont.rom build/chargen_pxlfont.patched - dd if=/dev/zero bs=8192 count=1 of=build/m65_padding_08_KB - dd if=/dev/zero bs=8192 count=8 of=build/m65_padding_64_KB +build/padding_08_KB: + dd if=/dev/zero bs=8192 count=1 of=build/padding_08_KB +build/padding_64_KB: + 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 @echo - cat build/m65_padding_08_KB > $(TARGET_M65_x) - cat build/m65_padding_08_KB >> $(TARGET_M65_x) + cat build/padding_08_KB > $(TARGET_M65_x) + cat build/padding_08_KB >> $(TARGET_M65_x) cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x) cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x) - cat build/m65_padding_08_KB >> $(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/m65_padding_64_KB >> $(TARGET_M65_x) + cat build/padding_64_KB >> $(TARGET_M65_x) @echo - cat build/m65_padding_08_KB > $(TARGET_M65_x_PXL) - cat build/m65_padding_08_KB >> $(TARGET_M65_x_PXL) + cat build/padding_08_KB > $(TARGET_M65_x_PXL) + cat build/padding_08_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/m65_padding_08_KB >> $(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) cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x_PXL) - cat build/m65_padding_64_KB >> $(TARGET_M65_x_PXL) - @echo - rm -f build/m65_padding_* + cat build/padding_64_KB >> $(TARGET_M65_x_PXL) @echo # Rules - platform 'Commander X16' specific $(TARGET_X16_x): $(SEG_LIST_X16) build/chargen_openroms.rom - dd if=/dev/zero bs=8192 count=1 of=build/x16_padding_08_KB - dd if=/dev/zero bs=8192 count=8 of=build/x16_padding_64_KB @echo cat $(DIR_X16)/basic.seg_0 > $(TARGET_X16_x) cat $(DIR_X16)/kernal.seg_0 >> $(TARGET_X16_x) @@ -409,8 +448,6 @@ $(TARGET_X16_x): $(SEG_LIST_X16) build/chargen_openroms.rom cat $(DIR_X16)/basic.seg_1 >> $(TARGET_X16_x) cat $(DIR_X16)/kernal.seg_1 >> $(TARGET_X16_x) @echo - rm -f build/x16_padding_* - @echo # Rules - tests @@ -436,8 +473,8 @@ test_testing: build/kernal_testing.rom build/basic_testing.rom build/symbols_tes test_ultimate64: build/kernal_ultimate64.rom build/basic_ultimate64.rom build/symbols_ultimate64.vs x64 -kernal build/kernal_ultimate64.rom -basic build/basic_ultimate64.rom -moncommands build/symbols_ultimate64.vs -1 $(TESTTAPE) -8 $(TESTDISK) -test_mega65: $(TARGET_M65_x) $(TARGET_M65_PXL) - ../xemu/build/bin/xmega65.native -dmarev 2 -forcerom -loadrom $(TARGET_M65_x) +test_mega65: $(TARGET_M65_x) $(TARGET_M65_x_PXL) + ../xemu/build/bin/xmega65.native -dmarev 2 -besure -fontrefresh -forcerom -loadrom $(TARGET_M65_x_PXL) test_cx16: $(TARGET_X16_x) ../x16-emulator/x16emu -rom $(TARGET_X16_x) diff --git a/README.md b/README.md index 4f8186b0..aa1af581 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ 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) * [development guide](./doc/Development.md) for those interested in OpenROMs technical aspects * [license](./LICENSE) information and list of major contributors * [credits](./CREDITS.md) to people whose work was of great help to us diff --git a/STATUS.md b/STATUS.md index e8013b30..145e4a86 100644 --- a/STATUS.md +++ b/STATUS.md @@ -10,19 +10,21 @@ 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) * turbo tape load support (as device 7, or using `←L`), 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) * tape format autodetection; normal vs turbo is mostly transparent to user * 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 `LOAD` command +* 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 - * secondary address over 255 is considered a start address + * command without parameters tries to load first file from drive chosen as above -* uses RAM under ROM and I/O: 61438 bytes free -* cold/warm start silences multiple SID chips - all $D4xx and $D5xx addresses, configured addresses +* 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 @@ -40,8 +42,8 @@ The following ROM features are currently missing: * most BASIC commands * BASIC variables -* BASIC expression parsing -* floating point routines +* BASIC expression handling +* most floating point routines * RS-232 support * NMI handling is incomplete @@ -143,7 +145,7 @@ Status of the various APIs and variables from the original ROMs ## Low memory locations (pages 0 - 3) -For the current status of the low memory location implementation andd usage check [this file](c64/aliases/,aliases_ram_lowmem.s). NOTE: available vector to certain routine does not mean that this routine is fully implemented! +For the current status of the low memory location implementation andd usage check [this file](src/aliases/,aliases_ram_lowmem.s). NOTE: available vector to certain routine does not mean that this routine is fully implemented! ## BASIC @@ -282,7 +284,7 @@ Not all of them - only these we want to have implemented. | `$A68E` | `RUNC` | DONE | | | `$A7AE` | `NEWSTT` | PARTIAL | redirected to RUN command | | `$AB1E` | `STROUT` | DONE | | -| `$AD9E` | `FRMEVL` | NOT DONE | | +| `$AD9E` | `FRMEVL` | PARTIAL | | | `$BDCD` | `LINPRT` | DONE | temporary implementation | | `$E3BF` | `INIT` | NOT DONE | | | `$E422` | `INITMSG` | DONE | | diff --git a/assembler/KickAss.jar b/assembler/KickAss.jar index 1ea5cc88..77fa9f23 100644 Binary files a/assembler/KickAss.jar and b/assembler/KickAss.jar differ diff --git a/assembler/KickAssembler.pdf b/assembler/KickAssembler.pdf index 907579f9..2ef23c87 100644 Binary files a/assembler/KickAssembler.pdf and b/assembler/KickAssembler.pdf differ diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 90679647..90052287 100644 Binary files a/bin/basic_generic.rom and b/bin/basic_generic.rom differ diff --git a/bin/basic_testing.rom b/bin/basic_testing.rom deleted file mode 100644 index d062189e..00000000 Binary files a/bin/basic_testing.rom and /dev/null differ diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom index 57b76a75..b84cd139 100644 Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 1b49889f..06a5a7fb 100644 Binary files a/bin/kernal_generic.rom and b/bin/kernal_generic.rom differ diff --git a/bin/kernal_testing.rom b/bin/kernal_testing.rom deleted file mode 100644 index bf78fb72..00000000 Binary files a/bin/kernal_testing.rom and /dev/null differ diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index b0d12b36..9f4108ff 100644 Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ diff --git a/bin/mega65.rom b/bin/mega65.rom index 9db58314..6c788321 100644 Binary files a/bin/mega65.rom and b/bin/mega65.rom differ diff --git a/bin/mega65_pxlfont.rom b/bin/mega65_pxlfont.rom index 3389f9fa..2b2c51e8 100644 Binary files a/bin/mega65_pxlfont.rom and b/bin/mega65_pxlfont.rom differ diff --git a/c64/basic/,stubs/ad9e.frmevl.s b/c64/basic/,stubs/ad9e.frmevl.s deleted file mode 100644 index 46f275ed..00000000 --- a/c64/basic/,stubs/ad9e.frmevl.s +++ /dev/null @@ -1,10 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - - -// XXX provide documentation and implementation - -FRMEVL: - STUB_IMPLEMENTATION() diff --git a/c64/basic/basic_do_error.s b/c64/basic/basic_do_error.s deleted file mode 100644 index f4f21fd4..00000000 --- a/c64/basic/basic_do_error.s +++ /dev/null @@ -1,41 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// Computes Mapping the 64 p93 - -basic_do_error: - - // Save error number - phx_trash_a - -#if ROM_LAYOUT_M65 - // Restore normal memory map - jsr map_NORMAL -#endif - - // Print ? at start - jsr print_return - lda #$3F - jsr JCHROUT - - // Print main part of error message - plx_trash_a - jsr print_packed_message - - // Print ERROR at end - jsr print_space - ldx #33 - jsr print_packed_message - - // XXX print IN if not in direct mode - - // XXX print line number if not in direct mode - - jsr print_return - jsr print_return - - // Reset stack, and go back to main loop - ldx #$FE - txs - jmp basic_main_loop diff --git a/c64/basic/basic_execute_line.s b/c64/basic/basic_execute_line.s deleted file mode 100644 index 9268327a..00000000 --- a/c64/basic/basic_execute_line.s +++ /dev/null @@ -1,371 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// Jump back into the BASIC execute line loop -// after first checking that we have a colon -// or $00 char - -basic_end_of_statement_check: - ldy #0 - -#if CONFIG_MEMORY_MODEL_60K - ldx #OLDTXT - // .byte $f0,OLDTXT - // .text ", STATEMENT PTR = $" - // .byte $f1,TXTPTR - // .byte $f0,TXTPTR - // .byte $d,0 - - // Go through the line until its end is reached. - // If we reach the end are in direct mode, then - // go back to reading input, else look for the - // next line, and advance to that, or else - // return to READY prompt because we have run out - // of program. - - // Get next char of program text, even if it is hiding under a ROM or the - // IO area. - - ldy #0 - -#if CONFIG_MEMORY_MODEL_60K - ldx #cmd_load_default_filename - jsr JSETNAM - jmp got_filename - -cmd_load_default_filename: - - .text "*" - -#endif - -!: - jsr basic_fetch_and_consume_character - cmp #$22 - beq !+ - jmp do_SYNTAX_error -!: - // Filename starts here so set pointer - lda TXTPTR+0 - sta FNADDR+0 - lda TXTPTR+1 - sta FNADDR+1 - - // Now search for end of line or closing quote - // so that we know the length of the filename -getting_filename: - jsr basic_fetch_and_consume_character - cmp #$22 - beq got_filename - cmp #$00 - bne !+ - jsr basic_unconsume_character - - jmp got_filename -!: - inc FNLEN - jmp getting_filename - -got_filename: - - // Now fetch the file number, start from the default one - jsr select_device - stx FA - jsr injest_comma - bcs got_devicenumber - - jsr basic_parse_line_number - lda LINNUM+1 - beq !+ - jmp do_ILLEGAL_QUANTITY_error -!: - lda LINNUM+0 - sta FA - -got_devicenumber: - - // Now fetch the secondary address - lda #$00 - sta SA - jsr injest_comma - bcs cmd_load_got_secondaryaddress - jsr basic_parse_line_number - lda LINNUM+1 - bne !+ - lda LINNUM+0 - sta SA - jmp cmd_load_got_secondaryaddress -!: - // Second parameter is above 255, this can not be a secondary address - // Use it as load address instead - // XXX temporary syntax, it would be better to use something - // XXX like 'LOAD"FILE",8 TO 49152' - ldx LINNUM+0 - ldy LINNUM+1 - bne got_loadaddress - -cmd_load_got_secondaryaddress: // input for tape wedge - ldy TXTTAB+1 - ldx TXTTAB+0 - -got_loadaddress: - lda #$00 // LOAD not verify - jsr JLOAD - php - pha - jsr print_return - pla - plp - bcc load_no_error - - // A = KERNAL error code, which also almost match - // basic ERROR codes - tax - dex - bpl !+ - ldx #B_ERR_BREAK -!: - jmp do_basic_error - -load_no_error: - // $YYXX is the last loaded address, so store it - stx VARTAB+0 - sty VARTAB+1 - - // Now relink the loaded program, as we cannot trust the line - // links supplied. For example, the VICE virtual drive emulation - // always supplies $0101 as the address of the next line. - jsr LINKPRG - - // After LOADing, we either start the program from the beginning, - // or go back to the READY prompt if LOAD was called from direct mode. - - // Reset to start of program - jsr init_oldtxt - - // XXX - should run program if LOAD was used in program mode - jmp basic_main_loop diff --git a/c64/basic/commands/cmd_unimplemented.s b/c64/basic/commands/cmd_unimplemented.s deleted file mode 100644 index 59407688..00000000 --- a/c64/basic/commands/cmd_unimplemented.s +++ /dev/null @@ -1,160 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Default handler for all not-yet-implemented commands -// -// Note: NOPs are here just to make debugging easier! -// - -cmd_for: - nop -cmd_next: - nop -cmd_data: - nop -cmd_inputhash: - nop -cmd_input: - nop -cmd_dim: - nop -cmd_read: - nop -cmd_let: - nop -cmd_if: - nop -cmd_restore: - nop -cmd_gosub: - nop -cmd_return: - nop - - // $90-$9F - -cmd_on: - nop -cmd_wait: - nop -cmd_save: - nop -cmd_verify: - nop -cmd_def: - nop -cmd_poke: - nop -cmd_printhash: - nop -cmd_print: - nop -cmd_cont: - nop -cmd_cmd: - nop -cmd_open: - nop - - // $A0-$AF - -cmd_close: - nop -cmd_get: - nop -cmd_tab: - nop -cmd_to: - nop -cmd_fn: - nop -cmd_spc: - nop -cmd_then: - nop -cmd_not: - nop -cmd_step: - nop -cmd_plus: - nop -cmd_minus: - nop -cmd_mult: - nop -cmd_div: - nop -cmd_exponent: - nop -cmd_and: - nop - - // $B0-$BF - -cmd_or: - nop -cmd_greater: - nop -cmd_equal: - nop -cmd_less: - nop -cmd_sgn: - nop -cmd_int: - nop -cmd_abs: - nop -cmd_usr: - nop -cmd_fre: - nop -cmd_pos: - nop -cmd_sqr: - nop -cmd_rnd: - nop -cmd_log: - nop -cmd_exp: - nop -cmd_cos: - nop -cmd_sin: - nop - - // $C0-$CF - -cmd_tan: - nop -cmd_atn: - nop -cmd_peek: - nop -cmd_len: - nop -cmd_str: - nop -cmd_val: - nop -cmd_asc: - nop -cmd_chr: - nop -cmd_left: - nop -cmd_right: - nop -cmd_mid: - nop -cmd_go: - nop - - // Undefined tokens - -cmd_unimplemented: - - jmp do_NOT_IMPLEMENTED_error diff --git a/c64/basic/injest_comma.s b/c64/basic/injest_comma.s deleted file mode 100644 index 2e59ead9..00000000 --- a/c64/basic/injest_comma.s +++ /dev/null @@ -1,23 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - - -// Consummes a comma in a BASIC code, C set for no coma found - -injest_comma: - - jsr basic_fetch_and_consume_character - cmp #$2C // comma character - beq injest_comma_found - cmp #$20 // space, can always be skipped - beq injest_comma - - // not found - jsr basic_unconsume_character - sec - rts - -injest_comma_found: - clc - rts diff --git a/c64/basic/pack_word.s b/c64/basic/pack_word.s deleted file mode 100644 index d975ca38..00000000 --- a/c64/basic/pack_word.s +++ /dev/null @@ -1,260 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# M65 BASIC_1 #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// Pack a word using the simple compression scheme. -// This has to be the same implementation as in compress_text.c -// because we compress input lines of BASIC to do the tokenisation. -// This allows us to search through the compressed tokens directly -// using the compressed fragment of BASIC, and thus work out the -// token for a given piece of string. -// This also helps ensure that we have an implementation that is totally -// different to that of the original C64 BASIC, as well as likely -// saving a bit of space in the ROM, especially once we start implementing -// larger keyword vocabs for BASIC 7 or BASIC 10 compatibility, since the -// compression and decompression machinery is of fixed size. - -pack_word: - // Inputs: - // X = offset of string to pack. Address is $0200 + X - // __tokenise_work1 = number of bytes to pack - // __tokenise_work2 = packed length of string - - // Outputs: - // Output is written to $0100 (bottom of stack). - - // Memory modified: - // __tokenise_work4 = temporary storage - // __tokenise_work3 = flag for whether we have a nybl prepared or not. - // (This can also be checked on exit, to know whether the last byte - // is incomplete, which is important for searching for abbreviated - // key words.) - - - // Make sure we have a sane request - lda __tokenise_work1 - bne !+ - sec - rts -!: - // Initialise internal variables - lda #$00 - sta __tokenise_work2 - sta __tokenise_work3 - -pack_char_loop: - - // Get the next char - lda $0200,x - - // Work out what type of character we have, and thus - // how we need to pack it. - jsr get_packed_char_index - - cmp #$00 - bne not_exception_char - - // Char is an exception char. - // We need to either finish the previous byte with $xF, - // Or if there is no existing nybl, then we need to output - // either $FE or $FF, depending on whether this is the last - // byte or not - - lda __tokenise_work3 - bne have_nybl_before_exception_char - - // No nybl exists before the exception char, so prefix with $FE or $FF - // based on whether we are at the end of the input string or not - inx - lda __tokenise_work1 - cmp #$01 - beq at_end - lda #$FF - .byte $2C -at_end: - lda #$FE - dex - jsr write_unpacked_char - // Fall through - -output_exception_byte: - lda $0200,x - jsr write_unpacked_char - jmp consider_next_char - -have_nybl_before_exception_char: - // Or existing byte with #$0F, and clear nybl flag - ldy __tokenise_work2 - lda $0100,y - ora #$0f - sta $0100,y - inc __tokenise_work2 - - // FALL THROUGH - -write_literal_and_terminate_if_required: - - // Clear have nybl flag - lda #$00 - sta __tokenise_work3 - - lda $0200,x - jsr write_unpacked_char - - jmp end_string_if_required - -end_string_if_required: - // Check if X points to last char of string to be packed - inx - lda __tokenise_work1 - cmp #$01 - beq !+ - dex - jmp consider_next_char -!: - dex - // Fall through - -end_string: - // Write end of string sequence if required - lda #$00 - jsr write_unpacked_char - rts - -write_unpacked_char: - ldy __tokenise_work2 - sta $0100,y - iny - sty __tokenise_work2 - rts - -not_exception_char: - // It wasn't an exception char, so write the symbol out - cmp #$10 - bcs whole_byte_symbol - - // Nybl encoded value: Put in upper half or lower half of a byte? - ldy __tokenise_work3 - bne store_low_nybl - - // Store in high nybl -- so shift it into the hi nybl - asl - asl - asl - asl - ldy __tokenise_work2 - sta $0100,y - bne stored_nybl // Must be taken, as A cannot be $00 - -store_low_nybl: - // Low nybl gets added to high nybl already stored in the byte - ldy __tokenise_work2 - ora $0100,y - sta $0100,y - -stored_nybl: - // Now toggle the nybl flag - lda __tokenise_work3 - eor #$ff - sta __tokenise_work3 - // And advance the offset if we filled this byte up - bne consider_next_char // Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free - - // Count the filled up byte - inc __tokenise_work2 - - // Add termination byte if required - // (This re-writes the same byte again, which we don't care about) - jmp end_string_if_required - -whole_byte_symbol: - // It's a $Fx symbol. - // But if we have a nybl to flush, then we handle it like - // a full exception character - - ldy __tokenise_work3 - beq nothing_to_flush - - // Set low nybl to $F to mark next byte as literal - ldy __tokenise_work2 - lda $0100,y - ora #$0f - sta $0100,y - inc __tokenise_work2 - - jmp write_literal_and_terminate_if_required - -nothing_to_flush: - // Write the symbol as it is, or the literal - // if it has been passed to us via fall-through - jsr write_unpacked_char - - jmp end_string_if_required - -consider_next_char: - // Pack next char - inx - dec __tokenise_work1 - beq !+ - jmp pack_char_loop -!: - // Add 1 to length if nybl waiting to be flushed - // (but leave flag set so the caller knows if the - // bottom nybl might be different if the string were - // longer). - lda __tokenise_work3 - beq !+ - inc __tokenise_work2 - rts -!: - // Last byte was full, so we need at $00 on the end - // (unless a $FE token was written 2 bytes ago) - ldy __tokenise_work2 - iny - lda #$00 - sta $0100,y - inc __tokenise_work2 - - rts - -get_packed_char_index: - // Find char in A in the packed char list, and return - // $1 - $E, $F1 - $FD if the charactar is abbreviable, - // or else return $00 if the character has to be stored literally. - - // Y register and A are modified, as are processor flags. - - ldy #$00 -find_char_loop: - cmp packed_message_chars,y - bne not_a_match -enumerate: - // Is it a nybl abbreviable char? - cpy #14 - bcs not_nybl_char - // Yes, so add 1 and return it - iny - tya - rts - -not_nybl_char: - cpy #27 - bcs not_a_match - // It's a $Fx character. - // Since the lowest index is $E, and it should be encoded as $F1 - // we need to add $E3 - tya - clc - adc #$E3 - rts - -not_a_match: - iny - // Loop until we find it, or we discover it isn't - // a character with a special encoding - cpy #27 - bne find_char_loop - // Not a char that we can pack, so return 0 - lda #$00 - rts diff --git a/c64/basic/print/list_single_line.s b/c64/basic/print/list_single_line.s deleted file mode 100644 index 64e6b2b4..00000000 --- a/c64/basic/print/list_single_line.s +++ /dev/null @@ -1,134 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# M65 * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -list_single_line: - -#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) - - jsr map_BASIC_1 - jsr_ind VB1__list_single_line - jmp map_NORMAL - -#else - - // Print line number - ldy #3 - -#if ROM_LAYOUT_M65 - jsr peek_via_OLDTXT -#elif CONFIG_MEMORY_MODEL_60K - jsr peek_under_roms -#else - lda (OLDTXT),y -#endif - - pha - dey - -#if ROM_LAYOUT_M65 - jsr peek_via_OLDTXT -#elif CONFIG_MEMORY_MODEL_60K - jsr peek_under_roms -#else - lda (OLDTXT),y -#endif - - tax - pla - jsr print_integer - jsr print_space - - // Iterate through printing out the line - // contents - lda #0 - sta QTSW - - ldy #4 - -list_print_loop: - -#if ROM_LAYOUT_M65 - jsr peek_via_OLDTXT -#elif CONFIG_MEMORY_MODEL_60K - ldx #packed_keywords - sta FRESPC+1 - - // Subtract $80 from token to get offset in word - // list - txa - and #$7f - tax - - // Now ask for it to be printed - ldy #$ff - jsr packed_word_search - - ply_trash_a - pla - - cmp #$8f - bne list_not_rem - // REM command locks quote flag on until the end of the line, allowing - // funny characters in REM statements without problem. - sta QTSW // Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here - // FALL THROUGH -list_not_rem: - - iny - bne list_print_loop // branch always - -list_is_pi: - lda #$7E - - // FALLTROUGH - -list_is_literal: - jsr JCHROUT - iny - bne list_print_loop - -list_end_of_line: - // Print end of line - jmp print_return - - -#endif // ROM layout diff --git a/c64/basic/print/print_packed_message.s b/c64/basic/print/print_packed_message.s deleted file mode 100644 index 7a062e6a..00000000 --- a/c64/basic/print/print_packed_message.s +++ /dev/null @@ -1,244 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# M65 * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// This routine prints messages that have been packed -// using the make_error_tables program. -// The general idea is to save space in the ROM. - -// The output of make_error_tables is written to packed_messages.s, and -// contains the following: -// -// packed_message_words - List of nybl packed words. -// packed_message_tokens - List of tokens that get joined to make messages -// packed_message_chars - List of characters in messages sorted by frequency. - - -print_packed_message: - // .X = message number - -#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) - - jsr map_BASIC_1 - jsr_ind VB1__print_packed_message - jmp map_NORMAL - -#else - - lda #$ff - ldy #$ff -packed_message_search: - iny - cpx #$00 - beq found_message_in_token_stream - lda packed_message_tokens,y - cmp #$ff - bne !+ - dex -!: - cpy #$ff - bne packed_message_search - // Could not find message - sec - rts - -found_message_in_token_stream: // XXX size-optimize this - // Now print each word in the message - phy_trash_a - lda packed_message_tokens,y - cmp #$FF - beq found_message_in_token_stream_done - - jsr print_packed_word - ply_trash_a - iny - beq found_message_in_token_stream_done -!: - phy_trash_a - lda packed_message_tokens,y - cmp #$FF - beq found_message_in_token_stream_done - - pha - jsr print_space - pla - - jsr print_packed_word - ply_trash_a - iny - bne !- - -found_message_in_token_stream_done: - pla - rts - -print_packed_word: - // A = the word to print - tax - - // Setup pointer to packed words - lda #packed_message_words - sta FRESPC+1 - - // Find the word in the list - ldy #$ff -packed_word_search: - iny - cpx #$00 - beq found_packed_word - - // $x0 is an end of work marker - lda (FRESPC),y - and #$0f - cmp #$00 - bne !+ - dex -!: - // $FE $xx is an end of work marker - lda (FRESPC),y - cmp #$fe - bne !+ - dex - iny // skip next byte -!: - cmp #$ff - bne !+ - iny // skip next byte -!: - - // Advance to next page if required - cpy #$ff - bne packed_word_search - inc FRESPC+1 - jmp packed_word_search - -found_packed_word: - - // Get pointer to start of packed word - // Make sure we do not wrap on a page boundary - tya - clc - adc FRESPC+0 - sta FRESPC+0 - lda FRESPC+1 - adc #$00 - sta FRESPC+1 - -print_packed_string: - ldy #$ff - -next_packed_word_char: - // .Y = offset into packed word data - 1 - iny - - // Check for end of word - lda (FRESPC),y - cmp #$00 - beq end_of_packed_word - cmp #$fe - beq last_literal - cmp #$ff - beq next_is_literal_char - and #$f0 - beq end_of_packed_word - - // Check if it is an uncommon char - lda (FRESPC),y - and #$f0 - cmp #$f0 - beq is_uncommon_char - - // Is not an uncommon char, so get char of upper nybl - lda (FRESPC),y - - // Put high nybl into low bits of X - lsr - lsr - lsr - lsr - tax - - // X=1-14 = first 14 chars, so subtract one - lda packed_message_chars-1,x - jsr JCHROUT // preserves .Y - - // See if there is a char in the low nybl to print - lda (FRESPC),y - and #$0f - beq end_of_packed_word - cmp #$0f - beq no_lo_nybl_char - -has_lo_nybl_char: - // We need to print the low nybl char as well - tax - phy_trash_a - - // Skip lower nybls of $F or $0 in nybl packed - // bytes, as these do not encode characters - cpx #$f - beq !+ -has_nybl: - cpx #0 - beq !+ - - // X=1-14 = first 14 chars, so subtract one - lda packed_message_chars-1,x - jsr JCHROUT -!: - ply_trash_a - // FALLTHROUGH - -no_lo_nybl_char: - - // If current byte has $0F in low nybl, then the next - // byte is a whole byte. - lda (FRESPC),y - and #$0f - cmp #$0f - beq next_is_literal_char - -ready_for_next_char: - cpy #$ff - bne next_packed_word_char -end_of_packed_word: - // Hit end of packed data - rts - -last_literal: - jsr unpack_literal_char - rts - -next_is_literal_char: - jsr unpack_literal_char - jmp ready_for_next_char - -unpack_literal_char: - // Output the literal char, and ready for next char - iny - phy_trash_a - lda (FRESPC),y - jsr JCHROUT - pla - tay - rts - -is_uncommon_char: - // Lower nybl has offset into low-frequency part of the table - - lda (FRESPC),y - and #$0f - clc - adc #14 - - // We need to print the low nybl char as well - tax - phy_trash_a - - jmp has_nybl - - -#endif // ROM layout diff --git a/c64/basic/tokenise_line.s b/c64/basic/tokenise_line.s deleted file mode 100644 index 0678658b..00000000 --- a/c64/basic/tokenise_line.s +++ /dev/null @@ -1,283 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# M65 * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// Tokenise a line of BASIC -// Stored at $0200 -// Length in __tokenise_work1 - -tokenise_line: - -#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) - - jsr map_BASIC_1 - jsr_ind VB1__tokenise_line - jmp map_NORMAL - -#else - - // We need to consider each offset in the string to see if it matches - // a token. No BASIC keyword is > 7 bytes, so we need to start with that - // length (or remaining length of string) and count our way back down. - // This means we need separate start and end points to keep track of. - - // $0110 = offset into string - // $0111 = number of bytes to pack - // $0112 = offset into tokenised output - // $0113 = length of raw string - - lda #$00 - sta $0110 - sta $0112 - sta QTSW - - lda __tokenise_work1 - sta $0113 - -tokenise_char: - - // Check if we have reached end of the line? - lda $0110 - cmp $0113 - bne !+ - - // End of line reached - - // Finished tokenising line - // Update __tokenise_work1 and terminate with null - ldx $0112 - lda #$00 - sta $0200,x - stx __tokenise_work1 - - // Clear quote mode flag that is also used by KERNAL for screen display - lda #$00 - sta QTSW - rts -!: - // More to do - - // Maximum keyword length - lda #7 - sta $0111 - -tokenise_char_loop: - // Pack the word from the start (start = X, raw len = __tokenise_work1) - // Returns packed length in __tokenise_work2 and writes the packed - // word at $0100+ - - ldx $0110 - lda $0200,x - cmp #$22 - bne tk_not_quote - - // Quote - lda QTSW - eor #$ff - sta QTSW - jmp tk_literal_char - -tk_not_quote: - // Check for literal characters in various ranges - // (This just speeds the tokeniser up, by avoiding the packed token search - // for such characters). - - // SPACE and punctuation before +,- and * - cmp #$2a - bcc tk_literal_char - // Don't try to tokenise digits - cmp #$30 - bcc tk_might_be_keyword - cmp #$3a - bcs tk_might_be_keyword - jmp tk_literal_char - -tk_might_be_keyword: - // Don't tokenise in quote mode - lda QTSW - bne tk_literal_char - - // Pack string - ldx $0110 - lda $0111 - sta __tokenise_work1 - - // XXX - We should implement an optimisation where we - // trim the last symbol of successively, instead of re-packing the word - // again with one less char each time. - // XXX - We should limit the word length to the length of interesting chars - // that are available. - - jsr pack_word - lda __tokenise_work2 - cmp #$10 - bcc !+ - // Packed string too long - jmp do_STRING_TOO_LONG_error -!: - - // Search for it in keywords - jsr keyword_search - - // Did we find a keyword? - bcc found_token_in_line - - // Nope, so try shorter - dec $0111 - bne tokenise_char_loop - -tk_literal_char: - // Is not a token, so copy to output verbatim - ldx $0110 - ldy $0112 - lda $0200,x - sta $0200,y - inc $0112 - inc $0110 - - // Tokenise next char - jmp tokenise_char - -found_token_in_line: - - // Got a token, so write it out - ldx $0112 - sta $0200,x - inx - stx $0112 - - // If it is REM, then lock us in quote mode to the end of the line - cmp #$8f - bne not_rem - sta QTSW -not_rem: - - // Now skip over the length of the token - lda $0110 - clc - adc $0111 - sta $0110 - - // See if there is more of the line left to process - jmp tokenise_char - - - - - // Search for word in keyword list - // The packed form is canonical, so we can search for the keyword while - // it remains compressed. This also saves a little time. - // Algorithm is simply to find matching first bytes, and then look for - // the rest being a match. - -keyword_search: - // Search for the compressed keyword stored at $0100 in the list - // of compressed keywords - - // __tokenise_work1 = offset in line of input - // __tokenise_work2 = length of token we are matching - // __tokenise_work3 = offset in token list - // __tokenise_work5 = temporary work space - // X and Y registers used as temporary space. - // returns C=1 if no matching token, else C=0 and A=token - - lda #$00 - sta __tokenise_work1 - sta __tokenise_work3 -next_kw_offset: - // Advance offset in compressed keyword list, to see if a match - // BEGINS here - - // Get count of bytes to compare - lda __tokenise_work2 - sta __tokenise_work5 - - // Load current position - ldy __tokenise_work3 - ldx __tokenise_work1 - - // Advance offset in compressed token list, and stop at the end - inc __tokenise_work3 - lda __tokenise_work3 - cmp #packed_keyword_table_len - bne next_in_match - jmp done_searching_for_token -next_in_match: - lda $0100,x - cmp packed_keywords,y - bne next_kw_offset - // Advance to next chars in source and target - inx - iny - - dec __tokenise_work5 // Have we compared all bytes yet? - - bne next_in_match - - // Keyword matches! - - // Now make sure we started on a keyword boundary - // (we know we finished on one, because of the structure of the compressed - // keyword data). - // Offset 0 - // previous byte is $x0 - // two byte prior is $FE - - // Get offset of first byte of this token - ldx __tokenise_work3 - dex // pointer points one late, so rewind it - - // At start of list? - cpx #$00 - beq word_boundary - dex - // Previous byte is $x0 end token? - lda packed_keywords,x - and #$0f - beq word_boundary - dex - // Uber-previouss byte is $FE final literal token? - lda packed_keywords,x - cmp #$fe - beq word_boundary - - // Not a word boundary, so ignore - jmp next_kw_offset - -word_boundary: - // Found a token whose offset is in __tokenise_work3 - // Now trace back to the start of the compressed keyword list - // to work out what keyword number we are, so that we can return - // the token number. - - ldy #$80 - -token_count_loop: - lda packed_keywords,x - cmp #$fe - bne !+ - iny -!: - and #$0f - cmp #$00 - bne !+ - iny -!: - cpx #$00 - beq !+ - dex - jmp token_count_loop -!: - - tya - clc - rts - -done_searching_for_token: - // No token found - sec - lda #$00 - rts - -#endif // ROM layout diff --git a/c64/basic/wedge_tape.s b/c64/basic/wedge_tape.s deleted file mode 100644 index ffc41f27..00000000 --- a/c64/basic/wedge_tape.s +++ /dev/null @@ -1,38 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - - -#if CONFIG_TAPE_WEDGE - - -// .X has to contain size of the buffer - -wedge_tape: - - lda #$FF - sta CURLIN+1 // in case of error do not print line number - - cpx #$02 - bne_16 do_SYNTAX_error - - lda BUF+1 - cmp #$4C // 'L' - bne_16 do_SYNTAX_error - - // Execute 'arrow + L' - - lda #$00 - sta FNLEN - - ldy #$01 - ldx #$07 // turbo tape device - jsr JSETFLS - - ldy TXTTAB+1 - ldx TXTTAB+0 - - jmp cmd_load_got_secondaryaddress - - -#endif // CONFIG_TAPE_WEDGE diff --git a/c64/kernal/interrupts/hw_entry_nmi.s b/c64/kernal/interrupts/hw_entry_nmi.s deleted file mode 100644 index 2ed19829..00000000 --- a/c64/kernal/interrupts/hw_entry_nmi.s +++ /dev/null @@ -1,24 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - - -hw_entry_nmi: - - sei // do not allow IRQ to interfere, see https://www.c64-wiki.com/wiki/Interrupt - -#if CONFIG_CPU_MOS_6502 && CONFIG_BCD_SAFE_INTERRUPTS - cld // clear decimal flag to allow using it without disabling interrupts -#endif - - // Call interrupt routine (only if initialised) - pha - lda NMINV - ora NMINV+1 - beq !+ - pla - jmp (NMINV) -!: - // Vector not initialized - call default interrupt routine - pla - jmp default_nmi_handler diff --git a/c64/kernal/print/print_features.s b/c64/kernal/print/print_features.s deleted file mode 100644 index c4b4c0ae..00000000 --- a/c64/kernal/print/print_features.s +++ /dev/null @@ -1,17 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Print configured features on startup banner -// - -#if CONFIG_SHOW_FEATURES - -print_features: - - ldx #__MSG_KERNAL_FEATURES -!: - jmp print_kernal_message - -#endif // CONFIG_SHOW_FEATURES diff --git a/c64/kernal/print/print_pal_ntsc.s b/c64/kernal/print/print_pal_ntsc.s deleted file mode 100644 index d005a63f..00000000 --- a/c64/kernal/print/print_pal_ntsc.s +++ /dev/null @@ -1,20 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Print video system on startup banner -// - -#if CONFIG_SHOW_PAL_NTSC - -print_pal_ntsc: - - ldx #__MSG_KERNAL_NTSC - lda TVSFLG - beq !+ - ldx #__MSG_KERNAL_PAL -!: - jmp print_kernal_message - -#endif // CONFIG_SHOW_PAL_NTSC diff --git a/c64/kernal/screen/chrout_screen_jumptable_codes.s b/c64/kernal/screen/chrout_screen_jumptable_codes.s deleted file mode 100644 index 66e56e74..00000000 --- a/c64/kernal/screen/chrout_screen_jumptable_codes.s +++ /dev/null @@ -1,130 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 * #IGNORE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Jumptable for screen control codes support. To improve performance, should be sorted -// starting from the least probable routine. -// - - -chrout_screen_jumptable_codes: - - .byte KEY_CLR - .byte KEY_HOME - .byte KEY_SHIFT_OFF - .byte KEY_SHIFT_ON - .byte KEY_TXT - .byte KEY_GFX - .byte KEY_RVS_OFF - .byte KEY_RVS_ON - .byte KEY_CRSR_RIGHT - .byte KEY_CRSR_LEFT - .byte KEY_CRSR_DOWN - .byte KEY_CRSR_UP - .byte KEY_INS - -__chrout_screen_jumptable_quote_guard: - -#if CONFIG_EDIT_STOPQUOTE - .byte KEY_STOP -#endif -#if CONFIG_EDIT_TABULATORS - .byte KEY_TAB_BW - .byte KEY_TAB_FW -#endif - .byte KEY_DEL - .byte KEY_RETURN - -__chrout_screen_jumptable_codes_end: - - -#if !HAS_OPCODES_65C02 - -chrout_screen_jumptable_lo: - - .byte <(chrout_screen_CLR - 1) - .byte <(chrout_screen_HOME - 1) - .byte <(chrout_screen_SHIFT_OFF - 1) - .byte <(chrout_screen_SHIFT_ON - 1) - .byte <(chrout_screen_TXT - 1) - .byte <(chrout_screen_GFX - 1) - .byte <(chrout_screen_RVS_OFF - 1) - .byte <(chrout_screen_RVS_ON - 1) - .byte <(chrout_screen_CRSR_RIGHT - 1) - .byte <(chrout_screen_CRSR_LEFT - 1) - .byte <(chrout_screen_CRSR_DOWN - 1) - .byte <(chrout_screen_CRSR_UP - 1) - .byte <(chrout_screen_INS - 1) -#if CONFIG_EDIT_STOPQUOTE - .byte <(chrout_screen_STOP - 1) -#endif -#if CONFIG_EDIT_TABULATORS - .byte <(chrout_screen_TAB_BW - 1) - .byte <(chrout_screen_TAB_FW - 1) -#endif - .byte <(chrout_screen_DEL - 1) - .byte <(chrout_screen_RETURN - 1) - -chrout_screen_jumptable_hi: - - .byte >(chrout_screen_CLR - 1) - .byte >(chrout_screen_HOME - 1) - .byte >(chrout_screen_SHIFT_OFF - 1) - .byte >(chrout_screen_SHIFT_ON - 1) - .byte >(chrout_screen_TXT - 1) - .byte >(chrout_screen_GFX - 1) - .byte >(chrout_screen_RVS_OFF - 1) - .byte >(chrout_screen_RVS_ON - 1) - .byte >(chrout_screen_CRSR_RIGHT - 1) - .byte >(chrout_screen_CRSR_LEFT - 1) - .byte >(chrout_screen_CRSR_DOWN - 1) - .byte >(chrout_screen_CRSR_UP - 1) - .byte >(chrout_screen_INS - 1) -#if CONFIG_EDIT_STOPQUOTE - .byte >(chrout_screen_STOP - 1) -#endif -#if CONFIG_EDIT_TABULATORS - .byte >(chrout_screen_TAB_BW - 1) - .byte >(chrout_screen_TAB_FW - 1) -#endif - .byte >(chrout_screen_DEL - 1) - .byte >(chrout_screen_RETURN - 1) - -#else - -__before_chrout_screen_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - -chrout_screen_jumptable: - - .word chrout_screen_CLR - .word chrout_screen_HOME - .word chrout_screen_SHIFT_OFF - .word chrout_screen_SHIFT_ON - .word chrout_screen_TXT - .word chrout_screen_GFX - .word chrout_screen_RVS_OFF - .word chrout_screen_RVS_ON - .word chrout_screen_CRSR_RIGHT - .word chrout_screen_CRSR_LEFT - .word chrout_screen_CRSR_DOWN - .word chrout_screen_CRSR_UP - .word chrout_screen_INS -#if CONFIG_EDIT_STOPQUOTE - .word chrout_screen_STOP -#endif -#if CONFIG_EDIT_TABULATORS - .word chrout_screen_TAB_BW - .word chrout_screen_TAB_FW -#endif - .word chrout_screen_DEL - .word chrout_screen_RETURN - - // Make sure routine size is always the same - build system limitation - -.if (__before_chrout_screen_jumptable == chrout_screen_jumptable) { brk } - -#endif diff --git a/doc/Development.md b/doc/Development.md index bc4c8ad7..2a834a22 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -59,6 +59,10 @@ There is no official PETSCII code for `TAB` - we can't utilize the ones from C12 Bits 3 and 4 are extension to the original variable, compatible with the C128 ROMs API. There is no official way to retrieve `NO_SCRL` status as of yet. The `40/80` key status cannot be retrieved in C64 mode at all (C128 hardware limitation). +#### NMI vector modification + +Before modifying NMI vector, set it's high byte to 0. The ROM routine considers such address invalid and won't try to call the custom code, thus preventing a crash if interrupt happens in the worst possible moment. + #### Mega65 native mode Mega65 build starts in legacy mode, which is intended to be reasonably compatible with the C64 ROMs. However, a native Mega65 mode is planned too, to make it easier to utilise extra features of this machine. Soo far the following has been done: @@ -128,6 +132,7 @@ where: | `#IGNORE` | ignore the file completely | | `#TAKE` | compile the file normally | | `#TAKE-FLOAT` | compile the file, but force it to be floating | +| `#TAKE-HIGH` | as above, but always place routine at `$E000` or above | | `#TAKE-OFFSET` | shifts the fixed-location address by hex offset given as parameter | The first match counts, all the remaining ones are dropped. Examples: @@ -180,6 +185,8 @@ ROUTINE_NAME: #endif ``` +Last, but not least - the `#TAKE-HIGH` is intended to be used for BASIC routines, which should still be available after the main BASIC ROM is banked out. + ### CPU-specific optimizations TODO diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md new file mode 100644 index 00000000..c5ebca1b --- /dev/null +++ b/doc/Extended-BASIC.md @@ -0,0 +1,30 @@ + +# Extended BASIC + +NOTE: Command syntax, behaviour details, and tokens are still subject to change! In the future most (if not all) extended commands will be available only on machines with extended ROM, like the Mega65. + +## Additional commands + +### `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. + +### `MERGE "file_name" [, device_number]` + +Appends the BASIC program from a storage medium to the one currently present in memory. NOTE: due to bug in BASIC editor (improper VARTAB handling) it currently works only with programs loaded from the storage medium, not the ones typed in! + +### `BLOAD "file_name", device_number, start_address` + +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` + +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` + +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. diff --git a/c64/,,config_custom.s b/src/,,config_custom.s similarity index 90% rename from c64/,,config_custom.s rename to src/,,config_custom.s index d5983fcb..ad83a50a 100644 --- a/c64/,,config_custom.s +++ b/src/,,config_custom.s @@ -39,7 +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_60K @@ -49,10 +51,10 @@ #define CONFIG_IEC_DOLPHINDOS #define CONFIG_IEC_DOLPHINDOS_FAST #define CONFIG_IEC_JIFFYDOS -#define CONFIG_IEC_JIFFYDOS_BLANK +// #define CONFIG_IEC_JIFFYDOS_BLANK // #define CONFIG_IEC_BURST_CIA1 // please keep disabled for now // #define CONFIG_IEC_BURST_CIA2 // please keep disabled for now -// #define CONFIG_IEC_BURST_SOFT // please keep disabled for now +// #define CONFIG_IEC_BURST_MEGA_65 // please keep disabled for now #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO @@ -87,8 +89,8 @@ // #define CONFIG_KEY_REPEAT_DEFAULT // #define CONFIG_KEY_REPEAT_ALWAYS #define CONFIG_KEY_FAST_SCAN -#define CONFIG_JOY1_CURSOR -#define CONFIG_JOY2_CURSOR +// #define CONFIG_JOY1_CURSOR +// #define CONFIG_JOY2_CURSOR #define CONFIG_PROGRAMMABLE_KEYS @@ -124,9 +126,9 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE #define CONFIG_TAPE_WEDGE +// #define CONFIG_TAPE_HEAD_ALIGN #define CONFIG_BCD_SAFE_INTERRUPTS - // Eye candy // #define CONFIG_COLORS_BRAND @@ -134,10 +136,13 @@ #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND #define CONFIG_SHOW_FEATURES -#define CONFIG_SHOW_PAL_NTSC // Debug options // #define CONFIG_DBG_STUBS_BRK // #define CONFIG_DBG_PRINTF + +// Other + +// #define CONFIG_COMPRESSION_LVL_2 diff --git a/c64/,,config_cx16.s b/src/,,config_cx16.s similarity index 95% rename from c64/,,config_cx16.s rename to src/,,config_cx16.s index 828f0e73..61056fb2 100644 --- a/c64/,,config_cx16.s +++ b/src/,,config_cx16.s @@ -39,6 +39,8 @@ // Memory model #define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_46K +// #define CONFIG_MEMORY_MODEL_50K // #define CONFIG_MEMORY_MODEL_60K @@ -117,6 +119,7 @@ // #define CONFIG_PANIC_SCREEN // #define CONFIG_DOS_WEDGE // #define CONFIG_TAPE_WEDGE +// #define CONFIG_TAPE_HEAD_ALIGN #define CONFIG_BCD_SAFE_INTERRUPTS @@ -127,10 +130,13 @@ #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND // #define CONFIG_SHOW_FEATURES -// #define CONFIG_SHOW_PAL_NTSC // Debug options // #define CONFIG_DBG_STUBS_BRK // #define CONFIG_DBG_PRINTF + +// Other + +// #define CONFIG_COMPRESSION_LVL_2 diff --git a/c64/,,config_generic.s b/src/,,config_generic.s similarity index 93% rename from c64/,,config_generic.s rename to src/,,config_generic.s index b74339af..391de569 100644 --- a/c64/,,config_generic.s +++ b/src/,,config_generic.s @@ -36,7 +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_60K @@ -115,6 +117,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE #define CONFIG_TAPE_WEDGE +// #define CONFIG_TAPE_HEAD_ALIGN #define CONFIG_BCD_SAFE_INTERRUPTS @@ -125,10 +128,13 @@ #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND #define CONFIG_SHOW_FEATURES -#define CONFIG_SHOW_PAL_NTSC // Debug options // #define CONFIG_DBG_STUBS_BRK // #define CONFIG_DBG_PRINTF + +// Other + +// #define CONFIG_COMPRESSION_LVL_2 diff --git a/c64/,,config_mega65.s b/src/,,config_mega65.s similarity index 90% rename from c64/,,config_mega65.s rename to src/,,config_mega65.s index 60826470..1c9cdbf5 100644 --- a/c64/,,config_mega65.s +++ b/src/,,config_mega65.s @@ -36,7 +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_60K @@ -96,11 +98,11 @@ .const CONFIG_KEYCMD_HELP = @"LIST" -.const CONFIG_KEYCMD_F9 = @"REM F9" +.const CONFIG_KEYCMD_F9 = @"BOOT" .const CONFIG_KEYCMD_F10 = @"REM F10" -.const CONFIG_KEYCMD_F11 = @"REM F11" +.const CONFIG_KEYCMD_F11 = @"MONITOR" .const CONFIG_KEYCMD_F12 = @"REM F12" -.const CONFIG_KEYCMD_F13 = @"REM F13" +.const CONFIG_KEYCMD_F13 = @"\$5FH" .const CONFIG_KEYCMD_F14 = @"REM F14" @@ -115,6 +117,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE #define CONFIG_TAPE_WEDGE +#define CONFIG_TAPE_HEAD_ALIGN #define CONFIG_BCD_SAFE_INTERRUPTS @@ -125,10 +128,13 @@ // #define CONFIG_BANNER_FANCY #define CONFIG_BANNER_BRAND // #define CONFIG_SHOW_FEATURES -// #define CONFIG_SHOW_PAL_NTSC // Debug options // #define CONFIG_DBG_STUBS_BRK // #define CONFIG_DBG_PRINTF + +// Other + +// #define CONFIG_COMPRESSION_LVL_2 diff --git a/c64/,,config_testing.s b/src/,,config_testing.s similarity index 94% rename from c64/,,config_testing.s rename to src/,,config_testing.s index d6743178..b56027c3 100644 --- a/c64/,,config_testing.s +++ b/src/,,config_testing.s @@ -37,6 +37,8 @@ // Memory model // #define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_46K +// #define CONFIG_MEMORY_MODEL_50K #define CONFIG_MEMORY_MODEL_60K @@ -115,6 +117,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE #define CONFIG_TAPE_WEDGE +// #define CONFIG_TAPE_HEAD_ALIGN #define CONFIG_BCD_SAFE_INTERRUPTS @@ -125,10 +128,13 @@ // #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND #define CONFIG_SHOW_FEATURES -#define CONFIG_SHOW_PAL_NTSC // Debug options // #define CONFIG_DBG_STUBS_BRK #define CONFIG_DBG_PRINTF + +// Other + +// #define CONFIG_COMPRESSION_LVL_2 diff --git a/c64/,,config_ultimate64.s b/src/,,config_ultimate64.s similarity index 93% rename from c64/,,config_ultimate64.s rename to src/,,config_ultimate64.s index 9cbd6819..b463c918 100644 --- a/c64/,,config_ultimate64.s +++ b/src/,,config_ultimate64.s @@ -36,7 +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_60K @@ -115,6 +117,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE #define CONFIG_TAPE_WEDGE +// #define CONFIG_TAPE_HEAD_ALIGN #define CONFIG_BCD_SAFE_INTERRUPTS @@ -125,10 +128,13 @@ #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND #define CONFIG_SHOW_FEATURES -#define CONFIG_SHOW_PAL_NTSC // Debug options // #define CONFIG_DBG_STUBS_BRK // #define CONFIG_DBG_PRINTF + +// Other + +// #define CONFIG_COMPRESSION_LVL_2 diff --git a/c64/aliases/,aliases_config.s b/src/aliases/,aliases_config.s similarity index 77% rename from c64/aliases/,aliases_config.s rename to src/aliases/,aliases_config.s index ebf44ae2..42c8166b 100644 --- a/c64/aliases/,aliases_config.s +++ b/src/aliases/,aliases_config.s @@ -121,6 +121,12 @@ #if CONFIG_MEMORY_MODEL_38K .eval selected++ #endif +#if CONFIG_MEMORY_MODEL_46K + .eval selected++ +#endif +#if CONFIG_MEMORY_MODEL_50K + .eval selected++ +#endif #if CONFIG_MEMORY_MODEL_60K .eval selected++ #endif @@ -148,12 +154,12 @@ .error "CONFIG_IEC_DOLPHINDOS_FAST requires CONFIG_IEC_DOLPHINDOS" #endif -#if (CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_SOFT) && !CONFIG_IEC +#if (CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_MEGA_65) && !CONFIG_IEC .error "CONFIG_IEC_BURST_* requires CONFIG_IEC" #endif -#if CONFIG_IEC_BURST_SOFT && !CONFIG_MB_MEGA_65 - .error "CONFIG_IEC_BURST_SOFT requires CONFIG_MB_MEGA_65" +#if CONFIG_IEC_BURST_MEGA_65 && !CONFIG_MB_MEGA_65 + .error "CONFIG_IEC_BURST_MEGA_65 requires CONFIG_MB_MEGA_65" #endif .var selected_iec_burst = 0; @@ -164,7 +170,7 @@ #if CONFIG_IEC_BURST_CIA2 .eval selected_iec_burst++ #endif -#if CONFIG_IEC_BURST_SOFT +#if CONFIG_IEC_BURST_MEGA_65 .eval selected_iec_burst++ #endif @@ -295,8 +301,11 @@ // Check that features are configured correctly { -#if CONFIG_TAPE_WEDGE && !CONFIG_TAPE_TURBO - .error "CONFIG_TAPE_WEDGE requires CONFIG_TAPE_TURBO" +#if CONFIG_TAPE_WEDGE && !CONFIG_TAPE_TURBO && !CONFIG_TAPE_NORMAL + .error "CONFIG_TAPE_WEDGE requires CONFIG_TAPE_TURBO or CONFIG_TAPE_NORMAL" +#endif +#if !CONFIG_TAPE_WEDGE && CONFIG_TAPE_HEAD_ALIGN + .error "CONFIG_TAPE_HEAD_ALIGN requires CONFIG_TAPE_WEDGE" #endif } @@ -341,84 +350,17 @@ } -// Function for printing out build features -.var feature_new_line = false +// Setup colors -.function ADD_FEATURE(current_features, new_feature) -{ - .var features_str = current_features +#if CONFIG_COLORS_BRAND && CONFIG_BRAND_ULTIMATE_64 - .if (!feature_new_line && features_str.size() > 0) - { - .eval features_str = features_str + ", " - } + .const CONFIG_COLOR_BG = $00 + .const CONFIG_COLOR_TXT = $01 - .if (feature_new_line) - { - .eval feature_new_line = false - .eval features_str = features_str + @"\r" - } +#else - .return features_str + new_feature -} + .const CONFIG_COLOR_BG = $06 + .const CONFIG_COLOR_TXT = $01 -.function BUILD_FEATURES_STR() -{ - .var features_str = "" - -#if CONFIG_TAPE_NORMAL && !CONFIG_TAPE_TURBO - .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD NORMAL") #endif -#if !CONFIG_TAPE_NORMAL && CONFIG_TAPE_TURBO - .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD TURBO") -#endif -#if CONFIG_TAPE_NORMAL && CONFIG_TAPE_TURBO - .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD NORMAL TURBO") -#endif - - .eval feature_new_line = true - -#if CONFIG_IEC - .var iec_features_str = "IEC" -#if CONFIG_IEC_BURST_CIA1 - .eval iec_features_str = iec_features_str + " BURST1" -#endif -#if CONFIG_IEC_BURST_CIA2 - .eval iec_features_str = iec_features_str + " BURST2" -#endif -#if CONFIG_IEC_BURST_SOFT - .eval iec_features_str = iec_features_str + " BURST" -#endif -#if CONFIG_IEC_DOLPHINDOS - .eval iec_features_str = iec_features_str + " DOLPHIN" -#endif -#if CONFIG_IEC_JIFFYDOS - .eval iec_features_str = iec_features_str + " JIFFY" -#endif -#if !CONFIG_IEC_BURST_CIA1 && !CONFIG_IEC_BURST_CIA2 && !CONFIG_IEC_BURST_SOFT && !CONFIG_IEC_DOLPHINDOS && !CONFIG_IEC_JIFFYDOS - .eval iec_features_str = iec_features_str + " NORMAL" -#endif - .eval features_str = ADD_FEATURE(features_str, iec_features_str) -#endif - - .eval feature_new_line = true - -#if CONFIG_RS232_UP2400 - .eval features_str = ADD_FEATURE(features_str, "UP2400") -#endif - -#if CONFIG_RS232_UP2400 - .eval features_str = ADD_FEATURE(features_str, "UP9600") -#endif - -#if CONFIG_KEYBOARD_C128 - .eval features_str = ADD_FEATURE(features_str, "KBD 128") -#endif - -#if CONFIG_KEYBOARD_C65 - .eval features_str = ADD_FEATURE(features_str, "KBD 65") -#endif - - .return features_str -} diff --git a/c64/aliases/,aliases_cpu.s b/src/aliases/,aliases_cpu.s similarity index 94% rename from c64/aliases/,aliases_cpu.s rename to src/aliases/,aliases_cpu.s index 38a321dc..d0f29fad 100644 --- a/c64/aliases/,aliases_cpu.s +++ b/src/aliases/,aliases_cpu.s @@ -42,6 +42,41 @@ +// +// Macros for generating jumptables +// + + +.macro put_jumptable_lo(list) +{ + .for (var i = 0; i < list.size(); i++) + { + .byte mod((list.get(i) - 1), $100) + } +} + +.macro put_jumptable_hi(list) +{ + .for (var i = 0; i < list.size(); i++) + { + .byte floor((list.get(i) - 1) / $100) + } +} + +#if HAS_OPCODES_65C02 + +.macro put_jumptable(list) +{ + .for (var i = 0; i < list.size(); i++) + { + .word list.get(i) + } +} + +#endif + + + // // Trick to skip a 2-byte instruction // diff --git a/c64/aliases/,aliases_error_codes.s b/src/aliases/,aliases_error_codes.s similarity index 100% rename from c64/aliases/,aliases_error_codes.s rename to src/aliases/,aliases_error_codes.s diff --git a/c64/aliases/,aliases_hardware.s b/src/aliases/,aliases_hardware.s similarity index 94% rename from c64/aliases/,aliases_hardware.s rename to src/aliases/,aliases_hardware.s index bdd0f5e5..f0096f81 100644 --- a/c64/aliases/,aliases_hardware.s +++ b/src/aliases/,aliases_hardware.s @@ -125,6 +125,10 @@ .label SID_RANDOM = $D41B .label SID_ENV3 = $D41C + // Color COLOR_RAM + + .label COLOR_RAM = $D800 + // CIA #1 registers .label __CIA1_BASE = $DC00 // base address of the chip @@ -183,10 +187,17 @@ #if CONFIG_MB_MEGA_65 - .const C65_EXTKEYS_PR = $D607 - .const C65_EXTKEYS_DDR = $D608 + .label C65_EXTKEYS_PR = $D607 + .label C65_EXTKEYS_DDR = $D608 - .const M65_BADL_SLI = $D710 + .label M65_BADL_SLI = $D710 + +#else + + // SuperCPU registers + + .label SCPU_SPEED_NORMAL = $D07A + .label SCPU_SPEED_TURBO = $D07B #endif diff --git a/c64/aliases/,aliases_hardware_cx16.s b/src/aliases/,aliases_hardware_cx16.s similarity index 100% rename from c64/aliases/,aliases_hardware_cx16.s rename to src/aliases/,aliases_hardware_cx16.s diff --git a/c64/aliases/,aliases_petscii_codes.s b/src/aliases/,aliases_petscii_codes.s similarity index 100% rename from c64/aliases/,aliases_petscii_codes.s rename to src/aliases/,aliases_petscii_codes.s diff --git a/c64/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s similarity index 96% rename from c64/aliases/,aliases_ram_lowmem.s rename to src/aliases/,aliases_ram_lowmem.s index f6f9e3ac..3e206102 100644 --- a/c64/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -17,10 +17,10 @@ .label CHARAC = $07 // [!] our implementation might be different XXX give more details .label ENDCHR = $08 // [!] our implementation might be different XXX give more details .label TRMPOS = $09 // -- NOT IMPLEMENTED -- - .label VERCKB = $0A // -- NOT IMPLEMENTED -- + .label VERCKB = $0A // flag used by BASIC, 0 - LOAD, 1 - VERIFY .label COUNT = $0B // [!] our implementation might be different XXX give more details .label DIMFLG = $0C // [!] our implementation might be different XXX give more details - .label VALTYP = $0D // -- NOT IMPLEMENTED -- + .label VALTYP = $0D // expression eveluation result; $00 - float, $FF - string .label INTFLG = $0E // -- NOT IMPLEMENTED -- .label GARBFL = $0F // [!] our implementation might be different XXX give more details .label SUBFLG = $10 // -- NOT IMPLEMENTED -- @@ -28,9 +28,9 @@ .label TANSGN = $12 // -- NOT IMPLEMENTED -- .label CHANNL = $13 // -- NOT IMPLEMENTED -- .label LINNUM = $14 // $14-$15 BASIC line number, [!] also used by DOS Wedge - .label TEMPPT = $16 // -- NOT IMPLEMENTED -- - .label LASTPT = $17 // $17-$18 -- NOT IMPLEMENTED -- - .label TEMPST = $19 // $19-$21 -- NOT IMPLEMENTED -- + .label TEMPPT = $16 // pointer to the first available slot in the temporary string descriptor stack + .label LASTPT = $17 // $17-$18 pointer to the last used slot in the temporary string descriptor + .label TEMPST = $19 // $19-$21 temporary string stack descriptors .label INDEX = $22 // $22-$25 temporary variables, [!] our usage might be different .label RESHO = $26 // $26-$2A -- NOT IMPLEMENTED -- .label TXTTAB = $2B // $2B-$2C start of BASIC code @@ -49,7 +49,7 @@ .label VARNAM = $45 // $45-$46 -- NOT IMPLEMENTED -- .label VARPNT = $47 // $47-$48 -- NOT IMPLEMENTED -- .label FORPNT = $49 // $49-$4A -- NOT IMPLEMENTED -- - .label OPPTR = $4B // $4B-$4C -- NOT IMPLEMENTED -- + .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 -- @@ -103,7 +103,7 @@ .label PTR1 = $9E // for tape support, counter of errorneous bytes .label PTR2 = $9F // for tape support, counter for errorneous bytes correction .label TIME = $A0 // $A0-$A2 jiffy clock -#if !CONFIG_IEC_JIFFYDOS && !CONFIG_IEC_DOLPHINDOS && !CONFIG_IEC_BURST_CIA1 && !CONFIG_IEC_BURST_CIA2 && !CONFIG_IEC_BURST_SOFT +#if !CONFIG_IEC_JIFFYDOS && !CONFIG_IEC_DOLPHINDOS && !CONFIG_IEC_BURST_CIA1 && !CONFIG_IEC_BURST_CIA2 && !CONFIG_IEC_BURST_MEGA_65 .label TSFCNT = $A3 // temporary variable for tape and IEC, [!] our usage differs #else .label IECPROTO = $A3 // -- WIP -- [!] 0 = normal, 1 = JiffyDOS, >= $80 for unknown diff --git a/c64/aliases/,aliases_rom_basic.s b/src/aliases/,aliases_rom_basic.s similarity index 100% rename from c64/aliases/,aliases_rom_basic.s rename to src/aliases/,aliases_rom_basic.s diff --git a/c64/aliases/,aliases_rom_cart.s b/src/aliases/,aliases_rom_cart.s similarity index 100% rename from c64/aliases/,aliases_rom_cart.s rename to src/aliases/,aliases_rom_cart.s diff --git a/c64/aliases/,aliases_rom_kernal.s b/src/aliases/,aliases_rom_kernal.s similarity index 100% rename from c64/aliases/,aliases_rom_kernal.s rename to src/aliases/,aliases_rom_kernal.s diff --git a/c64/basic/,aliases.s b/src/basic/,aliases.s similarity index 100% rename from c64/basic/,aliases.s rename to src/basic/,aliases.s diff --git a/c64/basic/,imports.s b/src/basic/,imports.s similarity index 84% rename from c64/basic/,imports.s rename to src/basic/,imports.s index 8c7b7643..8b3c1e45 100644 --- a/c64/basic/,imports.s +++ b/src/basic/,imports.s @@ -43,10 +43,8 @@ .label print_return = KERNAL().print_return .label print_space = KERNAL().print_space -#if CONFIG_SHOW_FEATURES -.label print_features = KERNAL().print_features +#if CONFIG_TAPE_HEAD_ALIGN +.label tape_head_align = KERNAL().tape_head_align #endif -#if CONFIG_SHOW_PAL_NTSC -.label print_pal_ntsc = KERNAL().print_pal_ntsc -#endif +.label filename_any = KERNAL().filename_any diff --git a/c64/basic/,stubs/a408.interop b/src/basic/,stubs/a408.interop similarity index 100% rename from c64/basic/,stubs/a408.interop rename to src/basic/,stubs/a408.interop diff --git a/c64/basic/,stubs/a408.reason.s b/src/basic/,stubs/a408.reason.s similarity index 100% rename from c64/basic/,stubs/a408.reason.s rename to src/basic/,stubs/a408.reason.s diff --git a/c64/basic/,stubs/a453.interop b/src/basic/,stubs/a453.interop similarity index 100% rename from c64/basic/,stubs/a453.interop rename to src/basic/,stubs/a453.interop diff --git a/c64/basic/,stubs/a453.unknown.s b/src/basic/,stubs/a453.unknown.s similarity index 100% rename from c64/basic/,stubs/a453.unknown.s rename to src/basic/,stubs/a453.unknown.s diff --git a/c64/basic/,stubs/a483.main.s b/src/basic/,stubs/a483.main.s similarity index 100% rename from c64/basic/,stubs/a483.main.s rename to src/basic/,stubs/a483.main.s diff --git a/c64/basic/,stubs/a57c.chrnch.s b/src/basic/,stubs/a57c.chrnch.s similarity index 100% rename from c64/basic/,stubs/a57c.chrnch.s rename to src/basic/,stubs/a57c.chrnch.s diff --git a/c64/basic/,stubs/a57c.interop b/src/basic/,stubs/a57c.interop similarity index 100% rename from c64/basic/,stubs/a57c.interop rename to src/basic/,stubs/a57c.interop diff --git a/c64/basic/,stubs/a644.interop b/src/basic/,stubs/a644.interop similarity index 100% rename from c64/basic/,stubs/a644.interop rename to src/basic/,stubs/a644.interop diff --git a/c64/basic/,stubs/a644.new.s b/src/basic/,stubs/a644.new.s similarity index 100% rename from c64/basic/,stubs/a644.new.s rename to src/basic/,stubs/a644.new.s diff --git a/c64/basic/,stubs/a659.interop b/src/basic/,stubs/a659.interop similarity index 100% rename from c64/basic/,stubs/a659.interop rename to src/basic/,stubs/a659.interop diff --git a/c64/basic/,stubs/a659.setcharptr.s b/src/basic/,stubs/a659.setcharptr.s similarity index 100% rename from c64/basic/,stubs/a659.setcharptr.s rename to src/basic/,stubs/a659.setcharptr.s diff --git a/c64/basic/,stubs/a71a.interop b/src/basic/,stubs/a71a.interop similarity index 100% rename from c64/basic/,stubs/a71a.interop rename to src/basic/,stubs/a71a.interop diff --git a/c64/basic/,stubs/a71a.qplop.s b/src/basic/,stubs/a71a.qplop.s similarity index 100% rename from c64/basic/,stubs/a71a.qplop.s rename to src/basic/,stubs/a71a.qplop.s diff --git a/c64/basic/,stubs/a7e4.gone.s b/src/basic/,stubs/a7e4.gone.s similarity index 100% rename from c64/basic/,stubs/a7e4.gone.s rename to src/basic/,stubs/a7e4.gone.s diff --git a/c64/basic/,stubs/a7e4.interop b/src/basic/,stubs/a7e4.interop similarity index 100% rename from c64/basic/,stubs/a7e4.interop rename to src/basic/,stubs/a7e4.interop diff --git a/c64/basic/,stubs/ae86.eval.s b/src/basic/,stubs/ae86.eval.s similarity index 100% rename from c64/basic/,stubs/ae86.eval.s rename to src/basic/,stubs/ae86.eval.s diff --git a/c64/basic/,stubs/ae86.interop b/src/basic/,stubs/ae86.interop similarity index 100% rename from c64/basic/,stubs/ae86.interop rename to src/basic/,stubs/ae86.interop diff --git a/c64/basic/basic_adray1.s b/src/basic/,stubs/basic_adray1.s similarity index 100% rename from c64/basic/basic_adray1.s rename to src/basic/,stubs/basic_adray1.s diff --git a/c64/basic/basic_adray2.s b/src/basic/,stubs/basic_adray2.s similarity index 100% rename from c64/basic/basic_adray2.s rename to src/basic/,stubs/basic_adray2.s diff --git a/c64/basic/,stubs/e38b.error.s b/src/basic/,stubs/e38b.error.s similarity index 100% rename from c64/basic/,stubs/e38b.error.s rename to src/basic/,stubs/e38b.error.s diff --git a/c64/basic/,stubs/e38b.interop b/src/basic/,stubs/e38b.interop similarity index 100% rename from c64/basic/,stubs/e38b.interop rename to src/basic/,stubs/e38b.interop diff --git a/c64/basic/,stubs/e3bf.init.s b/src/basic/,stubs/e3bf.init.s similarity index 100% rename from c64/basic/,stubs/e3bf.init.s rename to src/basic/,stubs/e3bf.init.s diff --git a/c64/basic/,stubs/e3bf.interop b/src/basic/,stubs/e3bf.interop similarity index 100% rename from c64/basic/,stubs/e3bf.interop rename to src/basic/,stubs/e3bf.interop diff --git a/c64/basic/,stubs/e453.interop b/src/basic/,stubs/e453.interop similarity index 100% rename from c64/basic/,stubs/e453.interop rename to src/basic/,stubs/e453.interop diff --git a/c64/basic/,stubs/e453.rvect.s b/src/basic/,stubs/e453.rvect.s similarity index 100% rename from c64/basic/,stubs/e453.rvect.s rename to src/basic/,stubs/e453.rvect.s diff --git a/c64/basic/,stubs_math/a9c4.convert_FAC1_to_INT.s b/src/basic/,stubs_math/a9c4.convert_FAC1_to_INT.s similarity index 100% rename from c64/basic/,stubs_math/a9c4.convert_FAC1_to_INT.s rename to src/basic/,stubs_math/a9c4.convert_FAC1_to_INT.s diff --git a/c64/basic/,stubs_math/a9c4.interop b/src/basic/,stubs_math/a9c4.interop similarity index 100% rename from c64/basic/,stubs_math/a9c4.interop rename to src/basic/,stubs_math/a9c4.interop diff --git a/c64/basic/,stubs_math/aabc.interop b/src/basic/,stubs_math/aabc.interop similarity index 100% rename from c64/basic/,stubs_math/aabc.interop rename to src/basic/,stubs_math/aabc.interop diff --git a/c64/basic/,stubs_math/aabc.print_FAC1.s b/src/basic/,stubs_math/aabc.print_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/aabc.print_FAC1.s rename to src/basic/,stubs_math/aabc.print_FAC1.s diff --git a/c64/basic/,stubs_math/af7b.compute_TI.s b/src/basic/,stubs_math/af7b.compute_TI.s similarity index 100% rename from c64/basic/,stubs_math/af7b.compute_TI.s rename to src/basic/,stubs_math/af7b.compute_TI.s diff --git a/c64/basic/,stubs_math/af7b.interop b/src/basic/,stubs_math/af7b.interop similarity index 100% rename from c64/basic/,stubs_math/af7b.interop rename to src/basic/,stubs_math/af7b.interop diff --git a/c64/basic/,stubs_math/af7e.interop b/src/basic/,stubs_math/af7e.interop similarity index 100% rename from c64/basic/,stubs_math/af7e.interop rename to src/basic/,stubs_math/af7e.interop diff --git a/c64/basic/,stubs_math/af7e.math_stub.s b/src/basic/,stubs_math/af7e.math_stub.s similarity index 100% rename from c64/basic/,stubs_math/af7e.math_stub.s rename to src/basic/,stubs_math/af7e.math_stub.s diff --git a/c64/basic/,stubs_math/af87.interop b/src/basic/,stubs_math/af87.interop similarity index 100% rename from c64/basic/,stubs_math/af87.interop rename to src/basic/,stubs_math/af87.interop diff --git a/c64/basic/,stubs_math/af87.math_stub.s b/src/basic/,stubs_math/af87.math_stub.s similarity index 100% rename from c64/basic/,stubs_math/af87.math_stub.s rename to src/basic/,stubs_math/af87.math_stub.s diff --git a/c64/basic/,stubs_math/af9a.compute_ST.s b/src/basic/,stubs_math/af9a.compute_ST.s similarity index 100% rename from c64/basic/,stubs_math/af9a.compute_ST.s rename to src/basic/,stubs_math/af9a.compute_ST.s diff --git a/c64/basic/,stubs_math/af9a.interop b/src/basic/,stubs_math/af9a.interop similarity index 100% rename from c64/basic/,stubs_math/af9a.interop rename to src/basic/,stubs_math/af9a.interop diff --git a/c64/basic/,stubs_math/b1aa.FACINX.s b/src/basic/,stubs_math/b1aa.FACINX.s similarity index 100% rename from c64/basic/,stubs_math/b1aa.FACINX.s rename to src/basic/,stubs_math/b1aa.FACINX.s diff --git a/c64/basic/,stubs_math/b1aa.interop b/src/basic/,stubs_math/b1aa.interop similarity index 100% rename from c64/basic/,stubs_math/b1aa.interop rename to src/basic/,stubs_math/b1aa.interop diff --git a/c64/basic/,stubs_math/b1bf.convert_FAC1_to_s16.s b/src/basic/,stubs_math/b1bf.convert_FAC1_to_s16.s similarity index 100% rename from c64/basic/,stubs_math/b1bf.convert_FAC1_to_s16.s rename to src/basic/,stubs_math/b1bf.convert_FAC1_to_s16.s diff --git a/c64/basic/,stubs_math/b1bf.interop b/src/basic/,stubs_math/b1bf.interop similarity index 100% rename from c64/basic/,stubs_math/b1bf.interop rename to src/basic/,stubs_math/b1bf.interop diff --git a/c64/basic/,stubs_math/b391.GIVAYF.s b/src/basic/,stubs_math/b391.GIVAYF.s similarity index 100% rename from c64/basic/,stubs_math/b391.GIVAYF.s rename to src/basic/,stubs_math/b391.GIVAYF.s diff --git a/c64/basic/,stubs_math/b391.interop b/src/basic/,stubs_math/b391.interop similarity index 100% rename from c64/basic/,stubs_math/b391.interop rename to src/basic/,stubs_math/b391.interop diff --git a/c64/basic/,stubs_math/b3a2.convert_Y_to_FAC1.s b/src/basic/,stubs_math/b3a2.convert_Y_to_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/b3a2.convert_Y_to_FAC1.s rename to src/basic/,stubs_math/b3a2.convert_Y_to_FAC1.s diff --git a/c64/basic/,stubs_math/b3a2.interop b/src/basic/,stubs_math/b3a2.interop similarity index 100% rename from c64/basic/,stubs_math/b3a2.interop rename to src/basic/,stubs_math/b3a2.interop diff --git a/c64/basic/,stubs_math/b794.convert_A_to_FAC1.s b/src/basic/,stubs_math/b794.convert_A_to_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/b794.convert_A_to_FAC1.s rename to src/basic/,stubs_math/b794.convert_A_to_FAC1.s diff --git a/c64/basic/,stubs_math/b794.interop b/src/basic/,stubs_math/b794.interop similarity index 100% rename from c64/basic/,stubs_math/b794.interop rename to src/basic/,stubs_math/b794.interop diff --git a/c64/basic/,stubs_math/b7b5.STRVAL.s b/src/basic/,stubs_math/b7b5.STRVAL.s similarity index 100% rename from c64/basic/,stubs_math/b7b5.STRVAL.s rename to src/basic/,stubs_math/b7b5.STRVAL.s diff --git a/c64/basic/,stubs_math/b7b5.interop b/src/basic/,stubs_math/b7b5.interop similarity index 100% rename from c64/basic/,stubs_math/b7b5.interop rename to src/basic/,stubs_math/b7b5.interop diff --git a/c64/basic/,stubs_math/b7f7.convert_FAC1_to_ADDR.s b/src/basic/,stubs_math/b7f7.convert_FAC1_to_ADDR.s similarity index 100% rename from c64/basic/,stubs_math/b7f7.convert_FAC1_to_ADDR.s rename to src/basic/,stubs_math/b7f7.convert_FAC1_to_ADDR.s diff --git a/c64/basic/,stubs_math/b7f7.interop b/src/basic/,stubs_math/b7f7.interop similarity index 100% rename from c64/basic/,stubs_math/b7f7.interop rename to src/basic/,stubs_math/b7f7.interop diff --git a/c64/basic/,stubs_math/b947.interop b/src/basic/,stubs_math/b947.interop similarity index 100% rename from c64/basic/,stubs_math/b947.interop rename to src/basic/,stubs_math/b947.interop diff --git a/c64/basic/,stubs_math/b947.inv_FAC1_mantissa.s b/src/basic/,stubs_math/b947.inv_FAC1_mantissa.s similarity index 100% rename from c64/basic/,stubs_math/b947.inv_FAC1_mantissa.s rename to src/basic/,stubs_math/b947.inv_FAC1_mantissa.s diff --git a/c64/basic/,stubs_math/b9ea.interop b/src/basic/,stubs_math/b9ea.interop similarity index 100% rename from c64/basic/,stubs_math/b9ea.interop rename to src/basic/,stubs_math/b9ea.interop diff --git a/c64/basic/,stubs_math/b9ea.log_FAC1.s b/src/basic/,stubs_math/b9ea.log_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/b9ea.log_FAC1.s rename to src/basic/,stubs_math/b9ea.log_FAC1.s diff --git a/c64/basic/,stubs_math/ba90.get_FAC2_via_INDEX.s b/src/basic/,stubs_math/ba90.get_FAC2_via_INDEX.s similarity index 100% rename from c64/basic/,stubs_math/ba90.get_FAC2_via_INDEX.s rename to src/basic/,stubs_math/ba90.get_FAC2_via_INDEX.s diff --git a/c64/basic/,stubs_math/ba90.interop b/src/basic/,stubs_math/ba90.interop similarity index 100% rename from c64/basic/,stubs_math/ba90.interop rename to src/basic/,stubs_math/ba90.interop diff --git a/c64/basic/,stubs_math/bba6.get_FAC1_via_INDEX.s b/src/basic/,stubs_math/bba6.get_FAC1_via_INDEX.s similarity index 100% rename from c64/basic/,stubs_math/bba6.get_FAC1_via_INDEX.s rename to src/basic/,stubs_math/bba6.get_FAC1_via_INDEX.s diff --git a/c64/basic/,stubs_math/bba6.interop b/src/basic/,stubs_math/bba6.interop similarity index 100% rename from c64/basic/,stubs_math/bba6.interop rename to src/basic/,stubs_math/bba6.interop diff --git a/c64/basic/,stubs_math/bc39.interop b/src/basic/,stubs_math/bc39.interop similarity index 100% rename from c64/basic/,stubs_math/bc39.interop rename to src/basic/,stubs_math/bc39.interop diff --git a/c64/basic/,stubs_math/bc39.sgn_FAC1.s b/src/basic/,stubs_math/bc39.sgn_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bc39.sgn_FAC1.s rename to src/basic/,stubs_math/bc39.sgn_FAC1.s diff --git a/c64/basic/,stubs_math/bc3c.convert_A_to_FAC1.s b/src/basic/,stubs_math/bc3c.convert_A_to_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bc3c.convert_A_to_FAC1.s rename to src/basic/,stubs_math/bc3c.convert_A_to_FAC1.s diff --git a/c64/basic/,stubs_math/bc3c.interop b/src/basic/,stubs_math/bc3c.interop similarity index 100% rename from c64/basic/,stubs_math/bc3c.interop rename to src/basic/,stubs_math/bc3c.interop diff --git a/c64/basic/,stubs_math/bc44.convert_i16_to_FAC1.s b/src/basic/,stubs_math/bc44.convert_i16_to_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bc44.convert_i16_to_FAC1.s rename to src/basic/,stubs_math/bc44.convert_i16_to_FAC1.s diff --git a/c64/basic/,stubs_math/bc44.interop b/src/basic/,stubs_math/bc44.interop similarity index 100% rename from c64/basic/,stubs_math/bc44.interop rename to src/basic/,stubs_math/bc44.interop diff --git a/c64/basic/,stubs_math/bc58.abs_FAC1.s b/src/basic/,stubs_math/bc58.abs_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bc58.abs_FAC1.s rename to src/basic/,stubs_math/bc58.abs_FAC1.s diff --git a/c64/basic/,stubs_math/bc58.interop b/src/basic/,stubs_math/bc58.interop similarity index 100% rename from c64/basic/,stubs_math/bc58.interop rename to src/basic/,stubs_math/bc58.interop diff --git a/c64/basic/,stubs_math/bc5b.FCOMP.s b/src/basic/,stubs_math/bc5b.FCOMP.s similarity index 100% rename from c64/basic/,stubs_math/bc5b.FCOMP.s rename to src/basic/,stubs_math/bc5b.FCOMP.s diff --git a/c64/basic/,stubs_math/bc5b.interop b/src/basic/,stubs_math/bc5b.interop similarity index 100% rename from c64/basic/,stubs_math/bc5b.interop rename to src/basic/,stubs_math/bc5b.interop diff --git a/c64/basic/,stubs_math/bc9b.QINT.s b/src/basic/,stubs_math/bc9b.QINT.s similarity index 100% rename from c64/basic/,stubs_math/bc9b.QINT.s rename to src/basic/,stubs_math/bc9b.QINT.s diff --git a/c64/basic/,stubs_math/bc9b.interop b/src/basic/,stubs_math/bc9b.interop similarity index 100% rename from c64/basic/,stubs_math/bc9b.interop rename to src/basic/,stubs_math/bc9b.interop diff --git a/c64/basic/,stubs_math/bccc.int_FAC1.s b/src/basic/,stubs_math/bccc.int_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bccc.int_FAC1.s rename to src/basic/,stubs_math/bccc.int_FAC1.s diff --git a/c64/basic/,stubs_math/bccc.interop b/src/basic/,stubs_math/bccc.interop similarity index 100% rename from c64/basic/,stubs_math/bccc.interop rename to src/basic/,stubs_math/bccc.interop diff --git a/c64/basic/,stubs_math/bcf3.FIN.s b/src/basic/,stubs_math/bcf3.FIN.s similarity index 100% rename from c64/basic/,stubs_math/bcf3.FIN.s rename to src/basic/,stubs_math/bcf3.FIN.s diff --git a/c64/basic/,stubs_math/bcf3.interop b/src/basic/,stubs_math/bcf3.interop similarity index 100% rename from c64/basic/,stubs_math/bcf3.interop rename to src/basic/,stubs_math/bcf3.interop diff --git a/c64/basic/,stubs_math/bd7e.FINLOG.s b/src/basic/,stubs_math/bd7e.FINLOG.s similarity index 100% rename from c64/basic/,stubs_math/bd7e.FINLOG.s rename to src/basic/,stubs_math/bd7e.FINLOG.s diff --git a/c64/basic/,stubs_math/bd7e.interop b/src/basic/,stubs_math/bd7e.interop similarity index 100% rename from c64/basic/,stubs_math/bd7e.interop rename to src/basic/,stubs_math/bd7e.interop diff --git a/c64/basic/,stubs_math/bddd.FOUT.s b/src/basic/,stubs_math/bddd.FOUT.s similarity index 100% rename from c64/basic/,stubs_math/bddd.FOUT.s rename to src/basic/,stubs_math/bddd.FOUT.s diff --git a/c64/basic/,stubs_math/bddd.interop b/src/basic/,stubs_math/bddd.interop similarity index 100% rename from c64/basic/,stubs_math/bddd.interop rename to src/basic/,stubs_math/bddd.interop diff --git a/c64/basic/,stubs_math/bf74.interop b/src/basic/,stubs_math/bf74.interop similarity index 100% rename from c64/basic/,stubs_math/bf74.interop rename to src/basic/,stubs_math/bf74.interop diff --git a/c64/basic/,stubs_math/bf74.sqr_FAC2.s b/src/basic/,stubs_math/bf74.sqr_FAC2.s similarity index 100% rename from c64/basic/,stubs_math/bf74.sqr_FAC2.s rename to src/basic/,stubs_math/bf74.sqr_FAC2.s diff --git a/c64/basic/,stubs_math/bf7b.interop b/src/basic/,stubs_math/bf7b.interop similarity index 100% rename from c64/basic/,stubs_math/bf7b.interop rename to src/basic/,stubs_math/bf7b.interop diff --git a/c64/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s b/src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s rename to src/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s diff --git a/c64/basic/,stubs_math/bfed.exp_FAC1.s b/src/basic/,stubs_math/bfed.exp_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/bfed.exp_FAC1.s rename to src/basic/,stubs_math/bfed.exp_FAC1.s diff --git a/c64/basic/,stubs_math/bfed.interop b/src/basic/,stubs_math/bfed.interop similarity index 100% rename from c64/basic/,stubs_math/bfed.interop rename to src/basic/,stubs_math/bfed.interop diff --git a/c64/basic/,stubs_math/e043.interop b/src/basic/,stubs_math/e043.interop similarity index 100% rename from c64/basic/,stubs_math/e043.interop rename to src/basic/,stubs_math/e043.interop diff --git a/c64/basic/,stubs_math/e043.poly1_FAC1.s b/src/basic/,stubs_math/e043.poly1_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/e043.poly1_FAC1.s rename to src/basic/,stubs_math/e043.poly1_FAC1.s diff --git a/c64/basic/,stubs_math/e059.interop b/src/basic/,stubs_math/e059.interop similarity index 100% rename from c64/basic/,stubs_math/e059.interop rename to src/basic/,stubs_math/e059.interop diff --git a/c64/basic/,stubs_math/e059.poly2_FAC1.s b/src/basic/,stubs_math/e059.poly2_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/e059.poly2_FAC1.s rename to src/basic/,stubs_math/e059.poly2_FAC1.s diff --git a/c64/basic/,stubs_math/e264.cos_FAC1.s b/src/basic/,stubs_math/e264.cos_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/e264.cos_FAC1.s rename to src/basic/,stubs_math/e264.cos_FAC1.s diff --git a/c64/basic/,stubs_math/e264.interop b/src/basic/,stubs_math/e264.interop similarity index 100% rename from c64/basic/,stubs_math/e264.interop rename to src/basic/,stubs_math/e264.interop diff --git a/c64/basic/,stubs_math/e26b.interop b/src/basic/,stubs_math/e26b.interop similarity index 100% rename from c64/basic/,stubs_math/e26b.interop rename to src/basic/,stubs_math/e26b.interop diff --git a/c64/basic/,stubs_math/e26b.sin_FAC1.s b/src/basic/,stubs_math/e26b.sin_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/e26b.sin_FAC1.s rename to src/basic/,stubs_math/e26b.sin_FAC1.s diff --git a/c64/basic/,stubs_math/e2b4.interop b/src/basic/,stubs_math/e2b4.interop similarity index 100% rename from c64/basic/,stubs_math/e2b4.interop rename to src/basic/,stubs_math/e2b4.interop diff --git a/c64/basic/,stubs_math/e2b4.tan_FAC1.s b/src/basic/,stubs_math/e2b4.tan_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/e2b4.tan_FAC1.s rename to src/basic/,stubs_math/e2b4.tan_FAC1.s diff --git a/c64/basic/,stubs_math/e30e.atn_FAC1.s b/src/basic/,stubs_math/e30e.atn_FAC1.s similarity index 100% rename from c64/basic/,stubs_math/e30e.atn_FAC1.s rename to src/basic/,stubs_math/e30e.atn_FAC1.s diff --git a/c64/basic/,stubs_math/e30e.interop b/src/basic/,stubs_math/e30e.interop similarity index 100% rename from c64/basic/,stubs_math/e30e.interop rename to src/basic/,stubs_math/e30e.interop diff --git a/c64/basic/a533.interop b/src/basic/a533.interop similarity index 100% rename from c64/basic/a533.interop rename to src/basic/a533.interop diff --git a/c64/basic/a533.linkprg.s b/src/basic/a533.linkprg.s similarity index 87% rename from c64/basic/a533.linkprg.s rename to src/basic/a533.linkprg.s index 57d6bdda..859faa8a 100644 --- a/c64/basic/a533.linkprg.s +++ b/src/basic/a533.linkprg.s @@ -34,7 +34,10 @@ linkprg_loop: ldx #filename_any + jmp JSETNAM diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s new file mode 100644 index 00000000..72168c3e --- /dev/null +++ b/src/basic/basic_commands_CC/cmd__jumptable_CC.s @@ -0,0 +1,49 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Jumptable for BASIC commands with tokens prefixed by $CC +// + + +.const command_CC_list = List().add( + + cmd_merge, + + cmd_bload, + cmd_bsave, + cmd_bverify +) + + +#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_CC/cmd_bload_bverify.s b/src/basic/basic_commands_CC/cmd_bload_bverify.s new file mode 100644 index 00000000..a85891f5 --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_bload_bverify.s @@ -0,0 +1,42 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_bverify: + + // LOAD and VERIFY are very similar, from BASIC perspective there is almost no difference; + // just different parameter passed to Kernal and different error message in case of failure + + lda #$01 // mark operation as VERIFY + skip_2_bytes_trash_nvz + +cmd_bload: + + lda #$00 // mark operation as LOAD + jsr helper_load_init_params + + // Fetch the file name + + jsr helper_bload_fetch_filename + + // Fetch device number + + jsr fetch_coma_uint8 + bcs_16 do_SYNTAX_error + + sta FA + + // Fetch the start address + + jsr helper_bload_fetch_address + + // Perform loading + + lda VERCKB // LOAD or VERIFY + jsr JLOAD + bcs_16 do_kernal_error + + // XXX when number parsing is done, change to continue execution + + jmp basic_main_loop diff --git a/src/basic/basic_commands_CC/cmd_bsave.s b/src/basic/basic_commands_CC/cmd_bsave.s new file mode 100644 index 00000000..1e2dbdf8 --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_bsave.s @@ -0,0 +1,42 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_bsave: + + // Set default device and secondary address + + jsr helper_load_init_params_no_VERCKB + + // Fetch the file name + + jsr helper_load_fetch_filename + bcs_16 do_MISSING_FILENAME_error + + // Fetch device number + + jsr helper_load_fetch_devnum + bcs_16 do_SYNTAX_error + + // Fetch memory area start address + + jsr helper_bload_fetch_address + + phx_trash_a + phy_trash_a + + // Fetch memory area end address + + jsr helper_bload_fetch_address + + pla + sta LINNUM+1 + pla + sta LINNUM+0 + + lda #LINNUM + + // Perform SAVE - reuse regular command + + jmp cmd_save_do diff --git a/src/basic/basic_commands_CC/cmd_merge.s b/src/basic/basic_commands_CC/cmd_merge.s new file mode 100644 index 00000000..5734b68d --- /dev/null +++ b/src/basic/basic_commands_CC/cmd_merge.s @@ -0,0 +1,53 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_merge: + + lda #$00 // mark operation as LOAD + jsr helper_load_init_params + + // Fetch the file name + + jsr helper_bload_fetch_filename + + // Fetch device number + + jsr helper_load_fetch_devnum + + // Perform loading - just for a different address + + // XXX sometimes works, sometimes does not - probably improper handling of VARTAB somewhere + + sec + lda VARTAB+0 + sbc #$02 + sta VARTAB+0 + tax + bcs !+ + dec VARTAB+1 +!: + ldy VARTAB+1 + + lda VERCKB // LOAD or VERIFY + jsr JLOAD + bcs_16 do_kernal_error + +cmd_merge_no_error: + + // Store last loaded address + + stx VARTAB+0 + sty VARTAB+1 + + // Clear the variables + jsr basic_do_clr + + // Now relink the loaded program, line links supplied are almost certainly wrong + + jsr LINKPRG + + // XXX when number parsing is done, change to continue execution + + jmp basic_main_loop diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_address.s b/src/basic/basic_commands_CC/helper_bload_fetch_address.s new file mode 100644 index 00000000..f5fca8f6 --- /dev/null +++ b/src/basic/basic_commands_CC/helper_bload_fetch_address.s @@ -0,0 +1,20 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches address for BLOAD/BVERIFY/BSAVE, reports error if not found +// + + +helper_bload_fetch_address: + + jsr injest_comma + bcs_16 do_SYNTAX_error + + jsr basic_parse_line_number // XXX detect errors here + + ldx LINNUM+0 + ldy LINNUM+1 + + rts diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_filename.s b/src/basic/basic_commands_CC/helper_bload_fetch_filename.s new file mode 100644 index 00000000..13da848c --- /dev/null +++ b/src/basic/basic_commands_CC/helper_bload_fetch_filename.s @@ -0,0 +1,26 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches file name for BLOAD/BVERIFY/MERGE, reports error if not found +// + + +helper_bload_fetch_filename: + + // Fetch the file name + + jsr helper_load_fetch_filename + bcc !+ + + // No filename supplied - this should only be allowed for tape (device number below 8) + + lda FA + and #%11111000 + bne_16 do_MISSING_FILENAME_error + + lda #$00 + sta FNLEN +!: + rts diff --git a/src/basic/basic_commands_CD/cmd__jumptable_CD.s b/src/basic/basic_commands_CD/cmd__jumptable_CD.s new file mode 100644 index 00000000..9cfa0c9a --- /dev/null +++ b/src/basic/basic_commands_CD/cmd__jumptable_CD.s @@ -0,0 +1,46 @@ +// #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/basic_commands_CD/cmd_fast_slow.s b/src/basic/basic_commands_CD/cmd_fast_slow.s new file mode 100644 index 00000000..79fcb6ae --- /dev/null +++ b/src/basic/basic_commands_CD/cmd_fast_slow.s @@ -0,0 +1,78 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +#if CONFIG_MB_MEGA_65 + + // Command implementation for Mega65 + + // XXX - I think there are some bit-set instructions in 65CE02... + +cmd_slow: + + lda #$40 + skip_2_bytes_trash_nvz + + // FALLTROUGH + +cmd_fast: + + lda #$41 + sta CPU_D6510 + + jmp execute_statements + +#elif CONFIG_MB_ULTIMATE_64 + + // Command implementation for Ultimate 64 - SuperCPU compatible way should be enough + +cmd_slow: + + sta SCPU_SPEED_NORMAL + jmp execute_statements + +cmd_fast: + + sta SCPU_SPEED_TURBO + jmp execute_statements + +#elif CONFIG_PLATFORM_COMMODORE_64 + + // Command implementation for generic C64 platform + +cmd_slow: + + // Try to disable turbo in SuperCPU compatible way + sta SCPU_SPEED_NORMAL + + // Try to disable turbo mode in C128 compatible way + + lda #$00 + beq !+ // branch always + +cmd_fast: + + // Try to enable turbo in SuperCPU compatible way + sta SCPU_SPEED_TURBO + + // Try to enable turbo mode in C128 compatible way + lda #$01 +!: + sta VIC_CLKRATE + + jmp execute_statements + +#else + +cmd_slow: + + nop // to prevent double label + + // FALLTROUGH + +cmd_fast: + + jmp do_NOT_IMPLEMENTED_error + +#endif diff --git a/c64/basic/basic_delete_line.s b/src/basic/basic_delete_line.s similarity index 90% rename from c64/basic/basic_delete_line.s rename to src/basic/basic_delete_line.s index d7491d1d..864fd0c7 100644 --- a/c64/basic/basic_delete_line.s +++ b/src/basic/basic_delete_line.s @@ -23,6 +23,8 @@ basic_delete_line: #if CONFIG_MEMORY_MODEL_60K ldx #$F7FF +#elif CONFIG_MEMORY_MODEL_50K + lda #>$D000 +#elif CONFIG_MEMORY_MODEL_46K + lda #>$C000 #else // CONFIG_MEMORY_MODEL_38K lda #>$A000 #endif - .byte $2C + skip_2_bytes_trash_nvz !: -#if CONFIG_MEMORY_MODEL_60K - lda #>$F7FF -#else // CONFIG_MEMORY_MODEL_38K - lda #>$A000 -#endif + lda #>$8000 sta MEMSIZ+1 sta FRETOP+1 #if CONFIG_MEMORY_MODEL_60K - lda #<$F7FF -#else // CONFIG_MEMORY_MODEL_38K - lda #<$A000 + cpx #$80 + beq !+ + lda #$FF + skip_2_bytes_trash_nvz +!: + lda #<$00 +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + lda #<$00 #endif sta MEMSIZ+0 sta FRETOP+0 - // FALL THROUGH + // FALLTHROUGH basic_do_clr: + // XXX shouldnt FRETOP go here? + // Clear variables, arrays and strings + lda VARTAB+0 sta ARYTAB+0 sta STREND+0 @@ -87,4 +95,5 @@ basic_do_clr: rts + #endif // ROM layout diff --git a/c64/basic/basic_find_line.s b/src/basic/basic_find_line.s similarity index 79% rename from c64/basic/basic_find_line.s rename to src/basic/basic_find_line.s index 45102507..be9a962e 100644 --- a/c64/basic/basic_find_line.s +++ b/src/basic/basic_find_line.s @@ -22,6 +22,8 @@ basic_find_line_loop: #if CONFIG_MEMORY_MODEL_60K ldx # - ldx #31 - jsr print_packed_message + + ldx #IDX__STR_IN + jsr print_packed_misc_str lda CURLIN+1 ldx CURLIN+0 jsr print_integer !: - // New lines - jsr print_return - lda #$00 - jsr JCHROUT + // Reset stack, and go back to main loop - // XXX - Restore stack depth first? + ldx #$FE + txs jmp basic_main_loop diff --git a/src/basic/engine/end_of_statement_check.s b/src/basic/engine/end_of_statement_check.s new file mode 100644 index 00000000..2c7a7271 --- /dev/null +++ b/src/basic/engine/end_of_statement_check.s @@ -0,0 +1,45 @@ +// #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 this can probably be size-optimized + + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx #=', '<=' and '<>' operators + + cmp #$07 + beq fetch_operator_try_gteq + + cmp #$09 + beq fetch_operator_try_lteq_neq + + // FALLTROUGH + +fetch_operator_success: + + clc + rts + +fetch_operator_failed: + + jsr unconsume_character + + sec + rts + + +fetch_operator_try_gteq: + + // Here we distinguish between '>' and '>=' + + jsr fetch_character + cmp #$B2 // '=' + beq !+ + + // This is a '>' + + jsr unconsume_character + lda #$07 + bne fetch_operator_success // branch always +!: + // This is a '>=' + + lda #$0A + bne fetch_operator_success // branch always + + +fetch_operator_try_lteq_neq: + + // Here we distinguish between '<', '<=', and '<>' + + jsr fetch_character + cmp #$B2 // '=' + beq !+ + cmp #$B1 // '>' + beq !++ + + // This is a '<' + + jsr unconsume_character + lda #$09 + bne fetch_operator_success // branch always +!: + // This is a '<=' + + lda #$0B + bne fetch_operator_success // branch always +!: + // This is a '<>' + + lda #$0C + bne fetch_operator_success // branch always diff --git a/src/basic/engine/fetch_uint8.s b/src/basic/engine/fetch_uint8.s new file mode 100644 index 00000000..1637b056 --- /dev/null +++ b/src/basic/engine/fetch_uint8.s @@ -0,0 +1,26 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches 8-bit unsigned integer +// + + +fetch_coma_uint8: + + jsr injest_comma + bcs !+ + + // FALLTROUGH + +fetch_uint8: + + jsr injest_spaces + jsr basic_parse_line_number // XXX detect errors here + lda LINNUM+1 + bne_16 do_ILLEGAL_QUANTITY_error + lda LINNUM+0 + clc +!: + rts diff --git a/c64/basic/init_oldtxt.s b/src/basic/engine/init_oldtxt.s similarity index 100% rename from c64/basic/init_oldtxt.s rename to src/basic/engine/init_oldtxt.s diff --git a/src/basic/engine/injest_comma.s b/src/basic/engine/injest_comma.s new file mode 100644 index 00000000..8997ee2a --- /dev/null +++ b/src/basic/engine/injest_comma.s @@ -0,0 +1,27 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Consummes a comma in a BASIC code, Carry set if not found. Injests all spaces. +// + + +injest_comma: + + jsr fetch_character + cmp #$2C // comma character + beq injest_comma_found + cmp #$20 // space, can always be skipped + beq injest_comma + + // Not found + jsr unconsume_character + + sec + rts + +injest_comma_found: + + clc + rts diff --git a/src/basic/engine/injest_spaces.s b/src/basic/engine/injest_spaces.s new file mode 100644 index 00000000..fb018def --- /dev/null +++ b/src/basic/engine/injest_spaces.s @@ -0,0 +1,18 @@ +// #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/engine/unconsume_character.s b/src/basic/engine/unconsume_character.s new file mode 100644 index 00000000..6503a17d --- /dev/null +++ b/src/basic/engine/unconsume_character.s @@ -0,0 +1,20 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Reverses character fetch +// + + +unconsume_character: + + lda TXTPTR+0 + sec + sbc #$01 + sta TXTPTR+0 + lda TXTPTR+1 + sbc #$00 + sta TXTPTR+1 + + rts diff --git a/c64/basic/fac1_mul.s b/src/basic/fac1_mul.s similarity index 100% rename from c64/basic/fac1_mul.s rename to src/basic/fac1_mul.s diff --git a/c64/basic/init/a000.cold_start_vector.s b/src/basic/init/a000.cold_start_vector.s similarity index 100% rename from c64/basic/init/a000.cold_start_vector.s rename to src/basic/init/a000.cold_start_vector.s diff --git a/c64/basic/init/a002.warm_start_vector.s b/src/basic/init/a002.warm_start_vector.s similarity index 100% rename from c64/basic/init/a002.warm_start_vector.s rename to src/basic/init/a002.warm_start_vector.s diff --git a/c64/basic/init/basic_cold_start_internal.s b/src/basic/init/basic_cold_start_internal.s similarity index 100% rename from c64/basic/init/basic_cold_start_internal.s rename to src/basic/init/basic_cold_start_internal.s diff --git a/c64/basic/init/basic_warm_start_internal.s b/src/basic/init/basic_warm_start_internal.s similarity index 90% rename from c64/basic/init/basic_warm_start_internal.s rename to src/basic/init/basic_warm_start_internal.s index f9ad47c0..75fc68c5 100644 --- a/c64/basic/init/basic_warm_start_internal.s +++ b/src/basic/init/basic_warm_start_internal.s @@ -19,14 +19,12 @@ basic_warm_start_real: ora CMP0+1 beq !+ - ldx #32 - jsr print_packed_message + ldx #IDX__STR_BRK_AT + jsr print_packed_misc_str lda CMP0+1 jsr print_hex_byte lda CMP0+0 jsr print_hex_byte - jsr print_return - !: jmp basic_main_loop diff --git a/c64/basic/init/e394.basic_cold_start.s b/src/basic/init/e394.basic_cold_start.s similarity index 100% rename from c64/basic/init/e394.basic_cold_start.s rename to src/basic/init/e394.basic_cold_start.s diff --git a/c64/basic/init/e394.interop b/src/basic/init/e394.interop similarity index 100% rename from c64/basic/init/e394.interop rename to src/basic/init/e394.interop diff --git a/c64/basic/init/e3b7.basic_warm_start.jmp.s b/src/basic/init/e3b7.basic_warm_start.jmp.s similarity index 100% rename from c64/basic/init/e3b7.basic_warm_start.jmp.s rename to src/basic/init/e3b7.basic_warm_start.jmp.s diff --git a/c64/basic/init/e3b7.interop b/src/basic/init/e3b7.interop similarity index 100% rename from c64/basic/init/e3b7.interop rename to src/basic/init/e3b7.interop diff --git a/c64/basic/init/e422.initmsg.jmp.s b/src/basic/init/e422.initmsg.jmp.s similarity index 100% rename from c64/basic/init/e422.initmsg.jmp.s rename to src/basic/init/e422.initmsg.jmp.s diff --git a/c64/basic/init/e422.interop b/src/basic/init/e422.interop similarity index 100% rename from c64/basic/init/e422.interop rename to src/basic/init/e422.interop diff --git a/c64/basic/init/initmsg_bytes_free.s b/src/basic/init/initmsg_bytes_free.s similarity index 88% rename from c64/basic/init/initmsg_bytes_free.s rename to src/basic/init/initmsg_bytes_free.s index 0093c12a..b277340f 100644 --- a/c64/basic/init/initmsg_bytes_free.s +++ b/src/basic/init/initmsg_bytes_free.s @@ -21,5 +21,5 @@ initmsg_bytes_free: jsr print_integer // Print rest of the start up message - ldx #34 - jmp print_packed_message + ldx #IDX__STR_BYTES + jmp print_packed_misc_str diff --git a/c64/basic/init/initmsg_real.s b/src/basic/init/initmsg_real.s similarity index 79% rename from c64/basic/init/initmsg_real.s rename to src/basic/init/initmsg_real.s index 332ef462..98df977a 100644 --- a/c64/basic/init/initmsg_real.s +++ b/src/basic/init/initmsg_real.s @@ -17,7 +17,7 @@ initmsg_real: #endif - // Clear the screen first, some cartridges (like IEEE-488) leeave a mess on the screen + // Clear the screen first, some cartridges (like IEEE-488) are leaving a mess on the screen lda #147 jsr JCHROUT @@ -55,14 +55,7 @@ initmsg_real: ldx #$05 #endif ldy #$00 -#if CONFIG_SHOW_PAL_NTSC && CONFIG_SHOW_FEATURES - jsr plot_set - jsr print_features - jmp print_pal_ntsc -#elif CONFIG_SHOW_PAL_NTSC - jsr plot_set - jmp print_pal_ntsc -#elif CONFIG_SHOW_FEATURES +#if CONFIG_SHOW_FEATURES jsr plot_set jmp print_features #else @@ -115,14 +108,7 @@ initmsg_real: ldx #$05 #endif ldy #$00 -#if CONFIG_SHOW_PAL_NTSC && CONFIG_SHOW_FEATURES - jsr plot_set - jsr print_features - jmp print_pal_ntsc -#elif CONFIG_SHOW_PAL_NTSC - jsr plot_set - jmp print_pal_ntsc -#elif CONFIG_SHOW_FEATURES +#if CONFIG_SHOW_FEATURES jsr plot_set jmp print_features #else @@ -167,10 +153,9 @@ initmsg_real: ldx #$08 ldy #$00 jsr plot_set - jsr print_features - jmp print_return + jmp print_features #else - ldx #$08 + ldx #$07 ldy #$00 jmp plot_set #endif diff --git a/c64/basic/init/startup_banner.s b/src/basic/init/startup_banner.s similarity index 100% rename from c64/basic/init/startup_banner.s rename to src/basic/init/startup_banner.s diff --git a/c64/basic/injest_number.s b/src/basic/injest_number.s similarity index 98% rename from c64/basic/injest_number.s rename to src/basic/injest_number.s index 8fef2c70..7cd5ff02 100644 --- a/c64/basic/injest_number.s +++ b/src/basic/injest_number.s @@ -68,7 +68,7 @@ injest_number: sta FAC1_sign // Skip over the minus sign - jsr basic_consume_character + jsr consume_character ij_loop1: ldy #$00 @@ -138,7 +138,7 @@ ij_loop2: ij_consider_next_digit: // Consider next digit - jsr basic_consume_character + jsr consume_character jmp ij_loop1 rts diff --git a/c64/basic/math/add_FAC2_FAC1_sub.s b/src/basic/math/add_FAC2_FAC1_sub.s similarity index 100% rename from c64/basic/math/add_FAC2_FAC1_sub.s rename to src/basic/math/add_FAC2_FAC1_sub.s diff --git a/c64/basic/math/add_align_exponents.s b/src/basic/math/add_align_exponents.s similarity index 100% rename from c64/basic/math/add_align_exponents.s rename to src/basic/math/add_align_exponents.s diff --git a/c64/basic/math/b849.add_HALF_FAC1.s b/src/basic/math/b849.add_HALF_FAC1.s similarity index 100% rename from c64/basic/math/b849.add_HALF_FAC1.s rename to src/basic/math/b849.add_HALF_FAC1.s diff --git a/c64/basic/math/b849.interop b/src/basic/math/b849.interop similarity index 100% rename from c64/basic/math/b849.interop rename to src/basic/math/b849.interop diff --git a/c64/basic/math/b850.interop b/src/basic/math/b850.interop similarity index 100% rename from c64/basic/math/b850.interop rename to src/basic/math/b850.interop diff --git a/c64/basic/math/b850.sub_MEM_FAC1.s b/src/basic/math/b850.sub_MEM_FAC1.s similarity index 100% rename from c64/basic/math/b850.sub_MEM_FAC1.s rename to src/basic/math/b850.sub_MEM_FAC1.s diff --git a/c64/basic/math/b853.interop b/src/basic/math/b853.interop similarity index 100% rename from c64/basic/math/b853.interop rename to src/basic/math/b853.interop diff --git a/c64/basic/math/b853.sub_FAC2_FAC1.s b/src/basic/math/b853.sub_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/b853.sub_FAC2_FAC1.s rename to src/basic/math/b853.sub_FAC2_FAC1.s diff --git a/c64/basic/math/b862.add_align_exponent.jmp.s b/src/basic/math/b862.add_align_exponent.jmp.s similarity index 100% rename from c64/basic/math/b862.add_align_exponent.jmp.s rename to src/basic/math/b862.add_align_exponent.jmp.s diff --git a/c64/basic/math/b862.interop b/src/basic/math/b862.interop similarity index 100% rename from c64/basic/math/b862.interop rename to src/basic/math/b862.interop diff --git a/c64/basic/math/b867.add_MEM_FAC1.s b/src/basic/math/b867.add_MEM_FAC1.s similarity index 100% rename from c64/basic/math/b867.add_MEM_FAC1.s rename to src/basic/math/b867.add_MEM_FAC1.s diff --git a/c64/basic/math/b867.interop b/src/basic/math/b867.interop similarity index 100% rename from c64/basic/math/b867.interop rename to src/basic/math/b867.interop diff --git a/c64/basic/math/b86a.add_FAC2_FAC1.s b/src/basic/math/b86a.add_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/b86a.add_FAC2_FAC1.s rename to src/basic/math/b86a.add_FAC2_FAC1.s diff --git a/c64/basic/math/b86a.interop b/src/basic/math/b86a.interop similarity index 100% rename from c64/basic/math/b86a.interop rename to src/basic/math/b86a.interop diff --git a/c64/basic/math/b8fe.interop b/src/basic/math/b8fe.interop similarity index 100% rename from c64/basic/math/b8fe.interop rename to src/basic/math/b8fe.interop diff --git a/c64/basic/math/b8fe.normal_FAC1.jmp.s b/src/basic/math/b8fe.normal_FAC1.jmp.s similarity index 100% rename from c64/basic/math/b8fe.normal_FAC1.jmp.s rename to src/basic/math/b8fe.normal_FAC1.jmp.s diff --git a/c64/basic/math/ba28.interop b/src/basic/math/ba28.interop similarity index 100% rename from c64/basic/math/ba28.interop rename to src/basic/math/ba28.interop diff --git a/c64/basic/math/ba28.mul_MEM_FAC1.jmp.s b/src/basic/math/ba28.mul_MEM_FAC1.jmp.s similarity index 100% rename from c64/basic/math/ba28.mul_MEM_FAC1.jmp.s rename to src/basic/math/ba28.mul_MEM_FAC1.jmp.s diff --git a/c64/basic/math/ba2b.interop b/src/basic/math/ba2b.interop similarity index 100% rename from c64/basic/math/ba2b.interop rename to src/basic/math/ba2b.interop diff --git a/c64/basic/math/ba2b.mul_FAC2_FAC1.s b/src/basic/math/ba2b.mul_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/ba2b.mul_FAC2_FAC1.s rename to src/basic/math/ba2b.mul_FAC2_FAC1.s diff --git a/c64/basic/math/ba8c.interop b/src/basic/math/ba8c.interop similarity index 100% rename from c64/basic/math/ba8c.interop rename to src/basic/math/ba8c.interop diff --git a/c64/basic/math/ba8c.mov_MEM_FAC2.jmp.s b/src/basic/math/ba8c.mov_MEM_FAC2.jmp.s similarity index 100% rename from c64/basic/math/ba8c.mov_MEM_FAC2.jmp.s rename to src/basic/math/ba8c.mov_MEM_FAC2.jmp.s diff --git a/c64/basic/math/bae2.interop b/src/basic/math/bae2.interop similarity index 100% rename from c64/basic/math/bae2.interop rename to src/basic/math/bae2.interop diff --git a/c64/basic/math/bae2.mul10_FAC1.s b/src/basic/math/bae2.mul10_FAC1.s similarity index 100% rename from c64/basic/math/bae2.mul10_FAC1.s rename to src/basic/math/bae2.mul10_FAC1.s diff --git a/c64/basic/math/bafe.div10_FAC1_p.s b/src/basic/math/bafe.div10_FAC1_p.s similarity index 100% rename from c64/basic/math/bafe.div10_FAC1_p.s rename to src/basic/math/bafe.div10_FAC1_p.s diff --git a/c64/basic/math/bafe.interop b/src/basic/math/bafe.interop similarity index 100% rename from c64/basic/math/bafe.interop rename to src/basic/math/bafe.interop diff --git a/c64/basic/math/bb0f.div_MEM_FAC1.s b/src/basic/math/bb0f.div_MEM_FAC1.s similarity index 100% rename from c64/basic/math/bb0f.div_MEM_FAC1.s rename to src/basic/math/bb0f.div_MEM_FAC1.s diff --git a/c64/basic/math/bb0f.interop b/src/basic/math/bb0f.interop similarity index 100% rename from c64/basic/math/bb0f.interop rename to src/basic/math/bb0f.interop diff --git a/c64/basic/math/bb12.div_FAC2_FAC1.s b/src/basic/math/bb12.div_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/bb12.div_FAC2_FAC1.s rename to src/basic/math/bb12.div_FAC2_FAC1.s diff --git a/c64/basic/math/bb12.interop b/src/basic/math/bb12.interop similarity index 100% rename from c64/basic/math/bb12.interop rename to src/basic/math/bb12.interop diff --git a/c64/basic/math/bc1b.interop b/src/basic/math/bc1b.interop similarity index 100% rename from c64/basic/math/bc1b.interop rename to src/basic/math/bc1b.interop diff --git a/c64/basic/math/bc1b.round_FAC1.jmp.s b/src/basic/math/bc1b.round_FAC1.jmp.s similarity index 100% rename from c64/basic/math/bc1b.round_FAC1.jmp.s rename to src/basic/math/bc1b.round_FAC1.jmp.s diff --git a/c64/basic/math/bc2b.interop b/src/basic/math/bc2b.interop similarity index 100% rename from c64/basic/math/bc2b.interop rename to src/basic/math/bc2b.interop diff --git a/c64/basic/math/bc2b.sgn_FAC1_A.s b/src/basic/math/bc2b.sgn_FAC1_A.s similarity index 100% rename from c64/basic/math/bc2b.sgn_FAC1_A.s rename to src/basic/math/bc2b.sgn_FAC1_A.s diff --git a/c64/basic/math/bf71.interop b/src/basic/math/bf71.interop similarity index 100% rename from c64/basic/math/bf71.interop rename to src/basic/math/bf71.interop diff --git a/c64/basic/math/bf71.sqr_FAC1.s b/src/basic/math/bf71.sqr_FAC1.s similarity index 100% rename from c64/basic/math/bf71.sqr_FAC1.s rename to src/basic/math/bf71.sqr_FAC1.s diff --git a/c64/basic/math/bf78.interop b/src/basic/math/bf78.interop similarity index 100% rename from c64/basic/math/bf78.interop rename to src/basic/math/bf78.interop diff --git a/c64/basic/math/bf78.pwr_FAC2_MEM.s b/src/basic/math/bf78.pwr_FAC2_MEM.s similarity index 100% rename from c64/basic/math/bf78.pwr_FAC2_MEM.s rename to src/basic/math/bf78.pwr_FAC2_MEM.s diff --git a/c64/basic/math/bfb4.interop b/src/basic/math/bfb4.interop similarity index 100% rename from c64/basic/math/bfb4.interop rename to src/basic/math/bfb4.interop diff --git a/c64/basic/math/bfb4.toggle_sign_FAC1.s b/src/basic/math/bfb4.toggle_sign_FAC1.s similarity index 100% rename from c64/basic/math/bfb4.toggle_sign_FAC1.s rename to src/basic/math/bfb4.toggle_sign_FAC1.s diff --git a/c64/basic/math/div_FAC1_denorm.s b/src/basic/math/div_FAC1_denorm.s similarity index 100% rename from c64/basic/math/div_FAC1_denorm.s rename to src/basic/math/div_FAC1_denorm.s diff --git a/c64/basic/math/div_mantissas.s b/src/basic/math/div_mantissas.s similarity index 100% rename from c64/basic/math/div_mantissas.s rename to src/basic/math/div_mantissas.s diff --git a/c64/basic/math/e097.interop b/src/basic/math/e097.interop similarity index 100% rename from c64/basic/math/e097.interop rename to src/basic/math/e097.interop diff --git a/c64/basic/math/e097.rnd_FAC1.s b/src/basic/math/e097.rnd_FAC1.s similarity index 100% rename from c64/basic/math/e097.rnd_FAC1.s rename to src/basic/math/e097.rnd_FAC1.s diff --git a/c64/basic/math/e09a.interop b/src/basic/math/e09a.interop similarity index 100% rename from c64/basic/math/e09a.interop rename to src/basic/math/e09a.interop diff --git a/c64/basic/math/e09a.rnd_A.s b/src/basic/math/e09a.rnd_A.s similarity index 100% rename from c64/basic/math/e09a.rnd_A.s rename to src/basic/math/e09a.rnd_A.s diff --git a/c64/basic/math/e0be.interop b/src/basic/math/e0be.interop similarity index 100% rename from c64/basic/math/e0be.interop rename to src/basic/math/e0be.interop diff --git a/c64/basic/math/e0be.rnd_generate.s b/src/basic/math/e0be.rnd_generate.s similarity index 100% rename from c64/basic/math/e0be.rnd_generate.s rename to src/basic/math/e0be.rnd_generate.s diff --git a/c64/basic/math/mul10_FAC1_mul2.s b/src/basic/math/mul10_FAC1_mul2.s similarity index 100% rename from c64/basic/math/mul10_FAC1_mul2.s rename to src/basic/math/mul10_FAC1_mul2.s diff --git a/c64/basic/math/mul_FAC2_FAC1.s b/src/basic/math/mul_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/mul_FAC2_FAC1.s rename to src/basic/math/mul_FAC2_FAC1.s diff --git a/c64/basic/math/mul_FAC2_FAC1_8x8.s b/src/basic/math/mul_FAC2_FAC1_8x8.s similarity index 100% rename from c64/basic/math/mul_FAC2_FAC1_8x8.s rename to src/basic/math/mul_FAC2_FAC1_8x8.s diff --git a/c64/basic/math/mul_FAC2_FAC1_shift.s b/src/basic/math/mul_FAC2_FAC1_shift.s similarity index 100% rename from c64/basic/math/mul_FAC2_FAC1_shift.s rename to src/basic/math/mul_FAC2_FAC1_shift.s diff --git a/c64/basic/math/muldiv_RESHO_helpers.s b/src/basic/math/muldiv_RESHO_helpers.s similarity index 100% rename from c64/basic/math/muldiv_RESHO_helpers.s rename to src/basic/math/muldiv_RESHO_helpers.s diff --git a/c64/basic/math/normal_FAC1.s b/src/basic/math/normal_FAC1.s similarity index 100% rename from c64/basic/math/normal_FAC1.s rename to src/basic/math/normal_FAC1.s diff --git a/c64/basic/math/rnd_seed_from_FAC1.s b/src/basic/math/rnd_seed_from_FAC1.s similarity index 100% rename from c64/basic/math/rnd_seed_from_FAC1.s rename to src/basic/math/rnd_seed_from_FAC1.s diff --git a/c64/basic/math/rnd_seed_init.s b/src/basic/math/rnd_seed_init.s similarity index 100% rename from c64/basic/math/rnd_seed_init.s rename to src/basic/math/rnd_seed_init.s diff --git a/c64/basic/math/round_FAC1.s b/src/basic/math/round_FAC1.s similarity index 100% rename from c64/basic/math/round_FAC1.s rename to src/basic/math/round_FAC1.s diff --git a/c64/basic/math_consts/aea8.const_PI.s b/src/basic/math_consts/aea8.const_PI.s similarity index 100% rename from c64/basic/math_consts/aea8.const_PI.s rename to src/basic/math_consts/aea8.const_PI.s diff --git a/c64/basic/math_consts/aea8.interop b/src/basic/math_consts/aea8.interop similarity index 100% rename from c64/basic/math_consts/aea8.interop rename to src/basic/math_consts/aea8.interop diff --git a/c64/basic/math_consts/b1a5.const_NEG_32768.s b/src/basic/math_consts/b1a5.const_NEG_32768.s similarity index 100% rename from c64/basic/math_consts/b1a5.const_NEG_32768.s rename to src/basic/math_consts/b1a5.const_NEG_32768.s diff --git a/c64/basic/math_consts/b1a5.interop b/src/basic/math_consts/b1a5.interop similarity index 100% rename from c64/basic/math_consts/b1a5.interop rename to src/basic/math_consts/b1a5.interop diff --git a/c64/basic/math_consts/b9bc.const_ONE.s b/src/basic/math_consts/b9bc.const_ONE.s similarity index 100% rename from c64/basic/math_consts/b9bc.const_ONE.s rename to src/basic/math_consts/b9bc.const_ONE.s diff --git a/c64/basic/math_consts/b9bc.interop b/src/basic/math_consts/b9bc.interop similarity index 100% rename from c64/basic/math_consts/b9bc.interop rename to src/basic/math_consts/b9bc.interop diff --git a/c64/basic/math_consts/b9d6.const_INV_SQR_2.s b/src/basic/math_consts/b9d6.const_INV_SQR_2.s similarity index 100% rename from c64/basic/math_consts/b9d6.const_INV_SQR_2.s rename to src/basic/math_consts/b9d6.const_INV_SQR_2.s diff --git a/c64/basic/math_consts/b9d6.interop b/src/basic/math_consts/b9d6.interop similarity index 100% rename from c64/basic/math_consts/b9d6.interop rename to src/basic/math_consts/b9d6.interop diff --git a/c64/basic/math_consts/b9db.const_SQR_2.s b/src/basic/math_consts/b9db.const_SQR_2.s similarity index 100% rename from c64/basic/math_consts/b9db.const_SQR_2.s rename to src/basic/math_consts/b9db.const_SQR_2.s diff --git a/c64/basic/math_consts/b9db.interop b/src/basic/math_consts/b9db.interop similarity index 100% rename from c64/basic/math_consts/b9db.interop rename to src/basic/math_consts/b9db.interop diff --git a/c64/basic/math_consts/b9e0.const_NEG_HALF.s b/src/basic/math_consts/b9e0.const_NEG_HALF.s similarity index 100% rename from c64/basic/math_consts/b9e0.const_NEG_HALF.s rename to src/basic/math_consts/b9e0.const_NEG_HALF.s diff --git a/c64/basic/math_consts/b9e0.interop b/src/basic/math_consts/b9e0.interop similarity index 100% rename from c64/basic/math_consts/b9e0.interop rename to src/basic/math_consts/b9e0.interop diff --git a/c64/basic/math_consts/b9e5.const_LOG_2.s b/src/basic/math_consts/b9e5.const_LOG_2.s similarity index 100% rename from c64/basic/math_consts/b9e5.const_LOG_2.s rename to src/basic/math_consts/b9e5.const_LOG_2.s diff --git a/c64/basic/math_consts/b9e5.interop b/src/basic/math_consts/b9e5.interop similarity index 100% rename from c64/basic/math_consts/b9e5.interop rename to src/basic/math_consts/b9e5.interop diff --git a/c64/basic/math_consts/baf9.const_TEN.s b/src/basic/math_consts/baf9.const_TEN.s similarity index 100% rename from c64/basic/math_consts/baf9.const_TEN.s rename to src/basic/math_consts/baf9.const_TEN.s diff --git a/c64/basic/math_consts/baf9.interop b/src/basic/math_consts/baf9.interop similarity index 100% rename from c64/basic/math_consts/baf9.interop rename to src/basic/math_consts/baf9.interop diff --git a/c64/basic/math_consts/bf11.const_HALF.s b/src/basic/math_consts/bf11.const_HALF.s similarity index 100% rename from c64/basic/math_consts/bf11.const_HALF.s rename to src/basic/math_consts/bf11.const_HALF.s diff --git a/c64/basic/math_consts/bf11.interop b/src/basic/math_consts/bf11.interop similarity index 100% rename from c64/basic/math_consts/bf11.interop rename to src/basic/math_consts/bf11.interop diff --git a/c64/basic/math_consts/bfbf.const_INV_LOG_2.s b/src/basic/math_consts/bfbf.const_INV_LOG_2.s similarity index 100% rename from c64/basic/math_consts/bfbf.const_INV_LOG_2.s rename to src/basic/math_consts/bfbf.const_INV_LOG_2.s diff --git a/c64/basic/math_consts/bfbf.interop b/src/basic/math_consts/bfbf.interop similarity index 100% rename from c64/basic/math_consts/bfbf.interop rename to src/basic/math_consts/bfbf.interop diff --git a/c64/basic/math_consts/bfe8.const_ONE.s b/src/basic/math_consts/bfe8.const_ONE.s similarity index 100% rename from c64/basic/math_consts/bfe8.const_ONE.s rename to src/basic/math_consts/bfe8.const_ONE.s diff --git a/c64/basic/math_consts/bfe8.interop b/src/basic/math_consts/bfe8.interop similarity index 100% rename from c64/basic/math_consts/bfe8.interop rename to src/basic/math_consts/bfe8.interop diff --git a/c64/basic/math_consts/e2e0.const_HALF_PI.s b/src/basic/math_consts/e2e0.const_HALF_PI.s similarity index 100% rename from c64/basic/math_consts/e2e0.const_HALF_PI.s rename to src/basic/math_consts/e2e0.const_HALF_PI.s diff --git a/c64/basic/math_consts/e2e0.interop b/src/basic/math_consts/e2e0.interop similarity index 100% rename from c64/basic/math_consts/e2e0.interop rename to src/basic/math_consts/e2e0.interop diff --git a/c64/basic/math_consts/e2e5.const_DOUBLE_PI.s b/src/basic/math_consts/e2e5.const_DOUBLE_PI.s similarity index 100% rename from c64/basic/math_consts/e2e5.const_DOUBLE_PI.s rename to src/basic/math_consts/e2e5.const_DOUBLE_PI.s diff --git a/c64/basic/math_consts/e2e5.interop b/src/basic/math_consts/e2e5.interop similarity index 100% rename from c64/basic/math_consts/e2e5.interop rename to src/basic/math_consts/e2e5.interop diff --git a/c64/basic/math_consts/e2ea.const_QUARTER.s b/src/basic/math_consts/e2ea.const_QUARTER.s similarity index 100% rename from c64/basic/math_consts/e2ea.const_QUARTER.s rename to src/basic/math_consts/e2ea.const_QUARTER.s diff --git a/c64/basic/math_consts/e2ea.interop b/src/basic/math_consts/e2ea.interop similarity index 100% rename from c64/basic/math_consts/e2ea.interop rename to src/basic/math_consts/e2ea.interop diff --git a/c64/basic/math_consts/e309.const_DOUBLE_PI.s b/src/basic/math_consts/e309.const_DOUBLE_PI.s similarity index 100% rename from c64/basic/math_consts/e309.const_DOUBLE_PI.s rename to src/basic/math_consts/e309.const_DOUBLE_PI.s diff --git a/c64/basic/math_consts/e309.interop b/src/basic/math_consts/e309.interop similarity index 100% rename from c64/basic/math_consts/e309.interop rename to src/basic/math_consts/e309.interop diff --git a/c64/basic/math_mov/bba2.interop b/src/basic/math_mov/bba2.interop similarity index 100% rename from c64/basic/math_mov/bba2.interop rename to src/basic/math_mov/bba2.interop diff --git a/c64/basic/math_mov/bba2.mov_MEM_FAC1.jmp.s b/src/basic/math_mov/bba2.mov_MEM_FAC1.jmp.s similarity index 100% rename from c64/basic/math_mov/bba2.mov_MEM_FAC1.jmp.s rename to src/basic/math_mov/bba2.mov_MEM_FAC1.jmp.s diff --git a/c64/basic/math_mov/bbc7.interop b/src/basic/math_mov/bbc7.interop similarity index 100% rename from c64/basic/math_mov/bbc7.interop rename to src/basic/math_mov/bbc7.interop diff --git a/c64/basic/math_mov/bbc7.mov_r_FAC1_TMP2.s b/src/basic/math_mov/bbc7.mov_r_FAC1_TMP2.s similarity index 100% rename from c64/basic/math_mov/bbc7.mov_r_FAC1_TMP2.s rename to src/basic/math_mov/bbc7.mov_r_FAC1_TMP2.s diff --git a/c64/basic/math_mov/bbca.interop b/src/basic/math_mov/bbca.interop similarity index 100% rename from c64/basic/math_mov/bbca.interop rename to src/basic/math_mov/bbca.interop diff --git a/c64/basic/math_mov/bbca.mov_r_FAC1_TMP1.s b/src/basic/math_mov/bbca.mov_r_FAC1_TMP1.s similarity index 100% rename from c64/basic/math_mov/bbca.mov_r_FAC1_TMP1.s rename to src/basic/math_mov/bbca.mov_r_FAC1_TMP1.s diff --git a/c64/basic/math_mov/bbd0.interop b/src/basic/math_mov/bbd0.interop similarity index 100% rename from c64/basic/math_mov/bbd0.interop rename to src/basic/math_mov/bbd0.interop diff --git a/c64/basic/math_mov/bbd0.mov_r_FAC1_VAR.s b/src/basic/math_mov/bbd0.mov_r_FAC1_VAR.s similarity index 100% rename from c64/basic/math_mov/bbd0.mov_r_FAC1_VAR.s rename to src/basic/math_mov/bbd0.mov_r_FAC1_VAR.s diff --git a/c64/basic/math_mov/bbd4.interop b/src/basic/math_mov/bbd4.interop similarity index 100% rename from c64/basic/math_mov/bbd4.interop rename to src/basic/math_mov/bbd4.interop diff --git a/c64/basic/math_mov/bbd4.mov_r_FAC1_MEM.s b/src/basic/math_mov/bbd4.mov_r_FAC1_MEM.s similarity index 100% rename from c64/basic/math_mov/bbd4.mov_r_FAC1_MEM.s rename to src/basic/math_mov/bbd4.mov_r_FAC1_MEM.s diff --git a/c64/basic/math_mov/bbfc.interop b/src/basic/math_mov/bbfc.interop similarity index 100% rename from c64/basic/math_mov/bbfc.interop rename to src/basic/math_mov/bbfc.interop diff --git a/c64/basic/math_mov/bbfc.mov_FAC2_FAC1.s b/src/basic/math_mov/bbfc.mov_FAC2_FAC1.s similarity index 100% rename from c64/basic/math_mov/bbfc.mov_FAC2_FAC1.s rename to src/basic/math_mov/bbfc.mov_FAC2_FAC1.s diff --git a/c64/basic/math_mov/bc0c.interop b/src/basic/math_mov/bc0c.interop similarity index 100% rename from c64/basic/math_mov/bc0c.interop rename to src/basic/math_mov/bc0c.interop diff --git a/c64/basic/math_mov/bc0c.mov_r_FAC1_FAC2.s b/src/basic/math_mov/bc0c.mov_r_FAC1_FAC2.s similarity index 100% rename from c64/basic/math_mov/bc0c.mov_r_FAC1_FAC2.s rename to src/basic/math_mov/bc0c.mov_r_FAC1_FAC2.s diff --git a/c64/basic/math_mov/bc0f.interop b/src/basic/math_mov/bc0f.interop similarity index 100% rename from c64/basic/math_mov/bc0f.interop rename to src/basic/math_mov/bc0f.interop diff --git a/c64/basic/math_mov/bc0f.mov_FAC1_FAC2.jmp.s b/src/basic/math_mov/bc0f.mov_FAC1_FAC2.jmp.s similarity index 100% rename from c64/basic/math_mov/bc0f.mov_FAC1_FAC2.jmp.s rename to src/basic/math_mov/bc0f.mov_FAC1_FAC2.jmp.s diff --git a/c64/basic/math_mov/mov_FAC1_FAC2.s b/src/basic/math_mov/mov_FAC1_FAC2.s similarity index 100% rename from c64/basic/math_mov/mov_FAC1_FAC2.s rename to src/basic/math_mov/mov_FAC1_FAC2.s diff --git a/c64/basic/math_mov/mov_FAC1_MEM.s b/src/basic/math_mov/mov_FAC1_MEM.s similarity index 100% rename from c64/basic/math_mov/mov_FAC1_MEM.s rename to src/basic/math_mov/mov_FAC1_MEM.s diff --git a/c64/basic/math_mov/mov_FAC2_FAC1.s b/src/basic/math_mov/mov_FAC2_FAC1.s similarity index 100% rename from c64/basic/math_mov/mov_FAC2_FAC1.s rename to src/basic/math_mov/mov_FAC2_FAC1.s diff --git a/c64/basic/math_mov/mov_MEM_FAC1.s b/src/basic/math_mov/mov_MEM_FAC1.s similarity index 100% rename from c64/basic/math_mov/mov_MEM_FAC1.s rename to src/basic/math_mov/mov_MEM_FAC1.s diff --git a/c64/basic/math_mov/mov_MEM_FAC2.s b/src/basic/math_mov/mov_MEM_FAC2.s similarity index 100% rename from c64/basic/math_mov/mov_MEM_FAC2.s rename to src/basic/math_mov/mov_MEM_FAC2.s diff --git a/c64/basic/math_mov/mov_r_FAC1_TMP1.s b/src/basic/math_mov/mov_r_FAC1_TMP1.s similarity index 100% rename from c64/basic/math_mov/mov_r_FAC1_TMP1.s rename to src/basic/math_mov/mov_r_FAC1_TMP1.s diff --git a/c64/basic/math_mov/mov_r_FAC1_TMP2.s b/src/basic/math_mov/mov_r_FAC1_TMP2.s similarity index 100% rename from c64/basic/math_mov/mov_r_FAC1_TMP2.s rename to src/basic/math_mov/mov_r_FAC1_TMP2.s diff --git a/src/basic/memory/shift_mem_down_38k.s b/src/basic/memory/shift_mem_down_38k.s new file mode 100644 index 00000000..471ac56b --- /dev/null +++ b/src/basic/memory/shift_mem_down_38k.s @@ -0,0 +1,30 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +#if CONFIG_MEMORY_MODEL_38K + +shift_mem_down: + + // Move __memmove_size bytes from __memmove_src to __memmove_dst, + // where __memmove_dst > __memmove_src + // This means we have to copy from the back end down. + // This routine assumes the pointers are already pointed + // to the end of the areas, and that Y is correctly initialised + // to allow the copy to begin. + + php +!: + lda (__memmove_src),y + sta (__memmove_dst),y + iny + bne !- + inc __memmove_src+1 + inc __memmove_dst+1 + dec __memmove_size+1 + bne !- + plp + rts + +#endif diff --git a/src/basic/memory/shift_mem_up_38k.s b/src/basic/memory/shift_mem_up_38k.s new file mode 100644 index 00000000..c8fab14b --- /dev/null +++ b/src/basic/memory/shift_mem_up_38k.s @@ -0,0 +1,30 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +#if CONFIG_MEMORY_MODEL_38K + +shift_mem_up: + + // Move __memmove_size bytes from __memmove_src to __memmove_dst, + // where __memmove_dst > __memmove_src + // This means we have to copy from the back end down. + // This routine assumes the pointers are already pointed + // to the end of the areas, and that Y is correctly initialised + // to allow the copy to begin. + + php +!: + lda (__memmove_src),y + sta (__memmove_dst),y + dey + bne !- + dec __memmove_src+1 + dec __memmove_dst+1 + dec __memmove_size+1 + bne !- + plp + rts + +#endif diff --git a/src/basic/memory/under_rom_routines_46k_50k.s b/src/basic/memory/under_rom_routines_46k_50k.s new file mode 100644 index 00000000..7ceb7a84 --- /dev/null +++ b/src/basic/memory/under_rom_routines_46k_50k.s @@ -0,0 +1,147 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - as the routines below bank out the main BASIC ROM! + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + +peek_under_roms_via_TXTPTR: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs + + lda (TXTPTR), y + + // FALLTROUGH + +peek_under_roms_finalize: + + // Restore memory mapping + + pha + lda #$27 + sta CPU_R6510 + pla + + // Quit + + rts + +peek_under_roms_via_OLDTXT: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve value from under ROMs + + lda (OLDTXT), y + +#if HAS_OPCODES_65C02 + bra peek_under_roms_finalize +#else + jmp peek_under_roms_finalize +#endif + +peek_under_roms_via_FAC1_PLUS_1: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // 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 + + + +shift_mem_up: + + // Move __memmove_size bytes from __memmove_src to __memmove_dst, + // where __memmove_dst > __memmove_src + // This means we have to copy from the back end down. + // This routine assumes the pointers are already pointed + // to the end of the areas, and that Y is correctly initialised + // to allow the copy to begin. + + // Unmap BASIC lower ROM + + php + + lda #$26 + sta CPU_R6510 + + // Perform the copying +!: + lda (__memmove_src),y + sta (__memmove_dst),y + dey + bne !- + dec __memmove_src+1 + dec __memmove_dst+1 + dec __memmove_size+1 + bne !- + +#if HAS_OPCODES_65C02 + bra shift_mem_finalize +#else + jmp shift_mem_finalize +#endif + + +shift_mem_down: + + // Move __memmove_size bytes from __memmove_src to __memmove_dst, + // where __memmove_dst > __memmove_src + // This means we have to copy from the back end down. + // This routine assumes the pointers are already pointed + // to the end of the areas, and that Y is correctly initialised + // to allow the copy to begin. + + // Unmap BASIC lower ROM + + php + + lda #$26 + sta CPU_R6510 + + // Perform the copying +!: + lda (__memmove_src),y + sta (__memmove_dst),y + iny + bne !- + inc __memmove_src+1 + inc __memmove_dst+1 + dec __memmove_size+1 + bne !- + // FALLTROUGH + +shift_mem_finalize: + + // Restore memory mapping and quit + + lda #$27 + sta CPU_R6510 + + plp + + rts + + +#endif diff --git a/c64/basic/under_rom_routines.s b/src/basic/memory/under_rom_routines_60k.s similarity index 67% rename from c64/basic/under_rom_routines.s rename to src/basic/memory/under_rom_routines_60k.s index 611b7e65..0a07dbc7 100644 --- a/c64/basic/under_rom_routines.s +++ b/src/basic/memory/under_rom_routines_60k.s @@ -2,14 +2,14 @@ // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE -// IMPORTANT: -// These routines lengths cannot be changed without changing -// the aliases for peek_under_roms, poke_under_roms etc -// in ,aliases.s. -// Thus those addresses are expressed using formulae. #if CONFIG_MEMORY_MODEL_60K +// IMPORTANT: +// These routines lengths cannot be changed without changing +// the aliases for peek_under_roms, poke_under_roms, etc. +// Thus those addresses are expressed using formulae. + install_ram_routines: // Copy routines into place ldx #__ram_routines_end-__ram_routines_start-1 @@ -113,46 +113,4 @@ smd1: __ram_routines_end: -#else // CONFIG_MEMORY_MODEL_60K - -shift_mem_up: - // Move __memmove_size bytes from __memmove_src to __memmove_dst, - // where __memmove_dst > __memmove_src - // This means we have to copy from the back end down. - // This routine assumes the pointers are already pointed - // to the end of the areas, and that Y is correctly initialised - // to allow the copy to begin. - php -smu1: - lda (__memmove_src),y - sta (__memmove_dst),y - dey - bne smu1 - dec __memmove_src+1 - dec __memmove_dst+1 - dec __memmove_size+1 - bne smu1 - plp - rts - -shift_mem_down: - // Move __memmove_size bytes from __memmove_src to __memmove_dst, - // where __memmove_dst > __memmove_src - // This means we have to copy from the back end down. - // This routine assumes the pointers are already pointed - // to the end of the areas, and that Y is correctly initialised - // to allow the copy to begin. - php -smd1: - lda (__memmove_src),y - sta (__memmove_dst),y - iny - bne smd1 - inc __memmove_src+1 - inc __memmove_dst+1 - dec __memmove_size+1 - bne smd1 - plp - rts - #endif diff --git a/c64/basic/peek_line_pointer_null_check.s b/src/basic/peek_line_pointer_null_check.s similarity index 74% rename from c64/basic/peek_line_pointer_null_check.s rename to src/basic/peek_line_pointer_null_check.s index d3368be5..a73351d4 100644 --- a/c64/basic/peek_line_pointer_null_check.s +++ b/src/basic/peek_line_pointer_null_check.s @@ -13,6 +13,9 @@ peek_line_pointer_null_check: ldx #packed_dict_errors + bne print_dict_packed_string // branch always + +print_packed_misc_str: // .X - misc string index + + lda #packed_dict_misc + + // FALLTROUGH + +print_dict_packed_string: + + // Search for the packed string on the list + + jsr print_packed_search + + ldy #$00 +!: + // At this point FRESPC contains a pointer to the string to display + // Fetch a byte-code + + lda (FRESPC), y + beq print_dict_packed_string_end // branch if everything displayed + tax + dex + + // Call 'print_freq_packed_string' - but preserve all the data needed to progress further + + phy_trash_a + lda FRESPC+0 + pha + lda FRESPC+1 + pha + + lda #packed_dictionary + + jsr print_freq_packed_string + + pla + sta FRESPC+1 + pla + sta FRESPC+0 + ply_trash_a + + // Next iteration + + iny + bne !- // branch always + +print_dict_packed_string_end: + + rts + + +#endif diff --git a/src/basic/print/print_packed_freq_string.s b/src/basic/print/print_packed_freq_string.s new file mode 100644 index 00000000..a936a675 --- /dev/null +++ b/src/basic/print/print_packed_freq_string.s @@ -0,0 +1,165 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// This routine prints strings that have been packed using the 'generate_trings' tool. +// The general idea is to save space in the ROM. + + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + +print_packed_error: + + jsr map_BASIC_1 + jsr_ind VB1__print_packed_error + jmp map_NORMAL + +print_packed_misc_str: + + jsr map_BASIC_1 + jsr_ind VB1__print_packed_misc_str + jmp map_NORMAL + +#else + +#if !CONFIG_COMPRESSION_LVL_2 + +print_packed_error: // .X - error string index + + lda #packed_freq_errors + bne print_freq_packed_string // branch always + +print_packed_misc_str: // .X - misc string index + + lda #packed_freq_misc + bne print_freq_packed_string // branch always + +#endif + +print_packed_keyword_CC: // .X - token number + + lda #packed_freq_keywords_CC + bne print_freq_packed_string // branch always + +print_packed_keyword_CD: // .X - token number + + lda #packed_freq_keywords_CD + bne print_freq_packed_string // branch always + +print_packed_keyword_V2: // .X - token number + + lda #packed_freq_keywords_V2 + + // FALLTROUGH + +print_freq_packed_string: // not to be used directly XXX rename to print_packed_string + + // Search for the packed string on the list + + jsr print_packed_search + + // At this point FRESPC contains a pointer to the string to display + // and we should start from the lower nibble + + ldy #$00 + + // FALLTROUGH + +print_freq_packed_string_nibble_lo: + + // Get the low nibble and check for the end of packed string + + lda (FRESPC), y + and #$0F + beq print_freq_packed_string_end + + // Not the end - check if this is a common character, encoded by a single nibble + + cmp #$0F + beq print_freq_packed_string_3n_split + + // Character is encoded by a single nibble - fetch it and display + + tax + lda packed_as_1n-1, x + jsr JCHROUT // preserves .Y + + // FALLTROUGH + +print_freq_packed_string_nibble_hi: + + // Get the high nibble and check for the end of packed string + + lda (FRESPC), y + and #$F0 + beq print_freq_packed_string_end + + // Not the end - check if this is a common character, encoded by a single nibble + + cmp #$F0 + beq print_freq_packed_string_3n_single + + // Character is encoded by a single nibble - fetch it and display + + lsr + lsr + lsr + lsr + + tax + lda packed_as_1n-1, x + jmp !+ // XXX should be bra on some CPUs + +print_freq_packed_string_3n_single: + + // Character is encoded using 3 nibbles (1st is a mark, already interpreted) + + iny + lda (FRESPC), y + tax + lda packed_as_3n-1, x +!: + jsr JCHROUT // preserves .Y + + // Advance to next nibble + + iny + bne print_freq_packed_string_nibble_lo // branch always + +print_freq_packed_string_3n_split: + + // Character is encoded using 3 nibbles (1st is a mark, already interpreted), + // but the 2 remaining nibbles are in two neighbour bytes; use a stack to combine them + + lda (FRESPC), y + and #$F0 + tsx + pha + + iny + lda (FRESPC), y + and #$0F + + clc + adc STACK, x + + txs // one cycle faster than PLA + + tax + lda packed_as_3n-1, x + jsr JCHROUT // preserves .Y + + jmp print_freq_packed_string_nibble_hi + +print_freq_packed_string_end: + + rts + + +#endif // ROM layout diff --git a/src/basic/print/print_packed_search.s b/src/basic/print/print_packed_search.s new file mode 100644 index 00000000..f536eb2e --- /dev/null +++ b/src/basic/print/print_packed_search.s @@ -0,0 +1,40 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +print_packed_search: + + // First store the initial address of the packed strings list + + sta FRESPC+0 + sty FRESPC+1 + + // Now find the address of the string to print out + // The implementation assumes no packed string is longer than 255 bytes, including trailing zero +!: + cpx #$00 + beq print_packed_done // branch if no need to advance anymore + dex + + ldy #$00 +!: + lda (FRESPC), y + iny + cmp #$00 + bne !- // branch if not the end of packed string + + clc // advance FREESPC pointer + tya + adc FRESPC+0 + sta FRESPC+0 + lda #$00 + adc FRESPC+1 + sta FRESPC+1 + + jmp !-- + +print_packed_done: + + rts diff --git a/c64/basic/rom_revision/a004.identifier.s b/src/basic/rom_revision/a004.identifier.s similarity index 100% rename from c64/basic/rom_revision/a004.identifier.s rename to src/basic/rom_revision/a004.identifier.s diff --git a/c64/basic/rom_revision/a483.interop b/src/basic/rom_revision/a483.interop similarity index 100% rename from c64/basic/rom_revision/a483.interop rename to src/basic/rom_revision/a483.interop diff --git a/c64/basic/rom_revision/bf52.interop b/src/basic/rom_revision/bf52.interop similarity index 100% rename from c64/basic/rom_revision/bf52.interop rename to src/basic/rom_revision/bf52.interop diff --git a/c64/basic/rom_revision/bf52.rom_revision_basic.s b/src/basic/rom_revision/bf52.rom_revision_basic.s similarity index 100% rename from c64/basic/rom_revision/bf52.rom_revision_basic.s rename to src/basic/rom_revision/bf52.rom_revision_basic.s diff --git a/c64/basic/rom_revision/e4b7.interop b/src/basic/rom_revision/e4b7.interop similarity index 100% rename from c64/basic/rom_revision/e4b7.interop rename to src/basic/rom_revision/e4b7.interop diff --git a/c64/basic/rom_revision/e4b7.rom_revision_kernal.s b/src/basic/rom_revision/e4b7.rom_revision_kernal.s similarity index 100% rename from c64/basic/rom_revision/e4b7.rom_revision_kernal.s rename to src/basic/rom_revision/e4b7.rom_revision_kernal.s diff --git a/c64/basic/select_device.s b/src/basic/select_device.s similarity index 100% rename from c64/basic/select_device.s rename to src/basic/select_device.s diff --git a/src/basic/tokenizer/tk_cut_away.s b/src/basic/tokenizer/tk_cut_away.s new file mode 100644 index 00000000..c88e3c6a --- /dev/null +++ b/src/basic/tokenizer/tk_cut_away.s @@ -0,0 +1,37 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Cuts away unnecessary characters after tokenizing a keyword +// + + +tk_cut_away_2: // for two-bytes tokenized keywords + + dec tk__len_unpacked + + // FALLTROUGH + +tk_cut_away_1: // for single-byte tokenized keywords + + dec tk__len_unpacked // keyword length, afterwards number of bytes to cut away + + inc tk__offset + ldy tk__offset + + lda tk__len_unpacked + clc + adc tk__offset + tax +!: + lda BUF, x + sta BUF, y + beq !+ + + inx + iny + bne !- +!: + rts diff --git a/src/basic/tokenizer/tk_pack.s b/src/basic/tokenizer/tk_pack.s new file mode 100644 index 00000000..99c27e12 --- /dev/null +++ b/src/basic/tokenizer/tk_pack.s @@ -0,0 +1,229 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Packs a keyword candidate using a simple compression scheme, +// same as in 'generate_strings.cc'. +// +// This allows us to search through the compressed tokens directly +// using the compressed fragment of BASIC, and thus work out the +// token for a given piece of string. +// +// This also helps ensure that we have an implementation that is totally +// different to that of the original C64 BASIC, as well as likely +// saving a bit of space in the ROM, especially once we start implementing +// larger keyword vocabs for extended BASIC, since the compression and +// decompression machinery is of fixed size. +// +// Input: +// - .X = offset of string to pack, address is BUF ($0200) + .X +// Output: +// - see labels in 'tk_pack' +// + + +tk_pack: + + // Reuse the CPU stack - addresses below $102 are used by 'tokenise_line.s' + + .label tk__len_unpacked = $103 // length of unpacked data; it could replace 'tk__nibble_flag', but at the cost of code size/performance + .label tk__shorten_bits = $104 // 2 bytes for quick shortening of packed candidate + .label tk__nibble_flag = $106 // $00 = start from new byte, $FF = start from high nibble + .label tk__byte_offset = $107 // offset of the current byte (to place new data) in tk__packed + + .label tk__packed = $108 // packed candidate, 25 bytes is enough for worst case - a 16 byte keyword + + // Initialize variables + + lda #$00 + ldy #($04 + 25) // initialize 5 bytes of data + 25 bytes of space for packing +!: + sta tk__len_unpacked, y + dey + bpl !- + + // FALLTROUGH + +tk_pack_loop: + + // Get the next character + + lda BUF, x + + // If character cannot be a part of a keyword - do not pack anything more + + cmp #$23 // '#' - first sane character for a keyword + bcc tk_pack_done // branch if below '#' + cmp #$7B // 'Z' + 1 + bcs tk_pack_done // branch if above 'Z' + + // Keywords should not contain digits, colons, or semicolons + + cmp #$30 + bcc !+ // branch if below '0' + cmp #$3C + bcc tk_pack_done // branch if below '<' +!: + // Try to find a nibble to encode the character + + ldy #$0E +!: + cmp packed_as_1n-1, y + beq tk_pack_1n + + dey + bne !- + + // Try to find a 3-nibble sequence to encode the character (1st nibble is always 0xF in this case) + + ldy #TK__PACKED_AS_3N +!: + cmp packed_as_3n-1, y + beq tk_pack_3n + + dey + bne !- + + // If it is not on the list, it cannot be a part of token - quit + + // FALLTROUGH + +tk_pack_done: + + rts + +tk_pack_1n: + + // .Y contains our nibble; check whether we should start a new encoded byte + + bit tk__nibble_flag + bpl tk_pack_1n_new_byte + + // Store in the high nibble of the current byte + + tya + + asl + asl + asl + asl + + ldy tk__byte_offset + ora tk__packed, y + sta tk__packed, y + + // Adjust remaining counters / flags + + inc tk__byte_offset + inc tk__nibble_flag // $FF -> $00 + + // FALLTROUGH + +tk_pack_1n_done: + + // Put the bit mark - to indicate 1-nibble encoding + + clc + ror tk__shorten_bits+0 + ror tk__shorten_bits+1 + + // FALLTROUGH + +tk_pack_loop_next: + + // Prepare for the next loop iteration - increment counters + + inx + inc tk__len_unpacked + + // Check length, if it is OK to pack one more byte; quit if not + + lda tk__len_unpacked + cmp #TK__MAX_KEYWORD_LEN + bne tk_pack_loop + + rts + +tk_pack_1n_new_byte: + + // Store in the low nibble of the next byte + + tya + ldy tk__byte_offset + sta tk__packed, y + + // Adjust remaining counters / flags + + dec tk__nibble_flag // $00 -> $FF + bmi tk_pack_1n_done + +tk_pack_3n: + + // .Y contains 2 nibbles to encode; check whether we should start a new encoded byte + + bit tk__nibble_flag + bpl tk_pack_3n_new_byte + + // Store 1st nibble (alwys 0xF) in the high nibble of the current byte + + phy_trash_a + + lda #$F0 + ldy tk__byte_offset + ora tk__packed, y + sta tk__packed, y + + // Store byte in the next byte + + iny + pla + sta tk__packed, y + + // Adjust remaining counters / flags + + iny + sty tk__byte_offset + inc tk__nibble_flag // $FF -> $00 + + // FALLTROUGH + +tk_pack_3n_done: + + // Put the bit mark - to indicate 3-nibble encoding + + sec + ror tk__shorten_bits+0 + ror tk__shorten_bits+1 + + bcc tk_pack_loop_next // branch always + +tk_pack_3n_new_byte: + + // First store everything in the current byte, we will set '0xF' mark later + + tya + ldy tk__byte_offset + sta tk__packed, y + + // Now store just the low nibble in the next byte + + iny + and #$0F + sta tk__packed, y + + // Go back for a moment and set the '0xF' mark in the low nibble + + dey + lda tk__packed, y + ora #$0F + sta tk__packed, y + iny + + // Adjust remaining counters / flags + + sty tk__byte_offset + dec tk__nibble_flag // $00 -> $FF + + bmi tk_pack_3n_done // branch always diff --git a/src/basic/tokenizer/tk_search.s b/src/basic/tokenizer/tk_search.s new file mode 100644 index 00000000..fb847b24 --- /dev/null +++ b/src/basic/tokenizer/tk_search.s @@ -0,0 +1,93 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Search for a token on the list pointed by FRESPC +// +// Input: +// - list address in FRESPC, has to be refreshed after routine call +// - uses same variables as 'tk_pack' +// Output: +// - Carry set = not found +// - .X = index of token found +// + + +tk_search: + + ldx #$00 // initial token index + + // FALLTROUGH + +tk_search_loop: + + // Check if end of the list + + ldy #$00 + lda (FRESPC), y + cmp #$FF + bne tk_search_compare + iny + lda (FRESPC), y + dey + cmp #$FF + bne tk_search_compare + + // End of the list + + sec + rts + +tk_search_compare: + + // Compare the packed candidate with the current keyword list entry + + lda (FRESPC), y + cmp tk__packed, y + bne tk_search_not_matching + + cmp #$00 + beq tk_search_found + + // For now everything matches, try the next byte + + iny + bne tk_search_compare // branch always + +tk_search_not_matching: + + inx // increment token index + + // We need to find the end of the keyword on the list + // and proceed one byte further + + cmp #$00 + beq tk_search_next +!: + iny + lda (FRESPC), y + bne !- + + // FALLTROUGH + +tk_search_next: + + // Update FRESPC - advance by .Y + + iny + tya + clc + adc FRESPC+0 + sta FRESPC+0 + lda FRESPC+1 + adc #$00 + sta FRESPC+1 + + bcc tk_search_loop // branch always + +tk_search_found: + + clc + rts diff --git a/src/basic/tokenizer/tk_shorten.s b/src/basic/tokenizer/tk_shorten.s new file mode 100644 index 00000000..1d3fe0a1 --- /dev/null +++ b/src/basic/tokenizer/tk_shorten.s @@ -0,0 +1,113 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Shortens a keyword candidate previously packed by tk_pack by 1 character +// +// Input: +// - uses same variables as 'tk_pack' +// + + +tk_shorten: + + // First make sure we actually can shorten anything + + dec tk__len_unpacked + beq tk_shorten_end + + // Now check if the last character was encoded as 1 nibble or 3 nibbles + + asl tk__shorten_bits+1 + rol tk__shorten_bits+0 + bcs tk_shorten_3n + + // FALLTROUGH + +tk_shorten_1n: + + ldy tk__byte_offset // will be needed in both cases + + // Now we need to check which nibble to cut away + + bit tk__nibble_flag + bcs tk_shorten_1n_lo + + // FALLTROUGH + +tk_shorten_1n_hi: // tk__nibble_flag = $00, both nibbles free + + // Go back one byte and clear the high nibble only + + dey + sty tk__byte_offset + + lda tk__packed, y + and #$F0 + sta tk__packed, y + + // Adjust remaining counters / flags, and quit + + dec tk__nibble_flag // $00 -> $FF + + // FALLTROUGH + +tk_shorten_end: + + rts + +tk_shorten_1n_lo: // tk__nibble_flag = $FF, only the high nibble is free + + // Clear the whole byte, it will be faster + + lda #$00 + sta tk__packed, y + + // Adjust remaining counters / flags, and quit + + inc tk__nibble_flag // $FF -> $00 + rts + +tk_shorten_3n: + + ldy tk__byte_offset // will be needed in both cases + lda #$00 + + // Now we need to check which nibble to cut away + + bit tk__nibble_flag + bcs tk_shorten_3n_2bytes + + // FALLTROUGH + +tk_shorten_3n_byte_nibble: // tk__nibble_flag = $00, both nibbles free + + // Go back one byte, clear it, go back and clear the high nibble only + + dey + sta tk__packed, y + + // Reuse 'tk_shorten_1n_hi' + + sty tk__byte_offset +#if HAS_OPCODES_65C02 + bra tk_shorten_1n_hi +#else + jmp tk_shorten_1n_hi +#endif + +tk_shorten_3n_2bytes: // tk__nibble_flag = $FF, only the high nibble is free + + // Clear the byte, go back, clear one more byte + + sta tk__packed, y + dey + sta tk__packed, y + + // Adjust remaining counters / flags, and quit + + sty tk__byte_offset + inc tk__nibble_flag // $FF -> $00 + rts diff --git a/src/basic/tokenizer/tokenise_line.s b/src/basic/tokenizer/tokenise_line.s new file mode 100644 index 00000000..dc52f9de --- /dev/null +++ b/src/basic/tokenizer/tokenise_line.s @@ -0,0 +1,213 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tokenise a line of BASIC stored at $0200 +// +// Input: +// - length in __tokenise_work1 +// + + +tokenise_line: + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__tokenise_line + jmp map_NORMAL + +#else + + // Reuse the CPU stack - addresses above $101 are used by 'tk_pack.s' + + .label tk__offset = $100 // offset into string + .label tk__length = $101 // length of the raw string XXX reuse __tokenise_work1? + + // Initialize variables + + lda #$00 + sta tk__offset + + ldx __tokenise_work1 + stx tk__length + + // Terminate input string with $00 + + // XXX do we need this? + sta BUF, x + + // FALLTROUGH + +tokenise_line_loop: + + // Check if we have reached end of the line + + lda tk__offset + cmp tk__length + beq tokenise_line_done + + // Check for some special characters + + ldx tk__offset + lda BUF, x + + cmp #$22 + beq tokenise_line_quote + + cmp #$DE + beq tokenise_line_pi + + cmp #$3F + beq tokenise_line_question_mark // shortcut for PRINT command + + // Try to tokenise + + jsr tk_pack +!: + lda tk__len_unpacked + beq tokenise_line_char // branch if attempt to tokenise failed + + // Check for BASIC V2 tokens + + lda #packed_freq_keywords_V2 + sta FRESPC+1 + + jsr tk_search + bcc tokenise_line_keyword_V2 // branch if keyword identified + + // Check for extended tokens + + lda #packed_freq_keywords_CC + sta FRESPC+1 + + jsr tk_search + bcc tokenise_line_keyword_CC // branch if keyword identified + + lda #packed_freq_keywords_CD + sta FRESPC+1 + + jsr tk_search + bcc tokenise_line_keyword_CD // branch if keyword identified + + // Shorten packed keyword candidate and try again + + jsr tk_shorten + +#if HAS_OPCODES_65C02 + bra !- +#else + jmp !- +#endif + +tokenise_line_keyword_V2: + + // .X contains a token ID, starting from 0 + + txa + pha // store the token on the stack, we will need it for REM support + + // Store the token + + ldx tk__offset + clc + adc #$80 + sta BUF, x + + // Cut away unnecessary bytes + + jsr tk_cut_away_1 + + // Special handling for REM command - after this one nothing more should be tokenised + + pla + cmp #$0F // REM token index + jmp tokenise_line_loop + + // FALLTROUGH + +tokenise_line_done: + + // Update line length and quit + + lda tk__length + sta __tokenise_work1 + + rts + +tokenise_line_quote: + + // For the quote, we advance without tokenizing, until the next quote is found + + inc tk__offset + ldx tk__offset + + lda BUF, x + beq tokenise_line_done + + cmp #$22 + beq tokenise_line_char + bne tokenise_line_quote // branch always + +tokenise_line_pi: + + lda #$FF // token for PI + skip_2_bytes_trash_nvz + + // FALLTROUGH + +tokenise_line_question_mark: + + lda #$99 // token for PRINT + sta BUF, x + + // FALLTROUGH + +tokenise_line_char: + + inc tk__offset + jmp tokenise_line_loop + + +// Support for extended keyword lists + +tokenise_line_keyword_CC: + + // Store the token list index + + lda #$CC + skip_2_bytes_trash_nvz + + // FALLTROUGH + +tokenise_line_keyword_CD: + + // Store the token list index + + lda #$CD + + ldy tk__offset + sta BUF, y + + // Store the sub-token itself + + inx + txa + iny + sty tk__offset + sta BUF, y + + // Cut away unnecessary bytes + + jsr tk_cut_away_2 + jmp tokenise_line_loop + +#endif // ROM layout diff --git a/c64/basic/wedge_dos.s b/src/basic/wedge/wedge_dos.s similarity index 97% rename from c64/basic/wedge_dos.s rename to src/basic/wedge/wedge_dos.s index 7b7db2a6..0e9b5d3d 100644 --- a/c64/basic/wedge_dos.s +++ b/src/basic/wedge/wedge_dos.s @@ -70,7 +70,6 @@ wedge_dos_command: !: // Retrieve status, print it if not OK jsr JCLALL - jsr print_return jsr wedge_dos_status_get lda BUF+0 cmp #$30 // '0' @@ -97,11 +96,14 @@ wedge_dos_change_drive: jmp do_ILLEGAL_DEVICE_NUMBER_error !: sta FA - jsr print_return - jmp basic_end_of_line + jmp basic_main_loop wedge_dos_status_get: + // New line - separate status from current display + + jsr print_return + // 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 @@ -131,17 +133,20 @@ wedge_dos_status_get: jsr JCHRIN bcc wedge_dos_x1 jmp wedge_dos_basic_error // XXX try to optimize this + wedge_dos_x1: sta BUF, y iny jmp !- !: + // Strip ending RETURN + + dey rts wedge_dos_status: jsr wedge_dos_status_get - jsr print_return // FALLTROUGH wedge_dos_status_print: @@ -186,9 +191,6 @@ wedge_dos_directory: jsr JCHRIN bcs wedge_dos_basic_error - // Print new line - jsr print_return - wedge_dos_directory_line: // Load a single line, reuse BASIC input buffer @@ -241,9 +243,8 @@ wedge_dos_clean_exit: wedge_dos_basic_error: pha jsr JCLALL - plx_trash_a - dex - jmp do_basic_error + pla + jmp do_kernal_error wedge_dos_setnam: // Now determine the length of the 'file' name diff --git a/src/basic/wedge/wedge_tape.s b/src/basic/wedge/wedge_tape.s new file mode 100644 index 00000000..ac89415d --- /dev/null +++ b/src/basic/wedge/wedge_tape.s @@ -0,0 +1,66 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +#if CONFIG_TAPE_WEDGE + + +// .X has to contain size of the buffer + +wedge_tape: + + lda #$FF + sta CURLIN+1 // in case of error do not print line number + + cpx #$02 + bne_16 do_SYNTAX_error + + lda BUF+1 + + cmp #$4C // 'L' + beq wedge_arrow_L + +#if CONFIG_TAPE_HEAD_ALIGN + + cmp #$48 // 'H' + beq wedge_arrow_H + +#endif + + jmp do_SYNTAX_error + +wedge_arrow_L: + + // Execute 'arrow + L' + + lda #$00 + sta FNLEN // default file name is empty + sta VERCKB // operation is LOAD, not VERIFY + + ldy #$01 +#if CONFIG_TAPE_TURBO + ldx #$07 // turbo tape device +#else + ldx #$01 // normal tape device +#endif + + jsr JSETFLS + + // Perform loading + + jmp cmd_load_got_params + +#if CONFIG_TAPE_HEAD_ALIGN + +wedge_arrow_H: + + jsr tape_head_align + + jsr print_return + jmp do_BREAK_error + +#endif + + +#endif // CONFIG_TAPE_WEDGE diff --git a/c64/kernal/,disabled/,aliases_ultimate64.s b/src/kernal/,disabled/,aliases_ultimate64.s similarity index 100% rename from c64/kernal/,disabled/,aliases_ultimate64.s rename to src/kernal/,disabled/,aliases_ultimate64.s diff --git a/c64/kernal/,disabled/u64_load.s b/src/kernal/,disabled/u64_load.s similarity index 100% rename from c64/kernal/,disabled/u64_load.s rename to src/kernal/,disabled/u64_load.s diff --git a/c64/kernal/,stubs/e6b6.advance_cursor.s b/src/kernal/,stubs/e6b6.advance_cursor.s similarity index 100% rename from c64/kernal/,stubs/e6b6.advance_cursor.s rename to src/kernal/,stubs/e6b6.advance_cursor.s diff --git a/c64/kernal/,stubs/e6b6.interop b/src/kernal/,stubs/e6b6.interop similarity index 100% rename from c64/kernal/,stubs/e6b6.interop rename to src/kernal/,stubs/e6b6.interop diff --git a/c64/kernal/,stubs/e701.interop b/src/kernal/,stubs/e701.interop similarity index 100% rename from c64/kernal/,stubs/e701.interop rename to src/kernal/,stubs/e701.interop diff --git a/c64/kernal/,stubs/e701.previous_line.s b/src/kernal/,stubs/e701.previous_line.s similarity index 100% rename from c64/kernal/,stubs/e701.previous_line.s rename to src/kernal/,stubs/e701.previous_line.s diff --git a/c64/kernal/,stubs/e716.chrout_screen.s b/src/kernal/,stubs/e716.chrout_screen.s similarity index 100% rename from c64/kernal/,stubs/e716.chrout_screen.s rename to src/kernal/,stubs/e716.chrout_screen.s diff --git a/c64/kernal/,stubs/e716.interop b/src/kernal/,stubs/e716.interop similarity index 100% rename from c64/kernal/,stubs/e716.interop rename to src/kernal/,stubs/e716.interop diff --git a/c64/kernal/,stubs/e96c.insert_line_at_top.s b/src/kernal/,stubs/e96c.insert_line_at_top.s similarity index 100% rename from c64/kernal/,stubs/e96c.insert_line_at_top.s rename to src/kernal/,stubs/e96c.insert_line_at_top.s diff --git a/c64/kernal/,stubs/e96c.interop b/src/kernal/,stubs/e96c.interop similarity index 100% rename from c64/kernal/,stubs/e96c.interop rename to src/kernal/,stubs/e96c.interop diff --git a/c64/kernal/,stubs/f3f6.interop b/src/kernal/,stubs/f3f6.interop similarity index 100% rename from c64/kernal/,stubs/f3f6.interop rename to src/kernal/,stubs/f3f6.interop diff --git a/c64/kernal/,stubs/f3f6.unknown.s b/src/kernal/,stubs/f3f6.unknown.s similarity index 100% rename from c64/kernal/,stubs/f3f6.unknown.s rename to src/kernal/,stubs/f3f6.unknown.s diff --git a/c64/kernal/,stubs/f646.iec_close.s b/src/kernal/,stubs/f646.iec_close.s similarity index 100% rename from c64/kernal/,stubs/f646.iec_close.s rename to src/kernal/,stubs/f646.iec_close.s diff --git a/c64/kernal/,stubs/f646.interop b/src/kernal/,stubs/f646.interop similarity index 100% rename from c64/kernal/,stubs/f646.interop rename to src/kernal/,stubs/f646.interop diff --git a/c64/kernal/,stubs/fd90.interop b/src/kernal/,stubs/fd90.interop similarity index 100% rename from c64/kernal/,stubs/fd90.interop rename to src/kernal/,stubs/fd90.interop diff --git a/c64/kernal/,stubs/fd90.unknown.s b/src/kernal/,stubs/fd90.unknown.s similarity index 100% rename from c64/kernal/,stubs/fd90.unknown.s rename to src/kernal/,stubs/fd90.unknown.s diff --git a/c64/kernal/assets/cartridge_signature.s b/src/kernal/assets/cartridge_signature.s similarity index 100% rename from c64/kernal/assets/cartridge_signature.s rename to src/kernal/assets/cartridge_signature.s diff --git a/c64/kernal/assets/e8da.colour_codes.s b/src/kernal/assets/e8da.colour_codes.s similarity index 100% rename from c64/kernal/assets/e8da.colour_codes.s rename to src/kernal/assets/e8da.colour_codes.s diff --git a/c64/kernal/assets/e8da.interop b/src/kernal/assets/e8da.interop similarity index 100% rename from c64/kernal/assets/e8da.interop rename to src/kernal/assets/e8da.interop diff --git a/c64/kernal/assets/fd30.interop b/src/kernal/assets/fd30.interop similarity index 100% rename from c64/kernal/assets/fd30.interop rename to src/kernal/assets/fd30.interop diff --git a/c64/kernal/assets/fd30.vector_defaults.s b/src/kernal/assets/fd30.vector_defaults.s similarity index 100% rename from c64/kernal/assets/fd30.vector_defaults.s rename to src/kernal/assets/fd30.vector_defaults.s diff --git a/src/kernal/assets/filename_any.s b/src/kernal/assets/filename_any.s new file mode 100644 index 00000000..c8524439 --- /dev/null +++ b/src/kernal/assets/filename_any.s @@ -0,0 +1,8 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * KERNAL_0 #TAKE +// #LAYOUT# * * #IGNORE + + +filename_any: + + .text "*" diff --git a/c64/kernal/assets/irq_timing_hi.s b/src/kernal/assets/irq_timing_hi.s similarity index 100% rename from c64/kernal/assets/irq_timing_hi.s rename to src/kernal/assets/irq_timing_hi.s diff --git a/c64/kernal/assets/irq_timing_lo.s b/src/kernal/assets/irq_timing_lo.s similarity index 100% rename from c64/kernal/assets/irq_timing_lo.s rename to src/kernal/assets/irq_timing_lo.s diff --git a/c64/kernal/assets/kernal_messages.s b/src/kernal/assets/kernal_messages.s similarity index 77% rename from c64/kernal/assets/kernal_messages.s rename to src/kernal/assets/kernal_messages.s index 3c876dc9..16129aa8 100644 --- a/c64/kernal/assets/kernal_messages.s +++ b/src/kernal/assets/kernal_messages.s @@ -26,19 +26,11 @@ #endif #endif -#if CONFIG_SHOW_PAL_NTSC -.label __MSG_KERNAL_PAL = __msg_kernalpal - __msg_kernal_first -.label __MSG_KERNAL_NTSC = __msg_kernalntsc - __msg_kernal_first -#endif - #if CONFIG_PANIC_SCREEN .label __MSG_KERNAL_PANIC = __msg_kernalpanic - __msg_kernal_first .label __MSG_KERNAL_PANIC_ROM_MISMATCH = __msg_kernalpanic_rom_mismatch - __msg_kernal_first #endif -#if CONFIG_SHOW_FEATURES -.label __MSG_KERNAL_FEATURES = __msg_kernalfeatures - __msg_kernal_first -#endif __msg_kernal_first: @@ -93,20 +85,6 @@ __msg_kernaloksearching: #endif -#if CONFIG_SHOW_PAL_NTSC - -__msg_kernalpal: - .text "PAL" - .byte $0D - .byte $80 + $0D // end of string mark + return - -__msg_kernalntsc: - .text "NTSC" - .byte $0D - .byte $80 + $0D // end of string mark + return - -#endif // CONFIG_SHOW_PAL_NTSC - #if CONFIG_PANIC_SCREEN __msg_kernalpanic: @@ -118,11 +96,3 @@ __msg_kernalpanic_rom_mismatch: .byte $80 + $48 // end of string mark + 'H' #endif // CONFIG_PANIC_SCREEN - -#if CONFIG_SHOW_FEATURES - -__msg_kernalfeatures: - .text BUILD_FEATURES_STR() - .byte $80 + $0D // end of string mark + return - -#endif // CONFIG_SHOW_FEATURES diff --git a/c64/kernal/assets/programmable_keys.s b/src/kernal/assets/programmable_keys.s similarity index 100% rename from c64/kernal/assets/programmable_keys.s rename to src/kernal/assets/programmable_keys.s diff --git a/c64/kernal/board_m65/4000.interop b/src/kernal/board_m65/4000.interop similarity index 100% rename from c64/kernal/board_m65/4000.interop rename to src/kernal/board_m65/4000.interop diff --git a/c64/kernal/board_m65/4000.mega65_vectable_kernal_1.s b/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s similarity index 87% rename from c64/kernal/board_m65/4000.mega65_vectable_kernal_1.s rename to src/kernal/board_m65/4000.mega65_vectable_kernal_1.s index 6c865009..9accb56b 100644 --- a/c64/kernal/board_m65/4000.mega65_vectable_kernal_1.s +++ b/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s @@ -17,6 +17,7 @@ .label VK1__load_tape_normal = $4000 + 2 * 3 .label VK1__load_tape_turbo = $4000 + 2 * 4 .label VK1__load_tape_auto = $4000 + 2 * 5 + .label VK1__tape_head_align = $4000 + 2 * 6 #else @@ -44,5 +45,10 @@ .word $0000 #endif +#if CONFIG_TAPE_HEAD_ALIGN + .word tape_head_align +#else + .word $0000 +#endif #endif diff --git a/c64/kernal/board_m65/mega65_imports.s b/src/kernal/board_m65/mega65_imports.s similarity index 86% rename from c64/kernal/board_m65/mega65_imports.s rename to src/kernal/board_m65/mega65_imports.s index e09cabb0..0588fa89 100644 --- a/c64/kernal/board_m65/mega65_imports.s +++ b/src/kernal/board_m65/mega65_imports.s @@ -9,6 +9,9 @@ .label STOP = KERNAL_0.STOP + +.label hw_entry_reset = KERNAL_0.hw_entry_reset +.label return_from_interrupt = KERNAL_0.return_from_interrupt .label clrchn_reset = KERNAL_0.clrchn_reset .label udtim_keyboard = KERNAL_0.udtim_keyboard @@ -55,3 +58,11 @@ .label tape_normal_byte_store = KERNAL_0.tape_normal_byte_store #endif + + +#if CONFIG_TAPE_HEAD_ALIGN + +.label CLALL = KERNAL_0.proxy_K1_CLALL +.label nmi_lock = KERNAL_0.nmi_lock + +#endif diff --git a/c64/kernal/board_m65/mega65_map_helpers.s b/src/kernal/board_m65/mega65_map_helpers.s similarity index 100% rename from c64/kernal/board_m65/mega65_map_helpers.s rename to src/kernal/board_m65/mega65_map_helpers.s diff --git a/c64/kernal/board_m65/mega65_proxies.s b/src/kernal/board_m65/mega65_proxies.s similarity index 90% rename from c64/kernal/board_m65/mega65_proxies.s rename to src/kernal/board_m65/mega65_proxies.s index 94026367..cf274435 100644 --- a/c64/kernal/board_m65/mega65_proxies.s +++ b/src/kernal/board_m65/mega65_proxies.s @@ -55,5 +55,15 @@ proxy_K1_print_return: jsr print_return jmp map_KERNAL_1 +#endif + + +#if CONFIG_TAPE_HEAD_ALIGN + +proxy_K1_CLALL: + + jsr map_NORMAL + jsr CLALL + jmp map_KERNAL_1 #endif diff --git a/c64/kernal/board_m65/mega65_redirect_load_tape.s b/src/kernal/board_m65/mega65_redirect_tape.s similarity index 74% rename from c64/kernal/board_m65/mega65_redirect_load_tape.s rename to src/kernal/board_m65/mega65_redirect_tape.s index 56061aca..4d25ab42 100644 --- a/c64/kernal/board_m65/mega65_redirect_load_tape.s +++ b/src/kernal/board_m65/mega65_redirect_tape.s @@ -2,7 +2,7 @@ // #LAYOUT# * * #IGNORE // -// ROM routine call redirect for tape loading +// ROM routine call redirect for tape routines // @@ -37,3 +37,14 @@ load_tape_auto: jmp map_NORMAL #endif + + +#if CONFIG_TAPE_HEAD_ALIGN + +tape_head_align: + + jsr map_KERNAL_1 + jsr_ind VK1__tape_head_align + jmp map_NORMAL + +#endif diff --git a/c64/kernal/board_m65/mega65_tape_normal_byte_store.s b/src/kernal/board_m65/mega65_tape_normal_byte_store.s similarity index 100% rename from c64/kernal/board_m65/mega65_tape_normal_byte_store.s rename to src/kernal/board_m65/mega65_tape_normal_byte_store.s diff --git a/c64/kernal/board_m65/mega65_unhide.s b/src/kernal/board_m65/mega65_unhide.s similarity index 100% rename from c64/kernal/board_m65/mega65_unhide.s rename to src/kernal/board_m65/mega65_unhide.s diff --git a/c64/kernal/board_x16/cx16_dummy.s b/src/kernal/board_x16/cx16_dummy.s similarity index 100% rename from c64/kernal/board_x16/cx16_dummy.s rename to src/kernal/board_x16/cx16_dummy.s diff --git a/c64/kernal/board_x16/cx16_stubs.s b/src/kernal/board_x16/cx16_stubs.s similarity index 100% rename from c64/kernal/board_x16/cx16_stubs.s rename to src/kernal/board_x16/cx16_stubs.s diff --git a/c64/kernal/errors.s b/src/kernal/errors.s similarity index 100% rename from c64/kernal/errors.s rename to src/kernal/errors.s diff --git a/c64/kernal/iec/acptr.s b/src/kernal/iec/acptr.s similarity index 100% rename from c64/kernal/iec/acptr.s rename to src/kernal/iec/acptr.s diff --git a/c64/kernal/iec/chkin_iec.s b/src/kernal/iec/chkin_iec.s similarity index 100% rename from c64/kernal/iec/chkin_iec.s rename to src/kernal/iec/chkin_iec.s diff --git a/c64/kernal/iec/chrin_iec.s b/src/kernal/iec/chrin_iec.s similarity index 100% rename from c64/kernal/iec/chrin_iec.s rename to src/kernal/iec/chrin_iec.s diff --git a/c64/kernal/iec/chrout_iec.s b/src/kernal/iec/chrout_iec.s similarity index 100% rename from c64/kernal/iec/chrout_iec.s rename to src/kernal/iec/chrout_iec.s diff --git a/c64/kernal/iec/ciout.s b/src/kernal/iec/ciout.s similarity index 100% rename from c64/kernal/iec/ciout.s rename to src/kernal/iec/ciout.s diff --git a/c64/kernal/iec/ckout_iec.s b/src/kernal/iec/ckout_iec.s similarity index 100% rename from c64/kernal/iec/ckout_iec.s rename to src/kernal/iec/ckout_iec.s diff --git a/c64/kernal/iec/close_iec.s b/src/kernal/iec/close_iec.s similarity index 100% rename from c64/kernal/iec/close_iec.s rename to src/kernal/iec/close_iec.s diff --git a/c64/kernal/iec/clrchn_iec.s b/src/kernal/iec/clrchn_iec.s similarity index 100% rename from c64/kernal/iec/clrchn_iec.s rename to src/kernal/iec/clrchn_iec.s diff --git a/c64/kernal/iec/iec_check_devnum.s b/src/kernal/iec/iec_check_devnum.s similarity index 100% rename from c64/kernal/iec/iec_check_devnum.s rename to src/kernal/iec/iec_check_devnum.s diff --git a/c64/kernal/iec/iec_close_load.s b/src/kernal/iec/iec_close_load.s similarity index 100% rename from c64/kernal/iec/iec_close_load.s rename to src/kernal/iec/iec_close_load.s diff --git a/c64/kernal/iec/iec_cmd_close.s b/src/kernal/iec/iec_cmd_close.s similarity index 100% rename from c64/kernal/iec/iec_cmd_close.s rename to src/kernal/iec/iec_cmd_close.s diff --git a/c64/kernal/iec/iec_cmd_open.s b/src/kernal/iec/iec_cmd_open.s similarity index 98% rename from c64/kernal/iec/iec_cmd_open.s rename to src/kernal/iec/iec_cmd_open.s index 6d1bba33..a4a0e2df 100644 --- a/c64/kernal/iec/iec_cmd_open.s +++ b/src/kernal/iec/iec_cmd_open.s @@ -20,7 +20,7 @@ iec_cmd_open: // similar to TKSA, but without turnaround !: ora #$F0 -#if CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA2 || CONFIG_IEC_BURST_SOFT +#if CONFIG_IEC_BURST_CIA1 || CONFIG_IEC_BURST_CIA2 || CONFIG_IEC_BURST_MEGA_65 pha jsr burst_advertise pla diff --git a/c64/kernal/iec/iec_pull_release.s b/src/kernal/iec/iec_pull_release.s similarity index 100% rename from c64/kernal/iec/iec_pull_release.s rename to src/kernal/iec/iec_pull_release.s diff --git a/c64/kernal/iec/iec_return.s b/src/kernal/iec/iec_return.s similarity index 100% rename from c64/kernal/iec/iec_return.s rename to src/kernal/iec/iec_return.s diff --git a/c64/kernal/iec/iec_rx_byte.s b/src/kernal/iec/iec_rx_byte.s similarity index 100% rename from c64/kernal/iec/iec_rx_byte.s rename to src/kernal/iec/iec_rx_byte.s diff --git a/c64/kernal/iec/iec_rx_check_eoi.s b/src/kernal/iec/iec_rx_check_eoi.s similarity index 100% rename from c64/kernal/iec/iec_rx_check_eoi.s rename to src/kernal/iec/iec_rx_check_eoi.s diff --git a/c64/kernal/iec/iec_send_file_name.s b/src/kernal/iec/iec_send_file_name.s similarity index 88% rename from c64/kernal/iec/iec_send_file_name.s rename to src/kernal/iec/iec_send_file_name.s index b250612a..2c850cf9 100644 --- a/c64/kernal/iec/iec_send_file_name.s +++ b/src/kernal/iec/iec_send_file_name.s @@ -20,6 +20,8 @@ iec_send_file_name_loop: #if CONFIG_MEMORY_MODEL_60K ldx #return_from_interrupt_rti + sta NMINV+1 + + // Stop timer A + + stx CIA2_CRA // $DD0E + + // Set timer A to 0, after starting NMI will occur immediately + + stx CIA2_TIMALO // $DD04 + stx CIA2_TIMAHI // $DD05 + + // Set timer A as source for NMI + + lda #$81 + sta CIA2_ICR // $DD0D + + // Start timer A to trigger the NMI + + lda #$01 + sta CIA2_CRA // $DD0E + + // All done. Unmaskable interrupts are now masked. + + rts + + +#endif diff --git a/c64/kernal/iostack/chkinout.s b/src/kernal/iostack/chkinout.s similarity index 100% rename from c64/kernal/iostack/chkinout.s rename to src/kernal/iostack/chkinout.s diff --git a/c64/kernal/iostack/clall_real.s b/src/kernal/iostack/clall_real.s similarity index 100% rename from c64/kernal/iostack/clall_real.s rename to src/kernal/iostack/clall_real.s diff --git a/c64/kernal/iostack/e50a.interop b/src/kernal/iostack/e50a.interop similarity index 100% rename from c64/kernal/iostack/e50a.interop rename to src/kernal/iostack/e50a.interop diff --git a/c64/kernal/iostack/e50a.plot.s b/src/kernal/iostack/e50a.plot.s similarity index 100% rename from c64/kernal/iostack/e50a.plot.s rename to src/kernal/iostack/e50a.plot.s diff --git a/c64/kernal/iostack/f13e.getin.s b/src/kernal/iostack/f13e.getin.s similarity index 100% rename from c64/kernal/iostack/f13e.getin.s rename to src/kernal/iostack/f13e.getin.s diff --git a/c64/kernal/iostack/f13e.interop b/src/kernal/iostack/f13e.interop similarity index 100% rename from c64/kernal/iostack/f13e.interop rename to src/kernal/iostack/f13e.interop diff --git a/c64/kernal/iostack/f157.chrin.s b/src/kernal/iostack/f157.chrin.s similarity index 100% rename from c64/kernal/iostack/f157.chrin.s rename to src/kernal/iostack/f157.chrin.s diff --git a/c64/kernal/iostack/f157.interop b/src/kernal/iostack/f157.interop similarity index 100% rename from c64/kernal/iostack/f157.interop rename to src/kernal/iostack/f157.interop diff --git a/c64/kernal/iostack/f1ca.chrout.s b/src/kernal/iostack/f1ca.chrout.s similarity index 100% rename from c64/kernal/iostack/f1ca.chrout.s rename to src/kernal/iostack/f1ca.chrout.s diff --git a/c64/kernal/iostack/f1ca.interop b/src/kernal/iostack/f1ca.interop similarity index 100% rename from c64/kernal/iostack/f1ca.interop rename to src/kernal/iostack/f1ca.interop diff --git a/c64/kernal/iostack/f20e.chkin.s b/src/kernal/iostack/f20e.chkin.s similarity index 100% rename from c64/kernal/iostack/f20e.chkin.s rename to src/kernal/iostack/f20e.chkin.s diff --git a/c64/kernal/iostack/f20e.interop b/src/kernal/iostack/f20e.interop similarity index 100% rename from c64/kernal/iostack/f20e.interop rename to src/kernal/iostack/f20e.interop diff --git a/c64/kernal/iostack/f250.ckout.s b/src/kernal/iostack/f250.ckout.s similarity index 100% rename from c64/kernal/iostack/f250.ckout.s rename to src/kernal/iostack/f250.ckout.s diff --git a/c64/kernal/iostack/f250.interop b/src/kernal/iostack/f250.interop similarity index 100% rename from c64/kernal/iostack/f250.interop rename to src/kernal/iostack/f250.interop diff --git a/c64/kernal/iostack/f291.close.s b/src/kernal/iostack/f291.close.s similarity index 100% rename from c64/kernal/iostack/f291.close.s rename to src/kernal/iostack/f291.close.s diff --git a/c64/kernal/iostack/f291.interop b/src/kernal/iostack/f291.interop similarity index 100% rename from c64/kernal/iostack/f291.interop rename to src/kernal/iostack/f291.interop diff --git a/c64/kernal/iostack/f32f.clall.jmp.s b/src/kernal/iostack/f32f.clall.jmp.s similarity index 100% rename from c64/kernal/iostack/f32f.clall.jmp.s rename to src/kernal/iostack/f32f.clall.jmp.s diff --git a/c64/kernal/iostack/f32f.interop b/src/kernal/iostack/f32f.interop similarity index 100% rename from c64/kernal/iostack/f32f.interop rename to src/kernal/iostack/f32f.interop diff --git a/c64/kernal/iostack/f333.clrchn.s b/src/kernal/iostack/f333.clrchn.s similarity index 100% rename from c64/kernal/iostack/f333.clrchn.s rename to src/kernal/iostack/f333.clrchn.s diff --git a/c64/kernal/iostack/f333.interop b/src/kernal/iostack/f333.interop similarity index 100% rename from c64/kernal/iostack/f333.interop rename to src/kernal/iostack/f333.interop diff --git a/c64/kernal/iostack/f34a.interop b/src/kernal/iostack/f34a.interop similarity index 100% rename from c64/kernal/iostack/f34a.interop rename to src/kernal/iostack/f34a.interop diff --git a/c64/kernal/iostack/f34a.open.s b/src/kernal/iostack/f34a.open.s similarity index 100% rename from c64/kernal/iostack/f34a.open.s rename to src/kernal/iostack/f34a.open.s diff --git a/c64/kernal/iostack/f49e.interop b/src/kernal/iostack/f49e.interop similarity index 100% rename from c64/kernal/iostack/f49e.interop rename to src/kernal/iostack/f49e.interop diff --git a/c64/kernal/iostack/f49e.load_prep.s b/src/kernal/iostack/f49e.load_prep.s similarity index 100% rename from c64/kernal/iostack/f49e.load_prep.s rename to src/kernal/iostack/f49e.load_prep.s diff --git a/c64/kernal/iostack/f4a5.interop b/src/kernal/iostack/f4a5.interop similarity index 100% rename from c64/kernal/iostack/f4a5.interop rename to src/kernal/iostack/f4a5.interop diff --git a/c64/kernal/iostack/f4a5.load.s b/src/kernal/iostack/f4a5.load.s similarity index 100% rename from c64/kernal/iostack/f4a5.load.s rename to src/kernal/iostack/f4a5.load.s diff --git a/c64/kernal/iostack/f5dd.interop b/src/kernal/iostack/f5dd.interop similarity index 100% rename from c64/kernal/iostack/f5dd.interop rename to src/kernal/iostack/f5dd.interop diff --git a/c64/kernal/iostack/f5dd.save_prep.s b/src/kernal/iostack/f5dd.save_prep.s similarity index 100% rename from c64/kernal/iostack/f5dd.save_prep.s rename to src/kernal/iostack/f5dd.save_prep.s diff --git a/c64/kernal/iostack/f5ed.interop b/src/kernal/iostack/f5ed.interop similarity index 100% rename from c64/kernal/iostack/f5ed.interop rename to src/kernal/iostack/f5ed.interop diff --git a/c64/kernal/iostack/f5ed.save.s b/src/kernal/iostack/f5ed.save.s similarity index 100% rename from c64/kernal/iostack/f5ed.save.s rename to src/kernal/iostack/f5ed.save.s diff --git a/c64/kernal/iostack/f6ed.interop b/src/kernal/iostack/f6ed.interop similarity index 100% rename from c64/kernal/iostack/f6ed.interop rename to src/kernal/iostack/f6ed.interop diff --git a/c64/kernal/iostack/findfls.s b/src/kernal/iostack/findfls.s similarity index 100% rename from c64/kernal/iostack/findfls.s rename to src/kernal/iostack/findfls.s diff --git a/c64/kernal/iostack/getin_real.s b/src/kernal/iostack/getin_real.s similarity index 100% rename from c64/kernal/iostack/getin_real.s rename to src/kernal/iostack/getin_real.s diff --git a/c64/kernal/iostack/load_save_common.s b/src/kernal/iostack/load_save_common.s similarity index 92% rename from c64/kernal/iostack/load_save_common.s rename to src/kernal/iostack/load_save_common.s index 000e88f8..6c5dc73e 100644 --- a/c64/kernal/iostack/load_save_common.s +++ b/src/kernal/iostack/load_save_common.s @@ -66,7 +66,18 @@ lvs_handle_byte_verify: // Compare with stored byte cmp TBTCNT -#else +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + // Store byte for comparing + sta TBTCNT + + ldy #0 + jsr peek_under_roms_via_EAL + + // Compare with stored byte + cmp TBTCNT + +#else // CONFIG_MEMORY_MODEL_38K ldy #0 cmp (EAL),y @@ -134,6 +145,8 @@ lvs_display_searching_for: #if CONFIG_MEMORY_MODEL_60K ldx #$D800 + lda #>COLOR_RAM sta PNT+1 sta USER+1 diff --git a/c64/kernal/screen/e9ff.interop b/src/kernal/screen/e9ff.interop similarity index 100% rename from c64/kernal/screen/e9ff.interop rename to src/kernal/screen/e9ff.interop diff --git a/c64/kernal/screen/e9ff.screen_clear_line.s b/src/kernal/screen/e9ff.screen_clear_line.s similarity index 100% rename from c64/kernal/screen/e9ff.screen_clear_line.s rename to src/kernal/screen/e9ff.screen_clear_line.s diff --git a/c64/kernal/screen/screen.s b/src/kernal/screen/screen.s similarity index 100% rename from c64/kernal/screen/screen.s rename to src/kernal/screen/screen.s diff --git a/c64/kernal/screen/screen_advance_to_next_line.s b/src/kernal/screen/screen_advance_to_next_line.s similarity index 100% rename from c64/kernal/screen/screen_advance_to_next_line.s rename to src/kernal/screen/screen_advance_to_next_line.s diff --git a/c64/kernal/screen/screen_calculate_pnt_user.s b/src/kernal/screen/screen_calculate_pnt_user.s similarity index 97% rename from c64/kernal/screen/screen_calculate_pnt_user.s rename to src/kernal/screen/screen_calculate_pnt_user.s index 4fc409fa..75603fc1 100644 --- a/c64/kernal/screen/screen_calculate_pnt_user.s +++ b/src/kernal/screen/screen_calculate_pnt_user.s @@ -50,7 +50,7 @@ screen_calculate_USER: sec sbc HIBASE clc - adc #>$d800 + adc #>COLOR_RAM sta USER+1 rts diff --git a/c64/kernal/screen/screen_calculate_pntr_lnmx.s b/src/kernal/screen/screen_calculate_pntr_lnmx.s similarity index 100% rename from c64/kernal/screen/screen_calculate_pntr_lnmx.s rename to src/kernal/screen/screen_calculate_pntr_lnmx.s diff --git a/c64/kernal/screen/screen_check_space_ends_line.s b/src/kernal/screen/screen_check_space_ends_line.s similarity index 100% rename from c64/kernal/screen/screen_check_space_ends_line.s rename to src/kernal/screen/screen_check_space_ends_line.s diff --git a/c64/kernal/screen/screen_check_toggle_quote.s b/src/kernal/screen/screen_check_toggle_quote.s similarity index 100% rename from c64/kernal/screen/screen_check_toggle_quote.s rename to src/kernal/screen/screen_check_toggle_quote.s diff --git a/c64/kernal/screen/screen_code_to_petscii.s b/src/kernal/screen/screen_code_to_petscii.s similarity index 100% rename from c64/kernal/screen/screen_code_to_petscii.s rename to src/kernal/screen/screen_code_to_petscii.s diff --git a/c64/kernal/screen/screen_get_cliped_pntr.s b/src/kernal/screen/screen_get_cliped_pntr.s similarity index 100% rename from c64/kernal/screen/screen_get_cliped_pntr.s rename to src/kernal/screen/screen_get_cliped_pntr.s diff --git a/c64/kernal/screen/screen_get_logical_line_end_ptr.s b/src/kernal/screen/screen_get_logical_line_end_ptr.s similarity index 100% rename from c64/kernal/screen/screen_get_logical_line_end_ptr.s rename to src/kernal/screen/screen_get_logical_line_end_ptr.s diff --git a/c64/kernal/screen/screen_grow_logical_line.s b/src/kernal/screen/screen_grow_logical_line.s similarity index 100% rename from c64/kernal/screen/screen_grow_logical_line.s rename to src/kernal/screen/screen_grow_logical_line.s diff --git a/c64/kernal/screen/screen_off.s b/src/kernal/screen/screen_off.s similarity index 100% rename from c64/kernal/screen/screen_off.s rename to src/kernal/screen/screen_off.s diff --git a/c64/kernal/screen/screen_on.s b/src/kernal/screen/screen_on.s similarity index 100% rename from c64/kernal/screen/screen_on.s rename to src/kernal/screen/screen_on.s diff --git a/c64/kernal/screen/screen_preserve_sal_eal.s b/src/kernal/screen/screen_preserve_sal_eal.s similarity index 100% rename from c64/kernal/screen/screen_preserve_sal_eal.s rename to src/kernal/screen/screen_preserve_sal_eal.s diff --git a/c64/kernal/screen/screen_restore_sal_eal.s b/src/kernal/screen/screen_restore_sal_eal.s similarity index 100% rename from c64/kernal/screen/screen_restore_sal_eal.s rename to src/kernal/screen/screen_restore_sal_eal.s diff --git a/c64/kernal/status.s b/src/kernal/status.s similarity index 100% rename from c64/kernal/status.s rename to src/kernal/status.s diff --git a/c64/kernal/tape/load_tape_normal.s b/src/kernal/tape/load_tape_normal.s similarity index 98% rename from c64/kernal/tape/load_tape_normal.s rename to src/kernal/tape/load_tape_normal.s index c53dabdb..c1ecd776 100644 --- a/c64/kernal/tape/load_tape_normal.s +++ b/src/kernal/tape/load_tape_normal.s @@ -45,6 +45,9 @@ load_tape_normal: // Start playing jsr tape_common_prepare_cia jsr tape_ask_play +#if CONFIG_TAPE_HEAD_ALIGN + jsr tape_prepare_reading +#endif // FALLTROUGH diff --git a/c64/kernal/tape/load_tape_turbo.s b/src/kernal/tape/load_tape_turbo.s similarity index 98% rename from c64/kernal/tape/load_tape_turbo.s rename to src/kernal/tape/load_tape_turbo.s index 7c421e90..fe20438e 100644 --- a/c64/kernal/tape/load_tape_turbo.s +++ b/src/kernal/tape/load_tape_turbo.s @@ -32,6 +32,9 @@ load_tape_auto: // Start playing jsr tape_common_prepare_cia jsr tape_ask_play +#if CONFIG_TAPE_HEAD_ALIGN + jsr tape_prepare_reading +#endif // FALLTROUGH diff --git a/c64/kernal/tape/tape_common.s b/src/kernal/tape/tape_common.s similarity index 98% rename from c64/kernal/tape/tape_common.s rename to src/kernal/tape/tape_common.s index fa813aef..f254dc43 100644 --- a/c64/kernal/tape/tape_common.s +++ b/src/kernal/tape/tape_common.s @@ -104,6 +104,17 @@ tape_wait_first_pulse: tape_wait_play_done: + lda #$01 + sta CAS1 // set the interlock + +#if CONFIG_TAPE_HEAD_ALIGN + + rts + +tape_prepare_reading: + +#endif // CONFIG_TAPE_HEAD_ALIGN + #if CONFIG_MB_MEGA_65 // Display confirmation @@ -115,9 +126,6 @@ tape_wait_play_done: // Prepare for reading - lda #$01 - sta CAS1 // set the interlock - jsr print_return jmp tape_screen_off_motor_on diff --git a/c64/kernal/tape/tape_common_autodetect.s b/src/kernal/tape/tape_common_autodetect.s similarity index 100% rename from c64/kernal/tape/tape_common_autodetect.s rename to src/kernal/tape/tape_common_autodetect.s diff --git a/c64/kernal/tape/tape_common_clean_sid.s b/src/kernal/tape/tape_common_clean_sid.s similarity index 100% rename from c64/kernal/tape/tape_common_clean_sid.s rename to src/kernal/tape/tape_common_clean_sid.s diff --git a/c64/kernal/tape/tape_common_ditch_verify.s b/src/kernal/tape/tape_common_ditch_verify.s similarity index 100% rename from c64/kernal/tape/tape_common_ditch_verify.s rename to src/kernal/tape/tape_common_ditch_verify.s diff --git a/c64/kernal/tape/tape_common_get_pulse.s b/src/kernal/tape/tape_common_get_pulse.s similarity index 92% rename from c64/kernal/tape/tape_common_get_pulse.s rename to src/kernal/tape/tape_common_get_pulse.s index b194ccd7..3cfccf75 100644 --- a/c64/kernal/tape/tape_common_get_pulse.s +++ b/src/kernal/tape/tape_common_get_pulse.s @@ -26,7 +26,7 @@ tape_common_get_pulse: ldx #%01010001 // start timer, force latch reload, count timer A underflows stx CIA2_CRB // $DD0F - cmp __pulse_threshold // sdefault pulse check + cmp __pulse_threshold // default pulse check rts diff --git a/c64/kernal/tape/tape_common_motor.s b/src/kernal/tape/tape_common_motor.s similarity index 100% rename from c64/kernal/tape/tape_common_motor.s rename to src/kernal/tape/tape_common_motor.s diff --git a/c64/kernal/tape/tape_common_prepare_cia.s b/src/kernal/tape/tape_common_prepare_cia.s similarity index 93% rename from c64/kernal/tape/tape_common_prepare_cia.s rename to src/kernal/tape/tape_common_prepare_cia.s index d4d6302c..dd9eb3c5 100644 --- a/c64/kernal/tape/tape_common_prepare_cia.s +++ b/src/kernal/tape/tape_common_prepare_cia.s @@ -42,6 +42,11 @@ tape_common_prepare_cia: // Setup CIA #2 timers ldx #$03 // set timer A to 4 ticks + + // FALLTROUGH + +tape_common_prepare_cia_by_x: // entry point for head align tool + stx CIA2_TIMALO // $DD04 ldx #$00 stx CIA2_TIMAHI // $DD05 diff --git a/c64/kernal/tape/tape_common_screen.s b/src/kernal/tape/tape_common_screen.s similarity index 100% rename from c64/kernal/tape/tape_common_screen.s rename to src/kernal/tape/tape_common_screen.s diff --git a/src/kernal/tape/tape_head_align.s b/src/kernal/tape/tape_head_align.s new file mode 100644 index 00000000..690c665b --- /dev/null +++ b/src/kernal/tape/tape_head_align.s @@ -0,0 +1,267 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 KERNAL_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tape head alignemnt tool +// + + +#if CONFIG_TAPE_HEAD_ALIGN + + +.label __ha_start = 12 // starting row of the chart +.label __ha_rows = 11 // number of rows for scrolling + +// Helper tables + +.label __ha_offsets = $1000; +.label __ha_masks = $1100; + +// Generated code location + +.label __ha_scroll = $1300; + +// Flag for GFX effects - reuse BASIC numeric work area on zero page + +.label __ha_gfxflag = TEMPF2; // 1 byte + + +tape_head_align: + + // Make sure user really wants to launch the tool + + jsr tape_ask_play + + // Disable interrupts, set proper I/O values + + jsr CLALL + + sei + + jsr IOINIT + // jsr CINT + + jsr nmi_lock + + // Prepare CIA timers + + ldx #$02 // set timer A to 3 ticks + jsr tape_common_prepare_cia_by_x + + ldx #$FF // timer to control scroll speed + stx CIA1_TIMBLO // $DC06 + stx CIA1_TIMBHI // $DC07 + + jsr tape_motor_on + + // Clear color data ($0800) + + ldy #$00 +!: + lda #(CONFIG_COLOR_TXT * $10 + CONFIG_COLOR_BG) + + sta $0800, y + sta $0900, y + sta $0A00, y + sta $0B00, y + + iny + bne !- + + // Clear bitmap data ($2000) + + lda #$20 + sta SAL+1 + tya // put 0 to .A + sta SAL+0 +!: + sta (SAL), y + iny + bne !- + + inc SAL+1 + ldx SAL+1 + cpx #$40 + bne !- + + // Print help message + + jsr tape_head_align_print_help + + // Make sure the row where the chart is being created is not visible + + lda #(CONFIG_COLOR_TXT * $10 + CONFIG_COLOR_TXT) + ldy #$24 +!: + sta $0800 + __ha_start * 40 + 1, y + sta $0800 + __ha_start * 40 + 1 + (__ha_rows + 1) * 40, y + + dey + bne !- + + // Set graphics mode + + lda #$28 // graphics start at $2000, color at $0800 + sta VIC_YMCSB + + lda #$3B // set bit 5 to enable graphic mode + sta VIC_SCROLY + + // Prepare lookup tables - to speed drawing, we are going to use two of them: + // - byte offset table will tell us which byte in memory to alter + // - mask will allow us to quickly put the pixel + + ldx #$00 // loop index + ldy #$00 // temporary value for mask calculation +!: + // Byte offset is simple, just zero the 3 least significant bits + + txa + and #%11111000 + sta __ha_offsets, x + + // Mask changes with each iteration, use our temporary value in .Y + + tya + clc + ror + bne !+ + lda #%10000000 +!: + tay + sta __ha_masks, x + + // Next iteration + + inx + bne !-- + + // Initialize flag for additional GFX effects + + stx __ha_gfxflag // .X is 0 at this moment + + // Generate helper code for screen scrolling + + jsr tape_head_align_gen_code + + // Provide new IRQ routine address + + lda #tape_head_align_irq + sta CINV+1 + + // Setup raster interrupt routine - see https://www.c64-wiki.com/wiki/Raster_interrupt + + lda #%01111111 // prevent CIA from generating interrupts + sta CIA1_ICR // $DC0D + + and VIC_SCROLY // clear the highest bit of RASTER + sta VIC_SCROLY // $D011 + + lda #$FB // we want no badlines during the interrupt, this raster is 100% safe + sta VIC_RASTER + + lda #%00000001 // enable raster interrupts + sta VIC_IRQMSK // $D01A + cli + +tape_head_align_loop_1: + + // Check for STOP key + + jsr udtim_keyboard + jsr STOP + bcs tape_head_align_quit + + // Launch the timer + + ldx #%00011001 // start timer, one-shot force latch reload, count system ticks + stx CIA1_CRB // $DC0F + + // Scroll the whole chart one line down + + ldx #$00 +!: + jsr __ha_scroll // scroll one column down, using fast generated code + + txa + clc + adc #$08 + tax + bne !- + + // Draw decorations + + lda __ha_gfxflag + inc __ha_gfxflag + clc + adc #$08 + and #%00001100 + bne !+ + ldy #%11110001 + lda #%10001111 + bne !++ +!: + ldy #%00000001 + lda #%10000000 +!: + ora __ha_chart + 7 + 8 * 0 + sta __ha_chart + 7 + 8 * 0 + + tya + ora __ha_chart + 7 + 8 * 31 + sta __ha_chart + 7 + 8 * 31 + + // Draw helper lines + + lda __ha_gfxflag + and #%00000010 + beq !+ + + // For 'normal' + + lda #%00000001 + ora __ha_chart + 7 + 8 * 6 + sta __ha_chart + 7 + 8 * 6 + + lda #%00000001 + ora __ha_chart + 7 + 8 * 13 + sta __ha_chart + 7 + 8 * 13 + + // For 'turbo' + + lda #%00010000 + ora __ha_chart + 7 + 8 * 21 + sta __ha_chart + 7 + 8 * 21 +!: + // FALLTROUGH + +tape_head_align_loop_2: + + lda CIA1_TIMBLO + and CIA1_TIMBHI + eor #$FF + + bne tape_head_align_loop_2 + beq tape_head_align_loop_1 + + +tape_head_align_quit: + + // It makes no sense to return to system, as we already destroyed + // a lot of memory; fust clear initial BASIC text area to prevent + // data recovery attempts, and reset + + ldx #$00 + txa +!: + sta $0800, x + inx + bne !- + + jmp hw_entry_reset + + +#endif // CONFIG_TAPE_HEAD_ALIGN diff --git a/src/kernal/tape/tape_head_align_gen_code.s b/src/kernal/tape/tape_head_align_gen_code.s new file mode 100644 index 00000000..f79b761a --- /dev/null +++ b/src/kernal/tape/tape_head_align_gen_code.s @@ -0,0 +1,138 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 KERNAL_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tape head alignemnt tool - helper code generator +// + + +#if CONFIG_TAPE_HEAD_ALIGN + + +// Helper variables - reuse BASIC numeric work area on zero page + +.label __ha_lda_addr = TEMPF1 + 0; // 2 bytes, for code generator +.label __ha_sta_addr = TEMPF1 + 2; // 2 bytes, for code generator + + +tape_head_align_gen_code: + + // Setup generated code start address + + lda #<__ha_scroll + sta SAL+0 + lda #>__ha_scroll + sta SAL+1 + + // Setup initial source and destination addresses + + ldy #<(__ha_chart + __ha_rows * (8 * 40) + 6) + sty __ha_lda_addr + 0 + iny + sty __ha_sta_addr + 0 + + ldy #>(__ha_chart + __ha_rows * (8 * 40) + 6) + sty __ha_lda_addr + 1 + sty __ha_sta_addr + 1 + + // Emit code to move 7 rows of one 8x8 cell +!: + ldx #$07 +!: + jsr tape_head_align_gen_code_emit_pair + + dec __ha_lda_addr + 0 + dec __ha_sta_addr + 0 + + dex + bne !- + + // Emit code to fetch a top row from the cell above + + inc __ha_lda_addr + 0 + sec + lda __ha_lda_addr + 0 + sbc #<(8 * 40 - 7) + sta __ha_lda_addr + 0 + lda __ha_lda_addr + 1 + sbc #>(8 * 40 - 7) + + sta __ha_lda_addr + 1 + + jsr tape_head_align_gen_code_emit_pair + + // Prepare addresses for the next iteration + + lda __ha_lda_addr + 0 + sta __ha_sta_addr + 0 + lda __ha_lda_addr + 1 + sta __ha_sta_addr + 1 + + dec __ha_lda_addr + 0 + + // Now, new iteration - if needed + + lda __ha_sta_addr + 0 + cmp #<(__ha_chart + 7) + bne !-- + lda __ha_sta_addr + 1 + cmp #>(__ha_chart + 7) + bne !-- + + // Last pair to be generated starts from LDA #$00 + + lda #$A9 + jsr tape_head_align_gen_code_emit_byte + lda #$00 + jsr tape_head_align_gen_code_emit_byte + + jsr tape_head_align_gen_code_emit_sta + + // Emit RTS and quit + + lda #$60 + jmp tape_head_align_gen_code_emit_byte + + + +tape_head_align_gen_code_emit_pair: + + lda #$BD // LDA absolute, x + jsr tape_head_align_gen_code_emit_byte + + lda __ha_lda_addr + 0 + jsr tape_head_align_gen_code_emit_byte + lda __ha_lda_addr + 1 + jsr tape_head_align_gen_code_emit_byte + + // FALLTROUGH + +tape_head_align_gen_code_emit_sta: + + lda #$9D // STA absolute, x + jsr tape_head_align_gen_code_emit_byte + + lda __ha_sta_addr + 0 + jsr tape_head_align_gen_code_emit_byte + lda __ha_sta_addr + 1 + + // FALLTROUGH + +tape_head_align_gen_code_emit_byte: + + ldy #$00 + sta (SAL), y +#if HAS_OPCODES_65CE02 + inw SAL +#else + inc SAL+0 + bne !+ + inc SAL+1 +!: +#endif + + rts + + +#endif // CONFIG_TAPE_HEAD_ALIGN diff --git a/src/kernal/tape/tape_head_align_get_pulse.s b/src/kernal/tape/tape_head_align_get_pulse.s new file mode 100644 index 00000000..71b22e8e --- /dev/null +++ b/src/kernal/tape/tape_head_align_get_pulse.s @@ -0,0 +1,45 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 KERNAL_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tape head alignemnt tool - reading pulses from tape +// + + +#if CONFIG_TAPE_HEAD_ALIGN + + +tape_head_align_get_pulse: + + // This routine differs from the one used to read pulse during tape reading: + // - it is not as precise + // - it terminates when timer reaches $FF + // - it returns value in .Y + + lda #$10 +!: + // Loop to detect signal + + ldy CIA2_TIMBLO // $DD06 + bit CIA1_ICR // $DC0D + bne !+ + + cpy #$FF + bne !- +!: + // FALLTROUGH + +tape_head_align_get_pulse_start_timer: + + // Start timer again, force latch reload, count timer A underflows + + lda #%01010001 + sta CIA2_CRB // $DD0F + + // Return with time elapsed in .Y + + rts + + +#endif // CONFIG_TAPE_HEAD_ALIGN diff --git a/src/kernal/tape/tape_head_align_help.s b/src/kernal/tape/tape_head_align_help.s new file mode 100644 index 00000000..a7115363 --- /dev/null +++ b/src/kernal/tape/tape_head_align_help.s @@ -0,0 +1,147 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 KERNAL_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tape head alignemnt tool - prints out a help message on screen +// + + +#if CONFIG_TAPE_HEAD_ALIGN + + +// Helper variable - reuse BASIC numeric work area on zero page + +.label __ha_storage = TEMPF1; // 1 byte + + +tape_head_align_print_help: + + // Make screen font visible + + lda CPU_R6510 + pha + and #%11111011 + sta CPU_R6510 + + // Print help message + + ldy #$00 + + // Retrieve address +!: + lda tape_head_align_help_text, y + iny + cmp #$FF + beq tape_head_align_print_end + sta EAL+0 + + lda tape_head_align_help_text, y + iny + sta EAL+1 +!: + // Retrieve and print character + + lda tape_head_align_help_text, y + iny + cmp #$FF + beq !-- + + sty __ha_storage + jsr tape_head_align_print_char + ldy __ha_storage + + bne !- // branch alwats + + +tape_head_align_print_end: + + // Restore normal memory configuration and quit + + pla + sta CPU_R6510 + rts + +tape_head_align_print_string: + + + +tape_head_align_print_char: + + // Calculate start address of character in .A + + sta SAL+0 + lda #$00 + sta SAL+1 + + asl SAL+0 + rol SAL+1 + asl SAL+0 + rol SAL+1 + asl SAL+0 + rol SAL+1 + + clc + lda SAL+1 + adc #$D0 + sta SAL+1 + + // Print out the character + + ldy #$07 +!: + lda (SAL), y + sta (EAL), y + dey + bpl !- + + // Prepare EAL for the next character + + lda EAL+0 + clc + adc #$08 + sta EAL+0 + bne !+ + inc EAL+1 +!: + rts + + +// +// Strings to print +// + +.encoding "screencode_upper" + + +tape_head_align_help_text: + + // Each string consists of: + // - destination (start byte) address + // - text in screencodes + // - $FF to mark end + + .word $2000 + (40 * 8) * 0 + 8 * 1 + .text "COMPUTER HAS TO TELL THE SIGNALS APART" + .byte $FF + + .word $2000 + (40 * 8) * 3 + 8 * 6 + .text "ALIGN HEAD FOR MINIMUM NOISE" + .byte $FF + + .word $2000 + (40 * 8) * 6 + 8 * 2 + .text "IF THE DECK HAS A PITCH (TAPE SPEED)" + .byte $FF + + .word $2000 + (40 * 8) * 7 + 8 * 1 + .text "CONTROL, TWEAK IT SO THAT DOTTED LINES" + .byte $FF + + .word $2000 + (40 * 8) * 8 + 8 * 5 + .text "ARE HALF A WAY BETWEEN SIGNALS" + .byte $FF + + .byte $FF // end of strings + + +#endif diff --git a/src/kernal/tape/tape_head_align_irq.s b/src/kernal/tape/tape_head_align_irq.s new file mode 100644 index 00000000..878041c6 --- /dev/null +++ b/src/kernal/tape/tape_head_align_irq.s @@ -0,0 +1,75 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 KERNAL_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tape head alignemnt tool - interrupt routine +// + + +#if CONFIG_TAPE_HEAD_ALIGN + + +tape_head_align_irq: + + // Acknowledge interrupt + + asl VIC_IRQ + + // Ignore 2 first pulses, they can be garbage + + jsr tape_head_align_get_pulse + jsr tape_head_align_get_pulse + + // Now, we can retrieve pulses for the chart + + ldx #$00 + + // FALLTROUGH + +tape_head_align_irq_loop: + + jsr tape_head_align_get_pulse + + // If we approached badlines again - we cannot use this measurement anymore + + lda VIC_SCROLY + bmi !+ // branch if lower border + + lda VIC_RASTER + cmp #$33 // first line where badline can occur + bcs tape_head_align_irq_end +!: + // Draw pulse on the screen + + cpy #$FF + beq !+ + + // Center the chart horizontaly, with some margin from top + + .label __ha_chart = $2000 + 8 * (40 * __ha_start + 4) + + phx_trash_a + + lda __ha_offsets, y + tax + lda __ha_masks, y + ora __ha_chart + 7, x + sta __ha_chart + 7, x + + plx_trash_a +!: + // Next iteration + + inx + cpx #$40 + bne tape_head_align_irq_loop + + // FALLTROUGH + +tape_head_align_irq_end: + + jmp return_from_interrupt + + +#endif // CONFIG_TAPE_HEAD_ALIGN diff --git a/c64/kernal/tape/tape_normal_calibrate.s b/src/kernal/tape/tape_normal_calibrate.s similarity index 100% rename from c64/kernal/tape/tape_normal_calibrate.s rename to src/kernal/tape/tape_normal_calibrate.s diff --git a/c64/kernal/tape/tape_normal_get_bit.s b/src/kernal/tape/tape_normal_get_bit.s similarity index 100% rename from c64/kernal/tape/tape_normal_get_bit.s rename to src/kernal/tape/tape_normal_get_bit.s diff --git a/c64/kernal/tape/tape_normal_get_byte.s b/src/kernal/tape/tape_normal_get_byte.s similarity index 100% rename from c64/kernal/tape/tape_normal_get_byte.s rename to src/kernal/tape/tape_normal_get_byte.s diff --git a/c64/kernal/tape/tape_normal_get_data_1.s b/src/kernal/tape/tape_normal_get_data_1.s similarity index 100% rename from c64/kernal/tape/tape_normal_get_data_1.s rename to src/kernal/tape/tape_normal_get_data_1.s diff --git a/c64/kernal/tape/tape_normal_get_data_2.s b/src/kernal/tape/tape_normal_get_data_2.s similarity index 100% rename from c64/kernal/tape/tape_normal_get_data_2.s rename to src/kernal/tape/tape_normal_get_data_2.s diff --git a/c64/kernal/tape/tape_normal_get_marker.s b/src/kernal/tape/tape_normal_get_marker.s similarity index 100% rename from c64/kernal/tape/tape_normal_get_marker.s rename to src/kernal/tape/tape_normal_get_marker.s diff --git a/c64/kernal/tape/tape_normal_get_pilot.s b/src/kernal/tape/tape_normal_get_pilot.s similarity index 100% rename from c64/kernal/tape/tape_normal_get_pilot.s rename to src/kernal/tape/tape_normal_get_pilot.s diff --git a/c64/kernal/tape/tape_normal_sync.s b/src/kernal/tape/tape_normal_sync.s similarity index 100% rename from c64/kernal/tape/tape_normal_sync.s rename to src/kernal/tape/tape_normal_sync.s diff --git a/c64/kernal/tape/tape_normal_update_checksum.s b/src/kernal/tape/tape_normal_update_checksum.s similarity index 100% rename from c64/kernal/tape/tape_normal_update_checksum.s rename to src/kernal/tape/tape_normal_update_checksum.s diff --git a/c64/kernal/tape/tape_turbo_bytestore.s b/src/kernal/tape/tape_turbo_bytestore.s similarity index 100% rename from c64/kernal/tape/tape_turbo_bytestore.s rename to src/kernal/tape/tape_turbo_bytestore.s diff --git a/c64/kernal/tape/tape_turbo_get_bit.s b/src/kernal/tape/tape_turbo_get_bit.s similarity index 100% rename from c64/kernal/tape/tape_turbo_get_bit.s rename to src/kernal/tape/tape_turbo_get_bit.s diff --git a/c64/kernal/tape/tape_turbo_get_byte.s b/src/kernal/tape/tape_turbo_get_byte.s similarity index 100% rename from c64/kernal/tape/tape_turbo_get_byte.s rename to src/kernal/tape/tape_turbo_get_byte.s diff --git a/c64/kernal/tape/tape_turbo_sync.s b/src/kernal/tape/tape_turbo_sync.s similarity index 100% rename from c64/kernal/tape/tape_turbo_sync.s rename to src/kernal/tape/tape_turbo_sync.s diff --git a/c64/kernal/tape/tape_turbo_sync_first.s b/src/kernal/tape/tape_turbo_sync_first.s similarity index 100% rename from c64/kernal/tape/tape_turbo_sync_first.s rename to src/kernal/tape/tape_turbo_sync_first.s diff --git a/c64/kernal/time/rdtim.s b/src/kernal/time/rdtim.s similarity index 100% rename from c64/kernal/time/rdtim.s rename to src/kernal/time/rdtim.s diff --git a/c64/kernal/time/settim.s b/src/kernal/time/settim.s similarity index 100% rename from c64/kernal/time/settim.s rename to src/kernal/time/settim.s diff --git a/c64/kernal/time/udtim.s b/src/kernal/time/udtim.s similarity index 100% rename from c64/kernal/time/udtim.s rename to src/kernal/time/udtim.s diff --git a/c64/program_traces/BASIC2.trace b/src/program_traces/BASIC2.trace similarity index 100% rename from c64/program_traces/BASIC2.trace rename to src/program_traces/BASIC2.trace diff --git a/c64/program_traces/README.md b/src/program_traces/README.md similarity index 100% rename from c64/program_traces/README.md rename to src/program_traces/README.md diff --git a/strings/012CA9022CA9032CA9042CA9052CA9062CA9072CA9082CA909 b/strings/012CA9022CA9032CA9042CA9052CA9062CA9072CA9082CA909 new file mode 100644 index 00000000..ca77c0d2 --- /dev/null +++ b/strings/012CA9022CA9032CA9042CA9052CA9062CA9072CA9082CA909 @@ -0,0 +1,3 @@ +$01 + BIT + LDA #$02 + BIT + LDA #$03 + ... + LDA #$09 + +Ledder of LDA's and BIT's - a common 6502 space-saving trick to set the CPU register value depending on the jump address and perform common action. Not creative - not copyrightable. diff --git a/strings/021860A90085 b/strings/021860A90085 new file mode 100644 index 00000000..046d28ca --- /dev/null +++ b/strings/021860A90085 @@ -0,0 +1,5 @@ +$18 + CLC + RTS + LDA #$00 + STA (zeropage address does not match) + +End of a routine reporting a success (by clearing Carry) followed by start of another routine, starting from putting 0 into .A register - plus some parts. Trivial - not copyrightable. + +BTW, most of the time the routines are placed in the order determined by algorithm, using a specialized tool (without human intervention), and this order can undergo major changes after a small code modification - and this similarity is most likely caused by the currently determined ROM layout. diff --git a/strings/0285B960 b/strings/0285B960 new file mode 100644 index 00000000..981bab45 --- /dev/null +++ b/strings/0285B960 @@ -0,0 +1,3 @@ +$02 + STA $B9 + RTS + +Routine ending by setting a zeropage variable + plus some part. Trivial - not copyrightable. diff --git a/strings/0980856A b/strings/0980856A new file mode 100644 index 00000000..d63a76be --- /dev/null +++ b/strings/0980856A @@ -0,0 +1,3 @@ +ORA #$80 + STA $6A + +Part of the code setting highest bit in a zeropage variable. Trivial - not copyrightable. diff --git a/strings/1860A900 b/strings/1860A900 new file mode 100644 index 00000000..15604581 --- /dev/null +++ b/strings/1860A900 @@ -0,0 +1,5 @@ +CLC + RTS + LDA #$00 + +End of a routine reporting a success (by clearing Carry) followed by start of another routine, starting from putting 0 into .A register. Trivial - not copyrightable. + +BTW, most of the time the routines are placed in the order determined by algorithm, using a specialized tool (without human intervention), and this order can undergo major changes after a small code modification - and this similarity is most likely caused by the currently determined ROM layout. diff --git a/strings/209EAD20 b/strings/209EAD20 new file mode 100644 index 00000000..03ccdf59 --- /dev/null +++ b/strings/209EAD20 @@ -0,0 +1,3 @@ +JSR $AD9E (CHRGOT) + JSR (address does not match) + +Call of a well-known subroutine + some part of other instruction. Trivial - not copyrightable. diff --git a/strings/278563A5 b/strings/278563A5 new file mode 100644 index 00000000..975d4737 --- /dev/null +++ b/strings/278563A5 @@ -0,0 +1,3 @@ +$27 + STA $63 + LDA (zeropage address does not match) + +Instruction (accessing well-known zeropage location) + some parts. Trivial - not copyrightable. diff --git a/strings/288564A5 b/strings/288564A5 new file mode 100644 index 00000000..d246494e --- /dev/null +++ b/strings/288564A5 @@ -0,0 +1,3 @@ +$28 + STA $64 + LDA (zeropage address does not match) + +Instruction (accessing well-known zeropage location) + some parts. Trivial - not copyrightable. diff --git a/strings/309004C93C90 b/strings/309004C93C90 new file mode 100644 index 00000000..17bda5a2 --- /dev/null +++ b/strings/309004C93C90 @@ -0,0 +1,3 @@ +$30 + BCC (offset matches) + CMP #$3C + BCC (offset does not match) + +Part of code checking whether the valu is within the given range. Not creative - not copyrightable. diff --git a/strings/48A56348 b/strings/48A56348 new file mode 100644 index 00000000..6a8bda71 --- /dev/null +++ b/strings/48A56348 @@ -0,0 +1,3 @@ +PHA + LDA $63 + PHA + +Part of the code storing several values on stack. Trivial - not copyrightable. diff --git a/strings/60A9012CA9 b/strings/60A9012CA9 new file mode 100644 index 00000000..b332d9e6 --- /dev/null +++ b/strings/60A9012CA9 @@ -0,0 +1,3 @@ +RTS + LDA #$01 + BIT + LDA + +Routine starting by setting .A to 1 or some other value, depending on entry address (common 6502 trick to save memoryy using BIT instruction). Not creative - not copyrightable. diff --git a/strings/60A9012CA900 b/strings/60A9012CA900 new file mode 100644 index 00000000..b98146f4 --- /dev/null +++ b/strings/60A9012CA900 @@ -0,0 +1,3 @@ +RTS + LDA #$01 + BIT + LDA #$00 + +Routine starting by setting .A to 0 or 1 depending on entry address (common 6502 trick to save memoryy using BIT instruction). Not creative - not copyrightable. diff --git a/strings/60C922D0 b/strings/60C922D0 new file mode 100644 index 00000000..7ae0b049 --- /dev/null +++ b/strings/60C922D0 @@ -0,0 +1,3 @@ +RTS + CMP #$22 + BNE (offset does not match) + +Routine starting by comparing accumulator to a predefined value - trivial, not copyrightable. diff --git a/strings/60C922D008A5D449 b/strings/60C922D008A5D449 new file mode 100644 index 00000000..cf26cf03 --- /dev/null +++ b/strings/60C922D008A5D449 @@ -0,0 +1,3 @@ +RTS + CMP #$22 + BNE (offset matches) + LDA $D4 + EOR (value does not match) + +Part of a routine handling quote flag (QTSW - $D4 on zeropage) depending on quote symbol ($22). Not creative (nothing complicated here and the similarity doesn't even cover the whole flow) - not copyrightable. diff --git a/strings/61A56585 b/strings/61A56585 new file mode 100644 index 00000000..e57488f7 --- /dev/null +++ b/strings/61A56585 @@ -0,0 +1,3 @@ +$61 + LDA $65 + STA (zeropage addres does not match) + +Instruction (accessing well-known zeropage location) + some parts. Trivial - not copyrightable. diff --git a/strings/62666366646665 b/strings/62666366646665 new file mode 100644 index 00000000..26e602d9 --- /dev/null +++ b/strings/62666366646665 @@ -0,0 +1,3 @@ +$62 + ROR $63 + ROR $64 + ROR $65 + +Right-rotate on a multibyte variable (typical 6502 code) - trivial, not copyrightable. diff --git a/strings/626663666466656670 b/strings/626663666466656670 new file mode 100644 index 00000000..21a369de --- /dev/null +++ b/strings/626663666466656670 @@ -0,0 +1,3 @@ +$62 + ROR $63 + ROR $64 + ROR $65 + ROR $70 + +Right-rotate on a multibyte variable (typical 6502 code) - trivial, not copyrightable. diff --git a/strings/65358535 b/strings/65358535 new file mode 100644 index 00000000..a2dfcd26 --- /dev/null +++ b/strings/65358535 @@ -0,0 +1,3 @@ +ADC $35 + STA $35 + +Adding a value to a zeropage variable. Trivial - not copyrightable. diff --git a/strings/6662666366646665 b/strings/6662666366646665 new file mode 100644 index 00000000..0f61ac66 --- /dev/null +++ b/strings/6662666366646665 @@ -0,0 +1,3 @@ +ROR $62 + ROR $63 + ROR $64 + ROR $65 + +Rotate-right operation done on a 32-bit value (floating point accumulator mantissa) - trivial, not copyrightable. diff --git a/strings/6662666366646665667060A5 b/strings/6662666366646665667060A5 new file mode 100644 index 00000000..43e94fa5 --- /dev/null +++ b/strings/6662666366646665667060A5 @@ -0,0 +1,3 @@ +ROR $62 + ROR $63 + ROR $64 + ROR $65 + ROR $70 + RTS + LDA (zeropage address does not match) + +Unrolled loop that performs a simple operation (shift by one bit) on a well-known variable - floating point accumulator mantissa. Plus some p[art of another instruction, from a different subroutine. Not creative and rather trivial - not copyrightable. diff --git a/strings/6663666466656670 b/strings/6663666466656670 new file mode 100644 index 00000000..8f8d4226 --- /dev/null +++ b/strings/6663666466656670 @@ -0,0 +1,3 @@ +ROR $63 + ROR $64 + ROR $65 + ROR $70 + +Right-rotate on a multibyte variable (typical 6502 code) - trivial, not copyrightable. diff --git a/strings/68856A6885 b/strings/68856A6885 new file mode 100644 index 00000000..0d77a3f6 --- /dev/null +++ b/strings/68856A6885 @@ -0,0 +1,3 @@ +PLA + STA $6A + PLA + STA (address does not match) + +Part of sequence storing several values on the stack. Trivial - not copyrightable. diff --git a/strings/68856B6885 b/strings/68856B6885 new file mode 100644 index 00000000..bf7bcfd1 --- /dev/null +++ b/strings/68856B6885 @@ -0,0 +1,3 @@ +PLA + STA $6B + PLA + STA (address does not match) + +Part of sequence storing several values on the stack. Trivial - not copyrightable. diff --git a/strings/69D0034C b/strings/69D0034C new file mode 100644 index 00000000..a2e1eabc --- /dev/null +++ b/strings/69D0034C @@ -0,0 +1,3 @@ +$69 + BNE (skip next instruction) + JMP (address does not match) + +Instruction plus some parts - trivial, not copyrightable. diff --git a/strings/85358436 b/strings/85358436 new file mode 100644 index 00000000..c61d15cc --- /dev/null +++ b/strings/85358436 @@ -0,0 +1,3 @@ +STA $35 + STY $36 + +Store two CPU registers in a 16-bit zeropage variable (FRESPC). Trivial - not copyrightable. diff --git a/strings/85658564 b/strings/85658564 new file mode 100644 index 00000000..1fe03e76 --- /dev/null +++ b/strings/85658564 @@ -0,0 +1,3 @@ +STA $65 + STA $64 + +Part of the code zeroing a temporary storage on zeropage. Trivial - not copyrightable. diff --git a/strings/91F38810F5 b/strings/91F38810F5 new file mode 100644 index 00000000..eadda531 --- /dev/null +++ b/strings/91F38810F5 @@ -0,0 +1,3 @@ +STA ($F3),Y + DEY + BPL (offset matches) + +Small part of the loop moving screen content. Not creative - not copyrightable. diff --git a/strings/A001B1B285 b/strings/A001B1B285 new file mode 100644 index 00000000..44f9cfdc --- /dev/null +++ b/strings/A001B1B285 @@ -0,0 +1,3 @@ +LDY #$01 + LDA ($B2),Y + STA (zeropage address does not match) + +Small part of the code (only 2 instructions fully match) fetching multi-byte value via zeropage pointer - trivial, not copyrightable. diff --git a/strings/A004B12285 b/strings/A004B12285 new file mode 100644 index 00000000..dd3688f6 --- /dev/null +++ b/strings/A004B12285 @@ -0,0 +1,3 @@ +LDY #$04 + LDA ($22),Y + STA (address does not match) + +Small part of the code (only 2 instructions fully match) fetching multi-byte value via zeropage pointer - trivial, not copyrightable. diff --git a/strings/A004B122856588B122856488B122856388B122 b/strings/A004B122856588B122856488B122856388B122 new file mode 100644 index 00000000..11b6c674 --- /dev/null +++ b/strings/A004B122856588B122856488B122856388B122 @@ -0,0 +1,3 @@ +LDY #$04 + LDA ($22),Y + STA $65 + DEY + LDA ($22),Y + STA $64 + DEY + LDA ($22),Y + STA $63 + DEY + LDA ($22),Y + +Unrolled loop that performs a simple operation (fetch from memory) on a well-known variable - floating point accumulator. Not creative and rather trivial - not copyrightable. diff --git a/strings/A004B122856D88B122856C88B122856B88B122 b/strings/A004B122856D88B122856C88B122856B88B122 new file mode 100644 index 00000000..316de38e --- /dev/null +++ b/strings/A004B122856D88B122856C88B122856B88B122 @@ -0,0 +1,3 @@ +LDY #$04 + LDA ($22),Y + STA $6D + DEY + LDA ($22),Y + STA $6C + DEY + LDA ($22),Y + STA $6B + DEY + LDA ($22),Y + +Part of unrolled loop that performs a simple operation (shift by one bit) on a well-known variable - floating point accumulator mantissa. Not creative and rather trivial - not copyrightable. diff --git a/strings/A2198616 b/strings/A2198616 new file mode 100644 index 00000000..b32f9e0f --- /dev/null +++ b/strings/A2198616 @@ -0,0 +1,3 @@ +LDX #$19 + STX $16 + +Store predefined value in a well-known zeropage location. Trivial - not copyrightable. diff --git a/strings/A5012910F0 b/strings/A5012910F0 new file mode 100644 index 00000000..4c011c4d --- /dev/null +++ b/strings/A5012910F0 @@ -0,0 +1,3 @@ +LDA $01 + AND #$10 + BEQ (offset does not match) + +Decision based on a state of a bit in a documented hardware register. Trivial - not copyrightable. diff --git a/strings/A56248A5 b/strings/A56248A5 new file mode 100644 index 00000000..13add0f8 --- /dev/null +++ b/strings/A56248A5 @@ -0,0 +1,4 @@ +LDA $62 + PHA + LDA (zeropage address does not match) + +Store zeropage variable on stack + some part - trivial, not copyrightable. + diff --git a/strings/A5648563 b/strings/A5648563 new file mode 100644 index 00000000..026aecf8 --- /dev/null +++ b/strings/A5648563 @@ -0,0 +1,3 @@ +LDA $64 + STA $63 + +Small part (2 instructions) of code manipulating a floating code mantissa. Trivial - not copyrightable. diff --git a/strings/A62DA42E b/strings/A62DA42E new file mode 100644 index 00000000..60368dc1 --- /dev/null +++ b/strings/A62DA42E @@ -0,0 +1,3 @@ +LDX $2D + LDY $2E + +2 instructions to fetch zeropage variable (VARTAB) for usage by Kernal documented API. Trivial - not copyrightable. diff --git a/strings/A63AE8D0 b/strings/A63AE8D0 new file mode 100644 index 00000000..cc32abeb --- /dev/null +++ b/strings/A63AE8D0 @@ -0,0 +1,3 @@ +LDX $3A + INX + BNE (offset does not match) + +Check whether a zeropage variable contains $FF. Trivial - not copyrightable. diff --git a/strings/A63AE8F0 b/strings/A63AE8F0 new file mode 100644 index 00000000..361fd785 --- /dev/null +++ b/strings/A63AE8F0 @@ -0,0 +1,3 @@ +LDX $3A + INX + BEQ (offset does not match) + +Check whether a zeropage variable contains $FF. Trivial - not copyrightable. diff --git a/strings/A9EFA0E2 b/strings/A9EFA0E2 new file mode 100644 index 00000000..bc12528b --- /dev/null +++ b/strings/A9EFA0E2 @@ -0,0 +1,3 @@ +LDA #$EF + LDY #$E2 + +2 instructions fetching known zeropage variables. Trivial - not copyrightable. diff --git a/strings/AE209EAD b/strings/AE209EAD new file mode 100644 index 00000000..a797f38b --- /dev/null +++ b/strings/AE209EAD @@ -0,0 +1,3 @@ +$AE + JSR $AD9E (FRMEVL) + +Instruction (calls a well-known routine) + some part. Trivial - not copyrightable. diff --git a/strings/AE209EAD20 b/strings/AE209EAD20 new file mode 100644 index 00000000..271509c4 --- /dev/null +++ b/strings/AE209EAD20 @@ -0,0 +1,3 @@ +$AE + JSR $AD9E (FRMEVL) + JSR (address does not match) + +Instruction (calls a well-known routine) + some parts. Trivial - not copyrightable. diff --git a/strings/B7F00A20 b/strings/B7F00A20 new file mode 100644 index 00000000..1dfc3334 --- /dev/null +++ b/strings/B7F00A20 @@ -0,0 +1,3 @@ +$B7 + BEQ (offset matches) + JSR (address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/C4B7F00A b/strings/C4B7F00A new file mode 100644 index 00000000..b84110a2 --- /dev/null +++ b/strings/C4B7F00A @@ -0,0 +1,3 @@ +CPY $B7 + BEQ (offset matches) + +Decision based on a fact whether CPU register is equal to zeropage variable. Trivial - not copyrightable. diff --git a/strings/C4D3D0EF b/strings/C4D3D0EF new file mode 100644 index 00000000..4200de6e --- /dev/null +++ b/strings/C4D3D0EF @@ -0,0 +1,3 @@ +CPY $D3 + BNE (offset matches) + +Decision based on a fact whether CPU register is equal to zeropage variable. Trivial - not copyrightable. diff --git a/strings/CAA000B1 b/strings/CAA000B1 new file mode 100644 index 00000000..a3bc6511 --- /dev/null +++ b/strings/CAA000B1 @@ -0,0 +1,3 @@ +$CA + LDY #$00 + LDA (zeropage address does not match), Y + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/D0FBC898 b/strings/D0FBC898 new file mode 100644 index 00000000..2b7528bb --- /dev/null +++ b/strings/D0FBC898 @@ -0,0 +1,3 @@ +BNE (offset matches) + INY + TYA + +Check for zero in some variable (or CPU register - similarity does not cover this part) + simple register manipulation. Not creative (too small fragment, this can be a piece of various routines) - not copyrightable. diff --git a/strings/F9F00720 b/strings/F9F00720 new file mode 100644 index 00000000..fce8ac5e --- /dev/null +++ b/strings/F9F00720 @@ -0,0 +1,3 @@ +$F9 + BEQ (offset matches) + JSR (address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/FF00000000000000000000 b/strings/FF00000000000000000000 new file mode 100644 index 00000000..2c98882f --- /dev/null +++ b/strings/FF00000000000000000000 @@ -0,0 +1,3 @@ +$FF followed by several 0's + +Meaningless sequence of bytes, most likely caused by ROM not being full to the last byte. Not copyrightable. diff --git a/tools/build_segment.cc b/tools/build_segment.cc index 422819ef..d160f055 100644 --- a/tools/build_segment.cc +++ b/tools/build_segment.cc @@ -88,6 +88,7 @@ public: bool ignore; bool floating; + bool high; std::vector content; std::string label; @@ -109,6 +110,7 @@ public: void addToProblem(SourceFile *routine); void fillGap(DualStream &logOutput, int gapAddress, const std::list &routines); + void placeHighRoutines(DualStream &logOutput); void performObviousSteps(DualStream &logOutput); void removeUselessGaps(DualStream &logOutput); void sortFloatingRoutinesBySize(); @@ -416,9 +418,22 @@ void prepareBinningProblem() { std::string spacing; spacing.resize(GLOBAL_maxFileNameLen + 4 - sourceFile.fileName.length(), ' '); - std::string floating = sourceFile.floating ? "(floating) " : " "; + std::string floating_high; - logOutput << "file: " << floating << sourceFile.fileName << spacing << "size: " << std::to_string(sourceFile.codeLength) << "\n"; + if (sourceFile.high) + { + floating_high = "(floating, high) "; + } + else if (sourceFile.floating) + { + floating_high = "(floating) "; + } + else + { + floating_high = " "; + } + + logOutput << "file: " << floating_high << sourceFile.fileName << spacing << "size: " << std::to_string(sourceFile.codeLength) << "\n"; } // Create the binning problem @@ -569,6 +584,7 @@ SourceFile::SourceFile(const std::string &fileName, const std::string &dirName) dirName(dirName), ignore(false), floating(false), + high(false), startAddr(-1), codeLength(-1), testAddrStart(-1), @@ -686,12 +702,17 @@ bool SourceFile::preprocessLine(const std::string &line) if (iter->compare("#IGNORE") == 0) { - ignore = true; + ignore = true; } else if (iter->compare("#TAKE-FLOAT") == 0) { floating = true; } + else if (iter->compare("#TAKE-HIGH") == 0) + { + floating = true; + high = true; + } else if (iter->compare("#TAKE-OFFSET") == 0) { if (++iter == tokens.end()) ERROR("syntax error, missing parameter for '#TAKE-OFFSET'"); @@ -844,10 +865,71 @@ void BinningProblem::fillGap(DualStream &logOutput, int gapAddress, const std::l gaps.erase(gapAddress); } +void BinningProblem::placeHighRoutines(DualStream &logOutput) +{ + // Place routines which has to be stored in the high ROM area + // It is expected there will be very few of them, so no complicated algorithms here + + std::string spacing; + + while (!floatingRoutines.empty()) + { + // Try to find any high routine + + auto iterRoutine = floatingRoutines.begin(); + while (iterRoutine != floatingRoutines.end() && !(*iterRoutine)->high) iterRoutine++; + + if (iterRoutine == floatingRoutines.end()) break; + + // Now we need to find a space to put it - just take the largest gap available, + // which is located in the high ROM area + + int routineSize = (*iterRoutine)->codeLength; + int gapAddress = -1; + + for (auto &gap : gaps) + { + if (gap.second < routineSize || gap.first < 0xE000) continue; + + if (gap.second == routineSize) + { + gapAddress = gap.first; + break; + } + + if (gapAddress < 0 || gap.second > gaps[gapAddress]) + { + gapAddress = gap.first; + } + } + + if (gapAddress < 0) ERROR("no suitable space for a high routine"); + + // Place routine in the gap found + + gaps[gapAddress] -= routineSize; + + int targetAddr = gapAddress + gaps[gapAddress]; + fixedRoutines[targetAddr] = *iterRoutine; + statFree -= routineSize; + + logOutput << "reducing gap $" << std::hex << gapAddress << std::dec << + " to size " << gaps[gapAddress] << "\n"; + + spacing.resize(GLOBAL_maxFileNameLen + 4 - (*iterRoutine)->fileName.length(), ' '); + logOutput << " $" << std::hex << targetAddr << std::dec << ": " << + (*iterRoutine)->fileName << spacing << "size: " << + (*iterRoutine)->codeLength << "\n"; + + floatingRoutines.erase(iterRoutine); + if (gaps[gapAddress] == 0) gaps.erase(gapAddress); + } +} + void BinningProblem::performObviousSteps(DualStream &logOutput) { // Get the size of the biggest routine; if there is just one gap which - // can handle it - put the roputine exactly there + // can handle it - put the routine exactly there std::string spacing; @@ -954,6 +1036,10 @@ void Solver::run() problem.sortFloatingRoutinesBySize(); + // Place routines which should be stored in high-ROM + + problem.placeHighRoutines(logOutput); + // Run the solver until all is done while (!problem.gaps.empty() && !problem.floatingRoutines.empty()) diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc new file mode 100644 index 00000000..790aaa8a --- /dev/null +++ b/tools/generate_strings.cc @@ -0,0 +1,1845 @@ +// +// Utility to generate compressed messages and BASIC tokens +// + +#include "common.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +// +// Command line settings +// + +std::string CMD_outFile = "out.s"; +std::string CMD_cnfFile = ""; + +// +// Type definition for text/tokens to generate +// + +typedef struct StringEntry +{ + bool enabledSTD; // whether enabled for basic build + bool enabledM65; // whether enabled for Mega65 build + bool enabledX16; // whether enabled for Commander X16 build + std::string alias; // alias, for the assembler + std::string string; // string/token + uint8_t abbrevLen = 0; // length of token abbreviation +} StringEntry; + +enum class ListType +{ + KEYWORDS, + STRINGS_BASIC, + DICTIONARY // for internal use only +}; + +typedef struct StringEntryList +{ + ListType type; + std::string name; + std::vector list; +} StringEntryList; + +typedef std::vector StringEncoded; +typedef std::vector StringEncodedList; + +// http://www.classic-games.com/commodore64/cbmtoken.html +// https://www.c64-wiki.com/wiki/BASIC_token + +// BASIC keywords - V2 dialect + +/* + The URLs here provide examples of other BASIC dialects that include the specified commands + or keywords. + All except VERIFY are known with certainty to be part of other BASIC dialects, and thus + cannot be subject to copyright infringement when implemented on a C64. + + The VERIFY Command however appears in other programming languages, and as a single word, + is the obvious complement to LOAD and SAVE when considering the following storage functions: + + 1. Load a file from storage into memory. + 2. Save a file from memory to storage. + 3. Verify that a file has been correctly written from memory to storage. + + Note that verify is the key verb in the behaviour of this function. Therefore it is the + obvious choice for the name for such a function, taking into account the convention of + LOAD and SAVE. Indeed, that this is so is highlighted by the fact that it was used in the + C64 ROM. Therefore there is no exercise of creativity here, and a reasonable person would + likely select this name independently. Also, single words cannot be copyright. + + Further, the list is a list of facts, and thus not copyrightable. + + We sourced the list from a public source, https://www.c64-wiki.com/wiki/BASIC, which has + been public on the internet for a long time, as have many other similar sources. + That website offers the page under the GFDL license, and we can therefore take the list + under those license terms if we wish, should the need arise. + + Note that in providing these justifications above, we do not in any way acknowledge that + without these conditions that the BASIC keyword list could be copyright, but provide this + information as a further layer of defence against any claims that it could somehow + infringe on the copyrights of the C64/C65/C128 etc ROMs. +*/ + +const StringEntryList GLOBAL_Keywords_V2 = { ListType::KEYWORDS, "keywords_V2", +{ + // STD M65 X16 + { true, true, true, "KV2_80", "END", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_81", "FOR", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_82", "NEXT", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_83", "DATA", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_84", "INPUT#", 2 }, // https://www.atariarchives.org/creativeatari/Using_Disks_With_Atari_Basic.php + { true, true, true, "KV2_85", "INPUT", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_86", "DIM", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_87", "READ", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_88", "LET", 2 }, // https://en.wikipedia.org/wiki/Atari_BASIC + { true, true, true, "KV2_89", "GOTO", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_8A", "RUN", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_8B", "IF", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_8C", "RESTORE", 3 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_8D", "GOSUB", 3 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_8E", "RETURN", 3 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_8F", "REM", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_90", "STOP", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_91", "ON", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_92", "WAIT", 2 }, // http://www.picaxe.com/BASIC-Commands/Time-Delays/wait/ + { true, true, true, "KV2_93", "LOAD", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_94", "SAVE", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_95", "VERIFY", 2 }, // https://en.wikipedia.org/wiki/Sinclair_BASIC + { true, true, true, "KV2_96", "DEF", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_97", "POKE", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_98", "PRINT#", 2 }, // https://www.atariarchives.org/creativeatari/Using_Disks_With_Atari_Basic.php + { true, true, true, "KV2_99", "PRINT", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_9A", "CONT", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_9B", "LIST", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_9C", "CLR", 2 }, // Apple I Replica Creation: Back to the Garage, p125 + { true, true, true, "KV2_9D", "CMD", 2 }, // https://en.wikipedia.org/wiki/List_of_DOS_commands + { true, true, true, "KV2_9E", "SYS", 2 }, // https://www.lifewire.com/dos-commands-4070427 + { true, true, true, "KV2_9F", "OPEN", 2 }, // https://www.atariarchives.org/creativeatari/Using_Disks_With_Atari_Basic.php + // STD M65 X16 + { true, true, true, "KV2_A0", "CLOSE", 3 }, // https://www.atariarchives.org/creativeatari/Using_Disks_With_Atari_Basic.php + { true, true, true, "KV2_A1", "GET", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_A2", "NEW", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_A3", "TAB(", 2 }, // http://www.antonis.de/qbebooks/gwbasman/tab.html + { true, true, true, "KV2_A4", "TO", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_A5", "FN", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_A6", "SPC(", 2 }, // http://www.antonis.de/qbebooks/gwbasman/spc.html + { true, true, true, "KV2_A7", "THEN", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_A8", "NOT", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_A9", "STEP", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_AA", "+", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_AB", "-", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_AC", "*", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_AD", "/", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_AE", "^", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_AF", "AND", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B0", "OR", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B1", ">", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B2", "=", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B3", "<", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B4", "SGN", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B5", "INT", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B6", "ABS", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B7", "USR", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_B8", "FRE", 2 }, // http://www.antonis.de/qbebooks/gwbasman/fre.html + { true, true, true, "KV2_B9", "POS", 0 }, // http://www.antonis.de/qbebooks/gwbasman/pos.html + { true, true, true, "KV2_BA", "SQR", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_BB", "RND", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_BC", "LOG", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_BD", "EXP", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_BE", "COS", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_BF", "SIN", 2 }, // https://www.landsnail.com/a2ref.htm + // STD M65 X16 + { true, true, true, "KV2_C0", "TAN", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C1", "ATN", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C2", "PEEK", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C3", "LEN", 0 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C4", "STR$", 3 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C5", "VAL", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C6", "ASC", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C7", "CHR$", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C8", "LEFT$", 3 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_C9", "RIGHT$", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_CA", "MID$", 2 }, // https://www.landsnail.com/a2ref.htm + { true, true, true, "KV2_CB", "GO", 0 }, // https://en.wikipedia.org/wiki/Goto +} }; + +// extended BASIC keywords - reserved for generic (hardware independent) BASIC commands + +const StringEntryList GLOBAL_Keywords_CC = { ListType::KEYWORDS, "keywords_CC", +{ + // STD M65 X16 + { true, true, true, "KCC_01", "MERGE", }, // OpenROMs specific, not present in CBM BASIC dialects + { true, true, true, "KCC_02", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html + { true, true, true, "KCC_03", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html + { true, true, true, "KCC_04", "BVERIFY", }, +} }; + +// extended BASIC keywords - reserved for BASIC commands likely making sense on most C64-compatible machines + +const StringEntryList GLOBAL_Keywords_CD = { ListType::KEYWORDS, "keywords_CD", +{ + // STD M65 X16 + { true, true, true, "KCD_01", "SLOW", }, // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant + { true, true, true, "KCD_02", "FAST", }, // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant +} }; + +// extended BASIC keywords - reserved for board-specific BASIC commands + +const StringEntryList GLOBAL_Keywords_CE = { ListType::KEYWORDS, "keywords_CE", +{ + // STD M65 X16 + { false, false, false, "KCE_01", "TESTCMD", }, +} }; + +const StringEntryList GLOBAL_Keywords_CF = { ListType::KEYWORDS, "keywords_CF", +{ + // STD M65 X16 + { false, false, false, "KCF_01", "TESTCMD", }, +} }; + +// extended BASIC keywords - reserved for generic (hardware independent) BASIC functions + +const StringEntryList GLOBAL_Keywords_D0 = { ListType::KEYWORDS, "keywords_D0", +{ + // STD M65 X16 + { false, false, false, "KD0_01", "TESTFUN", }, +} }; + +// extended BASIC keywords - reserved for BASIC functions likely making sense on most C64-compatible machines + +const StringEntryList GLOBAL_Keywords_D1 = { ListType::KEYWORDS, "keywords_D1", +{ + // STD M65 X16 + { false, false, false, "KD1_01", "TESTFUN", }, +} }; + +// extended BASIC keywords - reserved for board-specific BASIC functions + +const StringEntryList GLOBAL_Keywords_D2 = { ListType::KEYWORDS, "keywords_D2", +{ + // STD M65 X16 + { false, false, false, "KD2_01", "TESTFUN", }, +} }; + +const StringEntryList GLOBAL_Keywords_D3 = { ListType::KEYWORDS, "keywords_D3", +{ + // STD M65 X16 + { false, false, false, "KD3_01", "TESTFUN", }, +} }; + + +// BASIC errors - all dialects + +/* + These error messages are generally so well known, that it seems silly to have to even point out that they are + so widely used and known, if not completely genericised. + The most of them are inherited from the MICROSOFT BASIC on which the C64's BASIC is based, so for those, there + cannot even be any claim to copyright over them in any exclusive way. + + However, copyright of such short phrases that express ideas in short form cannot be copyrighted: + https://fairuse.stanford.edu/2003/09/09/copyright_protection_for_short/ + */ + +const StringEntryList GLOBAL_Errors = { ListType::STRINGS_BASIC, "errors", +{ + // STD M65 X16 --- error strings compatible with CBM BASIC V2 + { true, true, true, "EV2_01", "TOO MANY FILES" }, + { true, true, true, "EV2_02", "FILE OPEN" }, + { true, true, true, "EV2_03", "FILE NOT OPEN" }, + { true, true, true, "EV2_04", "FILE NOT FOUND" }, + { true, true, true, "EV2_05", "DEVICE NOT PRESENT" }, + { true, true, true, "EV2_06", "NOT INPUT FILE" }, + { true, true, true, "EV2_07", "NOT OUTPUT FILE" }, + { true, true, true, "EV2_08", "MISSING FILENAME" }, + { true, true, true, "EV2_09", "ILLEGAL DEVICE NUMBER" }, + { true, true, true, "EV2_0A", "NEXT WITHOUT FOR" }, + { true, true, true, "EV2_0B", "SYNTAX" }, + { true, true, true, "EV2_0C", "RETURN WITHOUT GOSUB" }, + { true, true, true, "EV2_0D", "OUT OF DATA" }, + { true, true, true, "EV2_0E", "ILLEGAL QUANTITY" }, + { true, true, true, "EV2_0F", "OVERFLOW" }, + { true, true, true, "EV2_10", "OUT OF MEMORY" }, + { true, true, true, "EV2_11", "UNDEF\'D STATEMENT" }, + { true, true, true, "EV2_12", "BAD SUBSCRIPT" }, + { true, true, true, "EV2_13", "REDIM\'D ARRAY" }, + { true, true, true, "EV2_14", "DIVISION BY ZERO" }, + { true, true, true, "EV2_15", "ILLEGAL DIRECT" }, + { true, true, true, "EV2_16", "TYPE MISMATCH" }, + { true, true, true, "EV2_17", "STRING TOO LONG" }, + { true, true, true, "EV2_18", "FILE DATA" }, + { true, true, true, "EV2_19", "FORMULA TOO COMPLEX" }, + { true, true, true, "EV2_1A", "CAN\'T CONTINUE" }, + { true, true, true, "EV2_1B", "UNDEF\'D FUNCTION" }, + { true, true, true, "EV2_1C", "VERIFY" }, + { true, true, true, "EV2_1D", "LOAD" }, + { true, true, true, "EV2_1E", "BREAK" }, + // STD M65 X16 --- error strings compatible with CBM BASIC V7 + { false, false, false, "EV7_1F", "CAN'T RESUME" }, // not used for now + { false, false, false, "EV7_20", "LOOP NOT FOUND" }, // not used for now + { false, false, false, "EV7_21", "LOOP WITHOUT DO" }, // not used for now + { true, true, true, "EV7_22", "DIRECT MODE ONLY" }, + { false, false, false, "EV7_23", "NO GRAPHICS AREA" }, // not used for now + { false, false, false, "EV7_24", "BAD DISK" }, // not used for now + { false, false, false, "EV7_25", "BEND NOT FOUND" }, // not used for now + { false, false, false, "EV7_26", "LINE NUMBER TOO LARGE" }, // not used for now + { false, false, false, "EV7_27", "UNRESOLVED REFERENCE" }, // not used for now + { true, true, true, "EV7_28", "NOT IMPLEMENTED" }, // this message actually differs from the CBM one + { false, false, false, "EV7_29", "FILE READ" }, // not used for now + // STD M65 X16 --- error strings specific to OpenROMs, not present in CBM BASIC dialects + { true, true, true, "EOR_2A", "MEMORY CORRUPT" }, +} }; + +// BASIC errors - miscelaneous strings + +const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", +{ + // STD M65 X16 --- misc strings as on CBM machines + { true, true, true, "STR_RET_QM", "\r?" }, + { true, true, true, "STR_BYTES", " BASIC BYTES FREE" }, // https://github.com/stefanhaustein/expressionparser + { 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, "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, "STR_IN", " IN " }, + // STD M65 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs + { true, true, true, "STR_BRK_AT", "\rBRK AT $" }, + // Note: depending on configuration, additional strings will be added here +} }; + + +/* NOTE: below are the BASIC V7/V10 keywords, see: + - https://sites.google.com/site/h2obsession/CBM/basic/tokens + - http://www.zimmers.net/anonftp/pub/cbm/programming/cbm-basic-tokens.txt + + "RGR" // $CC + "RCLR" // $CD + + "JOY" // $CF // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "RDOT" // $D0 + "DEC" // $D1 // Amos Professional Manual, Command Index + "HEX$" // $D2 // http://www.antonis.de/qbebooks/gwbasman/hexs.html + "ERR$" // $D3 // Amos Professional Manual, Command Index + "INSTR" // $D4 // Amos Professional Manual, Command Index + "ELSE" // $D5 // Amos Professional Manual, Command Index + "RESUME" // $D6 // Amos Professional Manual, Command Index + "TRAP" // $D7 // Amos Professional Manual, Command Index + "TRON" // $D8 // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "TROFF" // $D9 // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "SOUND" // $DA // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "VOL" // $DB + "AUTO" // $DC // http://www.antonis.de/qbebooks/gwbasman/auto.html + "PUDEF" // $DD + "GRAPHIC" // $DE + "PAINT" // $DF // Amos Professional Manual, Command Index + "CHAR" // $E0 // https://www.c64-wiki.com/wiki/Screen_Graphics_64 + "BOX" // $E1 // Amos Professional Manual, Command Index + "CIRCLE" // $E2 // https://en.wikipedia.org/wiki/Sinclair_BASIC + "PASTE" // $E3 // Amos Professional Manual, Command Index + "CUT" // $E4 + "LINE" // $E5 // https://en.wikipedia.org/wiki/Sinclair_BASIC + "LOCATE" // $E6 // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "COLOR" // $E7 + "SCNCLR" // $E8 + "SCALE" // $E9 // https://www.c64-wiki.com/wiki/Super_Expander_64 + "HELP" // $EA // http://www.classic-games.com/commodore64/cbmtoken.html, Speech Basic 2.7 + "DO" // $EB // Amos Professional Manual, Command Index + "LOOP" // $EC // Amos Professional Manual, Command Index + "EXIT" // $ED // Amos Professional Manual, Command Index + "DIR" // $EE // Amos Professional Manual, Command Index + "DSAVE" // $EF // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "DLOAD" // $F0 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "HEADER" // $F1 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "SCRATCH" // $F2 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "COLLECT" // $F3 + "COPY" // $F4 // https://en.wikipedia.org/wiki/Sinclair_BASIC + "RENAME" // $F5 // Amos Professional Manual, Command Index + "BACKUP" // $F6 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "DELETE" // $F7 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "RENUMBER" // $F8 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "KEY" // $F9 // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "MONITOR" // $FA // Amos Professional Manual, Command Index + "USING" // $FB // http://www.antonis.de/qbebooks/gwbasman/printusing.html + "UNTIL" // $FC // Amos Professional Manual, Command Index + "WHILE" // $FD // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + + "POT" // $CE $02 + "BUMP" // $CE $03 + "PEN" // $CE $04 // https://www.qsl.net/hb9xch/computer/amstrad/locomotivebasic.html + "RSPPOS" // $CE $05 // https://www.c64-wiki.com/wiki/Super_Expander_64 + "RSPRITE" // $CE $06 + "RSPCOLOR" // $CE $07 + "XOR" // $CE $08 + "RWINDOW" // $CE $09 + "POINTER" // $CE $0A + + "BANK" // $FE $02 // Amos Professional Manual, Command Index + "FILTER" // $FE $03 // https://www.c64-wiki.com/wiki/Super_Expander_64 + "PLAY" // $FE $04 // Amos Professional Manual, Command Index + "TEMPO" // $FE $05 // Amos Professional Manual, Command Index + "MOVSPR" // $FE $06 + "SPRITE" // $FE $07 // Amos Professional Manual, Command Index + "SPRCOLOR" // $FE $08 + "RREG" // $FE $09 + "ENVELOPE" // $FE $0A + "SLEEP" // $FE $0B + "CATALOG" // $FE $0C // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "DOPEN" // $FE $0D + "APPEND" // $FE $0E // Amos Professional Manual, Command Index + "DCLOSE" // $FE $0F + "BSAVE" // $FE $10 // http://www.antonis.de/qbebooks/gwbasman/bsave.html + "BLOAD" // $FE $11 // http://www.antonis.de/qbebooks/gwbasman/bload.html + "RECORD" // $FE $12 + "CONCAT" // $FE $13 + "DVERIFY" // $FE $14 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "DCLEAR" // $FE $15 + "SPRSAV" // $FE $16 // https://www.c64-wiki.com/wiki/Super_Expander_64 + "COLLISION" // $FE $17 + "BEGIN" // $FE $18 + "BEND" // $FE $19 + "WINDOW" // $FE $1A // http://www.antonis.de/qbebooks/gwbasman/window.html + "BOOT" // $FE $1B + "WIDTH" // $FE $1C // http://www.antonis.de/qbebooks/gwbasman/width.html + "SPRDEF" // $FE $1D // https://www.c64-wiki.com/wiki/Super_Expander_64 + "QUIT" // $FE $1E // http://www.classic-games.com/commodore64/cbmtoken.html, Speech Basic 2.7 + + "STASH" // $FE $1F - v7 + "FETCH" // $FE $21 - v7 + "SWAP" // $FE $23 - v7 // http://www.antonis.de/qbebooks/gwbasman/swap.html + + "DMA" // $FE $17/$21/$23 - v10 + + "OFF" // $FE $24 // http://www.classic-games.com/commodore64/cbmtoken.html, Speech Basic 2.7 + "FAST" // $FE $25 // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant + "SLOW" // $FE $26 // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant + "TYPE" // $FE $27 + "BVERIFY" // $FE $28 + "DIRECTORY" // $FE $29 // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "ERASE" // $FE $2A // https://en.wikipedia.org/wiki/Sinclair_BASIC + "FIND" // $FE $2B // http://www.classic-games.com/commodore64/cbmtoken.html, AtBasic (@Basic) + "CHANGE" // $FE $2C + "SET" // $FE $2D + "SCREEN" // $FE $2E // http://www.antonis.de/qbebooks/gwbasman/screens.html + "POLYGON" // $FE $2F // Amos Professional Manual, Command Index + "ELLIPSE" // $FE $30 // Amos Professional Manual, Command Index + "VIEWPORT" // $FE $31 + "GCOPY" // $FE $32 + "PEN" // $FE $33 // Amos Professional Manual, Command Index + "PALETTE" // $FE $34 // Amos Professional Manual, Command Index + "DMODE" // $FE $35 + "DPAT" // $FE $36 + "PIC" // $FE $37 + "GENLOCK" // $FE $38 + "FOREGROUND" // $FE $39 + + "BACKGROUND" // $FE $3B + "BORDER" // $FE $3C // https://en.wikipedia.org/wiki/Sinclair_BASIC + "HIGHLIGHT" // $FE $3D +*/ + +std::map GLOBAL_ConfigOptions; + +// +// Work class definitions +// + +class DictEncoder +{ +public: + + void addString(const std::string &inString, StringEncoded *outPtr); + + void process(StringEntryList &outDictionary); + +private: + + bool optimizeSplit(); + bool optimizeJoin(); + void optimizeOrder(); + + void cleanupDictionary(); + + void extractWords(std::vector &candidateList); + int32_t evaluateCandidate(std::string &candidate); + + std::vector encodings; + std::vector dictionary; +}; + +class DataSet +{ +public: + + void addStrings(const StringEntryList &stringList); + + const std::string &getOutput(); + +private: + + void process(); + + void generateConfigDepStrings(); + void validateLists(); + void calculateFrequencies(); + void encodeStringsDict(); + void encodeStringsFreq(); + + void encodeByFreq(const std::string &plain, StringEncoded &encoded) const; + + void prepareOutput(); + void prepareOutput_1n_3n(std::ostringstream &stream); + void prepareOutput_labels(std::ostringstream &stream, + const StringEntryList &stringEntryList, + const StringEncodedList &stringEncodedList); + void prepareOutput_packed(std::ostringstream &stream, + const StringEntryList &stringEntryList, + const StringEncodedList &stringEncodedList); + + void putCharEncoding(std::ostringstream &stream, uint8_t idx, char character, bool is3n); + + bool isCompressionLvl2(const StringEntryList &list) const; + + virtual bool isRelevant(const StringEntry &entry) const = 0; + virtual std::string layoutName() const = 0; + + std::vector stringEntryLists; + std::vector stringEncodedLists; + + std::vector as1n; // list of bytes to be encoded as 1 nibble + std::vector as3n; // list of bytes to be encoded as 3 nibbles + + uint8_t tk__packed_as_3n = 0; + uint8_t tk__max_keyword_len = 0; + + size_t maxAliasLen = 0; + std::string outFileContent; +}; + +class DataSetSTD : public DataSet +{ + bool isRelevant(const StringEntry &entry) const { return entry.enabledSTD; } + std::string layoutName() const { return "STD"; } +}; + +class DataSetM65 : public DataSet +{ + bool isRelevant(const StringEntry &entry) const { return entry.enabledM65; } + std::string layoutName() const { return "M65"; } +}; + +class DataSetX16 : public DataSet +{ + bool isRelevant(const StringEntry &entry) const { return entry.enabledX16; } + std::string layoutName() const { return "X16"; } +}; + +// +// Work class implementation +// + +void DictEncoder::addString(const std::string &inString, StringEncoded *outPtr) +{ + // Store the pointer to encoding + + encodings.push_back(outPtr); + + // Check if string is already present in the dictionary + + auto pos = std::find(dictionary.begin(), dictionary.end(), inString); + + // Create initial encoding + + if (pos != dictionary.end()) + { + encodings.back()->push_back(pos - dictionary.begin()); + } + else + { + if (dictionary.size() > 255) + { + ERROR("max 255 strings allowed for dictionary compression"); + } + + dictionary.push_back(inString); + encodings.back()->push_back(dictionary.size() - 1); + } +} + + +void DictEncoder::extractWords(std::vector &candidateList) +{ + for (const auto &dictionaryEntry : dictionary) + { + // Split the dictionary entry into words + + std::istringstream entryStream(dictionaryEntry); + while (entryStream) + { + std::string word_1; + entryStream >> word_1; + + if (word_1.empty()) continue; + + // Create possible variants with spaces + + std::string word_2 = " " + word_1; + std::string word_3 = word_1 + " "; + std::string word_4 = word_2 + " "; + + // If necessary, add the word to candidate list + + auto addToList = [&dictionaryEntry, &candidateList](std::string &word) + { + // Before dding, make sure the word variant exists in the string, + // is not already on the list, and is long enough it makes sense to try + + if (word.size() < 1) return; + if (dictionaryEntry.find(word) == std::string::npos) return; + if (std::find(candidateList.begin(), candidateList.end(), word) != candidateList.end()) return; + + candidateList.push_back(word); + }; + + addToList(word_1); + addToList(word_2); + addToList(word_3); + addToList(word_4); + } + } +} + +int32_t DictEncoder::evaluateCandidate(std::string &candidate) +{ + // XXX it looks like this is not 100% right - debug the algorithm if dictionary compression is reintroduced + + // Build the score - find how much bytes can be spared by extracting this particular candidate + // Limited size of the dictionary is taken into consideration + + int32_t score = -(candidate.size() + 1); + uint32_t targetSize = dictionary.size() + 1; + + // First check for situation when the candidate equals the currently existing dictionary entry + + for (const auto &dictionaryEntry : dictionary) + { + if (dictionaryEntry == candidate) + { + // Candidate equals the string + + score += candidate.size() + 1; + targetSize--; + continue; + } + } + + // Now check the remaining cases + + for (const auto &dictionaryEntry : dictionary) + { + if (dictionaryEntry == candidate) continue; // already handled + + // Find all the occurences of the candidate in the current string + + std::vector occurences; + for (auto iter = dictionaryEntry.begin(); iter < (dictionaryEntry.end() - candidate.size() + 1); iter++) + { + if (candidate != std::string(iter, iter + candidate.size())) continue; + + occurences.push_back(iter - dictionaryEntry.begin()); + iter += candidate.size() - 1; // to make sure we have no occurence overlapping + } + + if (occurences.empty()) continue; + + // Now summarize what we are going to gain when doing replacement + + if (occurences[0] != 0) + { + // For the substring before the first occurence we need to create a separate entry + // in the dictionary - unless it is already there, it brings some additional cost + + std::string otherStr = std::string(dictionaryEntry.begin(), dictionaryEntry.end() + occurences[0]); + + if (std::find(dictionary.begin(), dictionary.end(), otherStr) != dictionary.end()) + { + // This extra string is already in the dictionary - that gives extra saving + score += otherStr.size() - 1; + } + else + { + // This extra string is not in the dictionary, it has to be added + score -= 2; + targetSize++; + } + } + + for (auto iter = occurences.begin(); iter < occurences.end(); iter++) + { + // With a replacement, we should gain some bytes + score += candidate.size() - 1; + + // If the occurence ends with the last byte of dictionary string - nothing more to do + if (*iter + candidate.size() == dictionaryEntry.size()) break; + + // If next occurence starts immediately after this one - next iteration + if (iter + 1 != occurences.end() && (*(iter + 1) - *iter) == (uint8_t) candidate.size()) continue; + + // For the substring between this occurence and the next one (or the end of the string) + // we need to create a separate entry in the dictionary - unless it is already there, + // it brings some additional cost + + std::string otherStr; + if (iter + 1 == occurences.end()) + { + otherStr = std::string(dictionaryEntry.begin() + *iter + candidate.size(), + dictionaryEntry.end()); + } + else + { + otherStr = std::string(dictionaryEntry.begin() + *iter + candidate.size(), + dictionaryEntry.begin() + *(iter + 1)); + } + + if (std::find(dictionary.begin(), dictionary.end(), otherStr) != dictionary.end()) + { + // This extra string is already in the dictionary - that gives extra saving + score += otherStr.size() - 1; + } + else + { + // This extra string is not in the dictionary, it has to be added + score -= 2; + targetSize++; + } + } + + // We crossed the maximum number of strings (leave one free for the work buffer), + // do not consider this candidate + + if (targetSize > 254) return -1; + } + + return score; +} + +void DictEncoder::cleanupDictionary() +{ + // Get rid of dictionary entries which are not needed anymore + + bool isClean = false; + + while (!isClean) + { + isClean = true; + + for (auto iter = dictionary.begin(); iter < dictionary.end(); iter++) + { + if (!iter->empty()) continue; + + // Found an empty string in the dictionary - remove it and adapt encoding + + isClean = false; + uint8_t obsoleteStrIdx = iter - dictionary.begin(); + + dictionary.erase(iter); + + for (auto &encoding : encodings) for (auto &byte : *encoding) + { + if (byte >= obsoleteStrIdx) byte--; + } + + break; + } + } +} + +bool DictEncoder::optimizeSplit() +{ + // XXX - The code here is not the best one - redesign and algorithm improvements + // (like - consider optimizing as a game and apply alpha-beta scheme to select the best + // candidate, incorporate frequency encoding into candidate evaluation) could result in + // a slightly better compression. But currently we have very few strings, and the dictionary + // compression is disabled by default - so right now this is not worth the effort. + + if (dictionary.size() >= 255) return false; // up to 255 entries in the dictionary are possible + + // First select words, which can potentially be extracted to new substrings + + std::vector candidateList; + extractWords(candidateList); + + // XXX possible future improvement: find a couple of largest common substrings and add them as candidates too + + // Now find the best word to be extracted + + auto bestCandidate = candidateList.end(); + int32_t bestCandidateScore = 0; + + for (auto iter = candidateList.begin(); iter < candidateList.end(); iter++) + { + int32_t candidateScore = evaluateCandidate(*iter); + + if (candidateScore > bestCandidateScore) + { + bestCandidate = iter; + bestCandidateScore = candidateScore; + } + } + + // Only allow for replacements that brings some size benefit + + if (bestCandidateScore < 1) return false; + + // Extract the best candidate to a separate string + + // First add our selected candidate to the dictionary and replace all strings which are equal to it + + auto &selectedStr = *bestCandidate; + uint8_t selectedStrIdx = dictionary.size(); + + dictionary.push_back(selectedStr); + + for (auto iter = dictionary.begin(); iter < dictionary.end(); iter++) + { + uint8_t currentStrIdx = iter - dictionary.begin(); + + if (*iter != selectedStr || selectedStrIdx == currentStrIdx) continue; + + // Replace the current string with the new one + + for (auto &encoding : encodings) for (auto &byte : *encoding) + { + if (byte == currentStrIdx) byte = selectedStrIdx; + } + + // Mark obsolete dictionary entry as free for removal + + iter->clear(); + } + + cleanupDictionary(); + + // Now handle normal cases, when the string needs to be split + // XXX - this is not time-effective, optimize this in the future + + bool optimizeAgain = true; + bool nexIteration = true; + while (nexIteration) + { + nexIteration = false; + + for (auto iter = dictionary.begin(); iter < dictionary.end(); iter++) + { + auto ¤tStr = *iter; + uint8_t currentStrIdx = iter - dictionary.begin(); + auto selectedStrIter = std::find(dictionary.begin(), dictionary.end(), selectedStr); + selectedStrIdx = selectedStrIter - dictionary.begin(); + + if (currentStrIdx == selectedStrIdx) continue; + + // Check if the current string contains the selected string + + auto pos = currentStr.find(selectedStr); + if (pos == std::string::npos) continue; + + nexIteration = true; + optimizeAgain = true; + + // Prepare replacement sequence for 'selectedStrIdx' + + std::vector replacement; + + if (pos == 0) + { + // The current dictionary string starts with our selected substring + + replacement.push_back(selectedStrIdx); + currentStr = currentStr.substr(selectedStr.size(), currentStr.size() - selectedStr.size()); + + if (!currentStr.empty()) + { + // Check if the remaining string is present somewhere else in the dictionary; if so, reuse it + + uint8_t pos2 = currentStrIdx; + for (auto iter2 = dictionary.begin(); iter2 < dictionary.end(); iter2++) + { + if (iter2 == iter) continue; + if (currentStr == *iter2) + { + dictionary[pos2].clear(); + pos2 = iter2 - dictionary.begin(); + break; + } + } + + replacement.push_back(pos2); + } + } + else + { + // The current dictionary string does not start with our selected substring + + std::string newStr = currentStr.substr(0, pos); + currentStr = currentStr.substr(pos, currentStr.size() - pos); + + // Check if the newStr is present somewhere else in the dictionary; if so, reuse it + + bool found = false; + uint8_t pos2 = 0; + for (auto iter2 = dictionary.begin(); iter2 < dictionary.end(); iter2++) + { + if (*iter2 == newStr) + { + found = true; + pos2 = iter2 - dictionary.begin(); + + break; + } + } + + if (found) + { + replacement.push_back(pos2); + } + else + { + dictionary.push_back(newStr); + replacement.push_back(dictionary.size() - 1); + } + + replacement.push_back(currentStrIdx); + } + + // Now replace all the occurences of 'selectedStrIdx' with a 'replacement' vector + + for (auto &encoding : encodings) + { + for (uint8_t idx = 0; idx < encoding->size(); idx++) + { + if ((*encoding)[idx] != currentStrIdx) continue; + + // Perform replacement + + encoding->erase(encoding->begin() + idx); + + for (const auto replacementIdx : replacement) + { + encoding->insert(encoding->begin() + idx, replacementIdx); + idx++; + } + + idx--; + } + } + + cleanupDictionary(); + } + } + + return optimizeAgain; +} + +bool DictEncoder::optimizeJoin() +{ + // Try to optimize by joining two substrings + + // XXX - possible future improvement + + return false; +} + +void DictEncoder::optimizeOrder() +{ + // XXX - it would be better to do this after the dictionary is compressed + + // Try to optimize order of strings in the dictionary for fastest display + // - put the shorter substrings first + // - for strings with roughly the same length put more frequently used first + + typedef struct Entry + { + uint32_t penalty; + std::string word; + } Entry; + + // Create copy of the dictionary with optimization info + + std::vector optimizedOrder; + for (auto iter = dictionary.begin(); iter < dictionary.end(); iter++) + { + const auto &dictionaryStr = *iter; + + uint8_t sizePenalty = dictionaryStr.size() / 3; + uint16_t freqPenalty = 65535; + + // Calculate penalty for low occurence frequency + + for (auto &encoding : encodings) + { + for (auto &byte : *encoding) + { + if (byte == (iter - dictionary.begin())) freqPenalty--; + } + } + + // Create new entry + + Entry newEntry; + newEntry.word = dictionaryStr; + newEntry.penalty = sizePenalty * 65536 + freqPenalty; + + optimizedOrder.push_back(newEntry); + } + + + // Determine ordering - sort from smallest penalty to largest + + std::sort(optimizedOrder.begin(), optimizedOrder.end(), + [](const Entry &e1, const Entry &e2) { return e1.penalty < e2.penalty; }); + + // Create helper table for reordering + + std::vector reorderTable; + + for (uint8_t idx1 = 0; idx1 < dictionary.size(); idx1++) + { + uint8_t idx2 = 0; + while (dictionary[idx1] != optimizedOrder[idx2].word) idx2++; + + reorderTable.push_back(idx2); + } + + // Perform the reordering + + for (auto &encoding : encodings) for (auto &byte : *encoding) + { + byte = reorderTable[byte]; + } + + for (uint8_t idx = 0; idx < dictionary.size(); idx++) dictionary[idx] = optimizedOrder[idx].word; +} + +void DictEncoder::process(StringEntryList &outDictionary) +{ + if (dictionary.empty()) return; + // Optimize as long as it brings any improvement + + while (optimizeSplit() || optimizeJoin()) ; + optimizeOrder(); + + // Export the dictionary to external format + + outDictionary.type = ListType::DICTIONARY; + outDictionary.name = "DICTIONARY"; + + for (const auto &dictionaryStr : dictionary) + { + StringEntry newEntry = { true, true, true, "", dictionaryStr }; + outDictionary.list.push_back(newEntry); + } + + // Adapt the encoding to external format (0 = end of string) + + for (auto &encoding : encodings) + { + for (auto &byte : *encoding) byte++; + encoding->push_back(0); + } +} + +bool DataSet::isCompressionLvl2(const StringEntryList &list) const +{ + return (GLOBAL_ConfigOptions["CONFIG_COMPRESSION_LVL_2"] && list.type == ListType::STRINGS_BASIC); +} + +void DataSet::addStrings(const StringEntryList &stringList) +{ + // Import the new list of strings + + stringEntryLists.push_back(stringList); + stringEncodedLists.emplace_back(); + + // Clear strings not relevant for the current configuration + + while (1) + { + if (isRelevant(stringEntryLists.back().list.back())) break; + + stringEntryLists.back().list.pop_back(); + if (stringEntryLists.back().list.empty()) + { + ERROR(std::string("no valid strings in layout '") + layoutName() + "', list'" + stringEntryLists.back().name + "'"); + } + } + + // Clear the output content - make sure it is not valid anymore + + outFileContent.clear(); +} + +void DataSet::process() +{ + std::cout << "Processing file '" << CMD_cnfFile << "', layout '" << layoutName() << "'" << std::endl; + + generateConfigDepStrings(); + validateLists(); + encodeStringsDict(); + calculateFrequencies(); + encodeStringsFreq(); + prepareOutput(); +} + +const std::string &DataSet::getOutput() +{ + if (outFileContent.empty()) + { + process(); + } + + return outFileContent; +} + +void DataSet::generateConfigDepStrings() +{ + // Generate string to show the build features + + std::string featureStr; + + // Tape support features + + if (GLOBAL_ConfigOptions["CONFIG_TAPE_NORMAL"] && GLOBAL_ConfigOptions["CONFIG_TAPE_TURBO"]) + { + featureStr = "TAPE LOAD NORMAL TURBO\r"; + } + else if (GLOBAL_ConfigOptions["CONFIG_TAPE_NORMAL"]) + { + featureStr = "TAPE LOAD NORMAL\r"; + } + else if (GLOBAL_ConfigOptions["CONFIG_TAPE_TURBO"]) + { + featureStr = "TAPE LOAD TURBO\r"; + } + + // IEC support features + + if (GLOBAL_ConfigOptions["CONFIG_IEC"]) + { + featureStr += "IEC"; + + bool extendedIEC = false; + + if (GLOBAL_ConfigOptions["CONFIG_IEC_BURST_CIA1"]) + { + featureStr += " BURST1"; + extendedIEC = true; + } + if (GLOBAL_ConfigOptions["CONFIG_IEC_BURST_CIA2"]) + { + featureStr += " BURST2"; + extendedIEC = true; + } + if (GLOBAL_ConfigOptions["CONFIG_IEC_BURST_MEGA65"]) + { + featureStr += " BURST"; + extendedIEC = true; + } + + if (GLOBAL_ConfigOptions["CONFIG_IEC_DOLPHINDOS"]) + { + featureStr += " DOLPHIN"; + extendedIEC = true; + } + + if (GLOBAL_ConfigOptions["CONFIG_IEC_JIFFYDOS"]) + { + featureStr += " JIFFY"; + extendedIEC = true; + } + + if (!extendedIEC) featureStr += " NORMAL"; + + featureStr += "\r"; + } + + // RS-232 support features + + if (GLOBAL_ConfigOptions["CONFIG_RS232_UP2400"]) featureStr += "UP2400\r"; + if (GLOBAL_ConfigOptions["CONFIG_RS232_UP9600"]) featureStr += "UP9600\r"; + + // Keyboard support features + + if (GLOBAL_ConfigOptions["CONFIG_KEYBOARD_C128"]) featureStr += "KBD 128\r"; + if (GLOBAL_ConfigOptions["CONFIG_KEYBOARD_C65"]) featureStr += "KBD 65\r"; + + // Add strings to appropriate list + + for (auto &stringEntryList : stringEntryLists) + { + if (stringEntryList.name != std::string("misc")) continue; + + // List found + + if (GLOBAL_ConfigOptions["CONFIG_SHOW_FEATURES"]) + { + StringEntry newEntry1 = { true, true, true, "STR_PAL", "PAL\r" }; + StringEntry newEntry2 = { true, true, true, "STR_NTSC", "NTSC\r" }; + StringEntry newEntry3 = { true, true, true, "STR_FEATURES", featureStr }; + + stringEntryList.list.push_back(newEntry1); + stringEntryList.list.push_back(newEntry2); + stringEntryList.list.push_back(newEntry3); + + break; + } + } +} + +void DataSet::validateLists() +{ + for (const auto &stringEntryList : stringEntryLists) + { + for (const auto &stringEntry : stringEntryList.list) + { + // Check for maximum allowed string length + if (stringEntry.string.length() > 255) ERROR("string cannot be longer than 255 characters"); + + // Check mor maximum keyword length + if (stringEntryList.type == ListType::KEYWORDS) + { + if (stringEntry.string.length() > 16) ERROR("keyword cannot be longer than 16 characters"); + tk__max_keyword_len = std::max(tk__max_keyword_len, (uint8_t) stringEntry.string.length()); + } + + // Update maximum alias length too + maxAliasLen = std::max(maxAliasLen, stringEntry.alias.length()); + + for (const auto &character : stringEntry.string) + { + if ((unsigned char) character >= 0x80) + { + ERROR(std::string("character above 0x80 in string '") + stringEntry.string + "'"); + } + } + } + } +} + +void DataSet::encodeStringsDict() +{ + DictEncoder dictEncoder; + + // Add strings for dictionary compresssion + + for (uint8_t idx = 0; idx < stringEntryLists.size(); idx++) + { + const auto &stringEntryList = stringEntryLists[idx]; + auto &stringEncodedList = stringEncodedLists[idx]; + + // Skip lists not to be encoded using the dictionary + if (!isCompressionLvl2(stringEntryList)) continue; + + stringEncodedList.resize(stringEntryList.list.size()); + for (uint8_t idxEntry = 0; idxEntry < stringEntryList.list.size(); idxEntry++) + { + dictEncoder.addString(stringEntryList.list[idxEntry].string, + &stringEncodedList[idxEntry]); + } + } + + // Perform the compression + + StringEntryList dictionary; + dictEncoder.process(dictionary); + + // Add new lists + + stringEntryLists.push_back(dictionary); + stringEncodedLists.emplace_back(); +} + +void DataSet::calculateFrequencies() +{ + as1n.clear(); + as3n.clear(); + + std::map freqMapGeneral; // general character frequency map + std::map freqMapKeywords; // frequency map for keywords + + // Calculate frequencies of characters in the strings + + for (const auto &stringEntryList : stringEntryLists) + { + // Skip lists encoded by the dictionary + if (isCompressionLvl2(stringEntryList)) continue; + + for (const auto &stringEntry : stringEntryList.list) + { + if (!isRelevant(stringEntry)) continue; + + for (const auto &character : stringEntry.string) + { + freqMapGeneral[character]++; + if (stringEntryList.type == ListType::KEYWORDS) freqMapKeywords[character]++; + } + } + } + + // Sort characters by frequency + + std::vector freqVector1; + + for (auto iter = freqMapGeneral.begin(); iter != freqMapGeneral.end(); ++iter) + { + freqVector1.push_back(iter->first); + } + + std::sort(freqVector1.begin(), freqVector1.end(), [&freqMapGeneral](char e1, char e2) + { return freqMapGeneral[e2] < freqMapGeneral[e1]; }); + + // Check if minimal amount of characters needed, below 15 is not supported by the 6502 side code + + if (freqVector1.size() < 15) ERROR(std::string("not enough distinct characters in layout '") + layoutName() + "', at least 15 needed"); + + // Extract 14 most frequent characters to be encoded as 1 nibble + + for (uint8_t idx = 0; idx < 14; idx++) + { + as1n.push_back(freqVector1[idx]); + } + + // Now sort them by frequency in keywords, in descending order - this will speed up the tokenizer a little + + std::sort(as1n.begin(), as1n.end(), [&freqMapKeywords](char e1, char e2) { return freqMapKeywords[e2] > freqMapKeywords[e1]; }); + + // Extract characters to be encoded as 3 nibbles, which actually exist in keywords + + std::vector freqVector2; + + tk__packed_as_3n = 0; + for (uint8_t idx = 14; idx < freqVector1.size(); idx++) + { + const auto &character = freqVector1[idx]; + + if (freqMapKeywords[character] > 0) + { + as3n.push_back(character); + tk__packed_as_3n++; + } + else + { + freqVector2.push_back(character); + } + } + tk__packed_as_3n = std::max(tk__packed_as_3n, (uint8_t) 1); + + // Again, sort them by frequency in keywords, in descending order - this will speed up the tokenizer a little + + std::sort(as3n.begin(), as3n.end(), [&freqMapKeywords](char e1, char e2) { return freqMapKeywords[e2] > freqMapKeywords[e1]; }); + + // Finally extract the remaining characters to be encoded as 3 nibbles + + for (const auto &character : freqVector2) + { + as3n.push_back(character); + } +} + +void DataSet::encodeByFreq(const std::string &plain, StringEncoded &encoded) const +{ + bool fullByte = true; + + auto push1n = [&](uint8_t val) // push 1 nibble - encoded character or 0xF mark + { + if (fullByte) + { + encoded.push_back(val); + fullByte = false; + } + else + { + encoded.back() += val * 0x10; + fullByte = true; + } + }; + + auto push2n = [&](uint8_t val) // push the remaining nibbles for 3-niobble encoded characters + { + if (fullByte) + { + encoded.push_back(val); + } + else + { + // Encode byte in a way to be easily decoded by 6502 + encoded.back() += (val / 0x10) * 0x10; + encoded.push_back(val % 0x10); + } + }; + + // Encode every single character by frequency, put them in the output vector + + for (const char &character : plain) + { + auto iterEncoding1 = std::find(as1n.begin(), as1n.end(), character); + if (iterEncoding1 != as1n.end()) + { + push1n(std::distance(as1n.begin(), iterEncoding1) + 1); + } + else + { + push1n(0x0F); + + auto iterEncoding3 = std::find(as3n.begin(), as3n.end(), character); + if (iterEncoding3 == as3n.end()) + { + ERROR("internal error in 'encodeByFreq'"); + } + push2n(std::distance(as3n.begin(), iterEncoding3) + 1); + } + } + + // Make sure the last byte of encoded stream is 0 + + if (encoded.size() == 0 || encoded.back() != 0) encoded.push_back(0); +} + +void DataSet::encodeStringsFreq() +{ + // Encode every relevant string from every list - by character frequency + + for (uint8_t idx = 0; idx < stringEntryLists.size(); idx++) + { + const auto &stringEntryList = stringEntryLists[idx]; + auto &stringEncodedList = stringEncodedLists[idx]; + + // Skip lists encoded by the dictionary + if (isCompressionLvl2(stringEntryList)) continue; + + // Perform frequency encoding of the list + + for (const auto &stringEntry : stringEntryList.list) + { + stringEncodedList.emplace_back(); + auto &stringEncoded = stringEncodedList.back(); + + if (isRelevant(stringEntry)) + { + encodeByFreq(stringEntry.string, stringEncoded); + } + } + } +} + +void DataSet::putCharEncoding(std::ostringstream &stream, uint8_t idx, char character, bool is3n) +{ + stream << "\t.byte $" << std::uppercase << std::hex << + std::setfill('0') << std::setw(2) << +character << + " // " << std::setfill(is3n ? '0' : ' ') << std::setw(2) << +idx; + + std::string petscii; + + if (character == 0x20) + { + petscii = " = SPACE"; + } + else if (character == 0x27) + { + petscii = " = APOSTROPHE"; + } + else if (character == 0x0D) + { + petscii = " = RETURN"; + } + else if (character > ' ' && character < 'a') + { + petscii = std::string(" = '") + character + "'"; + } + + stream << petscii << std::endl; +} + +void DataSet::prepareOutput_1n_3n(std::ostringstream &stream) +{ + uint8_t idx; + + // Export all nibble-encoded characters + + stream << std::endl << ".macro put_packed_as_1n() // characters encoded as 1 nibble" << std::endl << "{" << std::endl; + + idx = 0; + for (const auto& encoding : as1n) + { + putCharEncoding(stream, ++idx, encoding, false); + } + + stream << "}" << std::endl; + + // Export all byte-encoded characters + + stream << std::endl << ".macro put_packed_as_3n() // characters encoded as 3 nibbles" << std::endl << "{" << std::endl; + + idx = 0; + for (const auto& encoding : as3n) + { + if (idx == tk__packed_as_3n) stream << std::endl << + "\t// Characters below are not used by any BASIC keyword" << std::endl << std::endl; + + putCharEncoding(stream, ++idx, encoding, true); + } + + stream << "}" << std::endl; +} + +void DataSet::prepareOutput_labels(std::ostringstream &stream, + const StringEntryList &stringEntryList, + const StringEncodedList &stringEncodedList) +{ + // For the dictionary we do not have any labels + if (stringEntryList.type == ListType::DICTIONARY) return; + + stream << std::endl; + for (uint8_t idx = 0; idx < stringEncodedList.size(); idx++) + { + const auto &stringEntry = stringEntryList.list[idx]; + const auto &stringEncoded = stringEncodedList[idx]; + + if (!stringEncoded.empty()) + { + stream << ".label IDX__" << stringEntry.alias << + std::string(maxAliasLen - stringEntry.alias.length(), ' ') << " = $" << + std::uppercase << std::hex << std::setfill('0') << std::setw(2) << +idx << std::endl; + } + } +} + +void DataSet::prepareOutput_packed(std::ostringstream &stream, + const StringEntryList &stringEntryList, + const StringEncodedList &stringEncodedList) +{ + if (isCompressionLvl2(stringEntryList)) + { + stream << std::endl << ".macro put_packed_dict_"; + } + else + { + stream << std::endl << ".macro put_packed_freq_"; + } + + stream << stringEntryList.name << "()" << std::endl << "{" << std::endl; + + enum LastStr { NONE, SKIPPED, WRITTEN } lastStr = LastStr::NONE; + for (uint8_t idxString = 0; idxString < stringEncodedList.size(); idxString++) + { + const auto &stringEncoded = stringEncodedList[idxString]; + + if (stringEncoded.empty()) + { + if (stringEntryList.type == ListType::DICTIONARY) ERROR("internal error"); // should never happen + + if (lastStr == LastStr::WRITTEN) stream << std::endl; + stream << "\t.byte $00 // skipped " << stringEntryList.list[idxString].alias << std::endl; + lastStr = LastStr::SKIPPED; + } + else + { + if (lastStr != LastStr::NONE) stream << std::endl; + + // Output the label - as a comment + + if (stringEntryList.type != ListType::DICTIONARY) + { + stream << "\t// IDX__" << stringEntryList.list[idxString].alias << std::endl; + } + + // Output the source string - as a comment + + stream << "\t// '"; + for (auto &character : stringEntryList.list[idxString].string) + { + if (character >= 32 && character <= 132 && character != 39 && character != 34) + { + stream << character; + } + else if (character == 13) + { + stream << ""; + } + else + { + stream << "_"; + } + } + stream << "'" << std::endl; + + // Output the encoding + + stream << "\t.byte "; + + bool first = true; + for (const auto &charEncoded : stringEncoded) + { + if (first) + { + first = false; + } + else + { + stream << ", "; + } + + stream << "$" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << +charEncoded; + } + + stream << std::endl; + lastStr = LastStr::WRITTEN; + } + } + + // For the token list - put the 'end of keywords' mark + + if (stringEntryList.type == ListType::KEYWORDS) + { + stream << std::endl << "\t// Marker - end of the keyword list" << std::endl; + stream << "\t.byte $FF, $FF" << std::endl; + } + + stream << "}" << std::endl; +} + +void DataSet::prepareOutput() +{ + // Convert our encoded strings to a KickAssembler source + + std::ostringstream stream; + stream << std::endl << "#if ROM_LAYOUT_" << layoutName() << std::endl; + + // Export 1-nibble and 3-nibble encoding data + + prepareOutput_1n_3n(stream); + + // Export additional data for the tokenizer + + stream << std::endl << ".label TK__PACKED_AS_3N = $" << std::hex << +tk__packed_as_3n << + std::endl << ".label TK__MAX_KEYWORD_LEN = " << std::dec << +tk__max_keyword_len << std::endl; + + // Export encoded strings + + for (uint8_t idx = 0; idx < stringEntryLists.size(); idx++) + { + const auto &stringEntryList = stringEntryLists[idx]; + const auto &stringEncodedList = stringEncodedLists[idx]; + + if (stringEncodedList.empty()) continue; + + // Export labels for the current list + + prepareOutput_labels(stream, stringEntryList, stringEncodedList); + + // For the token list - put the number of tokens available + + if (stringEntryList.type == ListType::KEYWORDS) + { + stream << std::endl << ".label TK__MAXTOKEN_" << stringEntryList.name << " = " << + std::dec << stringEncodedList.size() << std::endl; + } + + // Export the packed data + + prepareOutput_packed(stream, stringEntryList, stringEncodedList); + } + + // Finalize the file stream + + stream << std::endl << "#endif // ROM_LAYOUT_" << layoutName() << std::endl; + outFileContent = stream.str(); +} + + +// +// Common helper functions +// + +void parseConfigFile() +{ + GLOBAL_ConfigOptions.clear(); + + // Open the configuration file + + std::ifstream cnfFile; + cnfFile.open(CMD_cnfFile); + if (!cnfFile.good()) ERROR("unable to open config file"); + + // Parse the file + + size_t lineNum = 0; + while (!cnfFile.eof()) + { + lineNum++; + std::string workStr; + + // Read a single line, remove leading spaces and tabs + + std::getline(cnfFile, workStr); + if (cnfFile.bad()) ERROR("error reading configuration file"); + workStr = std::regex_replace(workStr, std::regex("^[ \t]+"), ""); + + // Skip lines which are not preprocessor definitions + + if (workStr.empty() || workStr[0] != '#') continue; + + // Make sure this is '#define ' + + if (!std::regex_match(workStr, std::regex("^#define[ \t].*"))) + { + ERROR(std::string("only '#define' preprocessor directives allowed in config files - line ") + std::to_string(lineNum)); + } + + // Get rid of the directive and trailing spaces/comments + + workStr = std::regex_replace(workStr, std::regex("^#define[ \t]+"), ""); + workStr = std::regex_replace(workStr, std::regex("[ \t]+.*"), ""); + + // Add definitin to config option map + + if (workStr.empty()) ERROR(std::string("error parsing config file - line ") + std::to_string(lineNum)); + + GLOBAL_ConfigOptions[workStr] = true; + } + + cnfFile.close(); +} + +void printUsage() +{ + std::cout << "\n" << + "usage: generate_strings [-o ] [-c ]" << "\n\n"; +} + +void printBanner() +{ + printBannerLineTop(); + std::cout << "// Generating compressed messages and BASIC tokens\n"; + printBannerLineBottom(); +} + +void parseCommandLine(int argc, char **argv) +{ + int opt; + + // Retrieve command line options + + while ((opt = getopt(argc, argv, "o:c:")) != -1) + { + switch(opt) + { + case 'o': CMD_outFile = optarg; break; + case 'c': CMD_cnfFile = optarg; break; + default: printUsage(); ERROR(); + } + } +} + +void writeStrings() +{ + std::string outputString; + + if (GLOBAL_ConfigOptions["CONFIG_PLATFORM_COMMANDER_X16"]) + { + DataSetX16 dataSetX16; + + // Add input data to computation objects + + dataSetX16.addStrings(GLOBAL_Keywords_V2); + dataSetX16.addStrings(GLOBAL_Keywords_CC); + dataSetX16.addStrings(GLOBAL_Keywords_CD); + dataSetX16.addStrings(GLOBAL_Errors); + dataSetX16.addStrings(GLOBAL_MiscStrings); + + // Retrieve the results + + outputString = dataSetX16.getOutput(); + } + else if (GLOBAL_ConfigOptions["CONFIG_PLATFORM_COMMODORE_64"] && GLOBAL_ConfigOptions["CONFIG_MB_MEGA_65"]) + { + DataSetM65 dataSetM65; + + // Add input data to computation objects + + dataSetM65.addStrings(GLOBAL_Keywords_V2); + dataSetM65.addStrings(GLOBAL_Keywords_CC); + dataSetM65.addStrings(GLOBAL_Keywords_CD); + dataSetM65.addStrings(GLOBAL_Errors); + dataSetM65.addStrings(GLOBAL_MiscStrings); + + // Retrieve the results + + outputString = dataSetM65.getOutput(); + } + else if (GLOBAL_ConfigOptions["CONFIG_PLATFORM_COMMODORE_64"]) + { + DataSetSTD dataSetSTD; + + // Add input data to computation objects + + dataSetSTD.addStrings(GLOBAL_Keywords_V2); + dataSetSTD.addStrings(GLOBAL_Keywords_CC); + dataSetSTD.addStrings(GLOBAL_Keywords_CD); + dataSetSTD.addStrings(GLOBAL_Errors); + dataSetSTD.addStrings(GLOBAL_MiscStrings); + + // Retrieve the results + + outputString = dataSetSTD.getOutput(); + } + else + { + ERROR("unable to determine string set"); + } + + // Remove old file + + unlink(CMD_outFile.c_str()); + + // Open output file for writing + + std::ofstream outFile(CMD_outFile, std::fstream::out | std::fstream::trunc); + if (!outFile.good()) ERROR(std::string("can't open oputput file '") + CMD_outFile + "'"); + + // Write header + + outFile << "//\n// Generated file - do not edit\n//"; + + // Write packed strings + + outFile << std::endl << std::endl; + outFile << outputString; + outFile << std::endl << std::endl; + + // Close the file + + outFile.close(); + + std::cout << std::string("Compressed strings written to: ") + CMD_outFile + "\n\n"; +} + +// +// Main function +// + +int main(int argc, char **argv) +{ + printBanner(); + parseCommandLine(argc, argv); + + parseConfigFile(); + + writeStrings(); + + return 0; +} diff --git a/tools/compress_text.c b/tools/outdated/compress_text.c similarity index 98% rename from tools/compress_text.c rename to tools/outdated/compress_text.c index 6f7b0daf..89eaacf0 100644 --- a/tools/compress_text.c +++ b/tools/outdated/compress_text.c @@ -157,12 +157,12 @@ char *error_list[]={ "UNDEF\'D FUNCTION", // https://www.saatchiart.com/print/Painting-Undef-d-Function-3495/16167/3829193/view "VERIFY", // https://forums.openvpn.net/viewtopic.php?t=22040 "LOAD", // https://www.discogs.com/Gimmik-Load-Error/release/482462 + "BREAK", // #29 // Non-error messages - "READY.\r", // #29 // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser - "BREAK", // #30 + "READY.\r", // #30 // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser " IN ", // #31 "BRK AT $", // #32 - "ERROR", // #33 // Simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html + " ERROR", // #33 // Simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html " BASIC BYTES FREE", // #34 // https://github.com/stefanhaustein/expressionparser "MEMORY CORRUPT", // #35 "NOT IMPLEMENTED", // #36