diff --git a/.gitignore b/.gitignore index e4515487..1f3eaccc 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ build/* dump.mem *project .*swp +*.log diff --git a/CONFIG.md b/CONFIG.md index 48a6e652..f548ee4f 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -167,7 +167,7 @@ Needs about 100 more bytes in KERNAL segment. ### `CONFIG_TAPE_NO_KEY_SENSE` -Enable this option if you are using a tape interface adapter with some audio signal source connected. These adapters lack key sense functionality, so the computer is unable to tell whether Play got pressed or not - with this option ROM will assume Play got pressed after impulses start arriving from the tape. +Enable this option if you are using a tape interface adapter with some audio signal source connected. These adapters lack key sense functionality, so the computer is unable to tell whether Play got pressed or not - this option changes the ROM behaviour, so that it can detect Play pressed when impulses start arriving from the tape. ### `CONFIG_TAPE_NO_MOTOR_CONTROL` @@ -187,7 +187,7 @@ The SID support in the ROM is very limited - it only disables the sound during s ### `CONFIG_SID_2ND` and `CONFIG_SID_3RD` -Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively. +Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively. Do not use when `CONFIG_MB_MEGA_65` is selected - the motherboard support code already knows the SID locations. Each of these options needs 3 bytes in KERNAL segment. @@ -195,7 +195,7 @@ Each of these options needs 3 bytes in KERNAL segment. Cause the system to support SIDs in `$D4xx` and `$D5xx` ranges, respectively. -Each of them needs a couple of bytes in KERNAL segment - but they can share some code, and `$D4xx` range support replaces the standard `$D400` address handling, so exact amount depends on the exact configuration. +Each of them needs a couple of bytes in KERNAL segment - but they can share some code, and `$D4xx` range support replaces the standard `$D400` address handling, so exact amount depends on the exact configuration. Do not use when `CONFIG_MB_MEGA_65` is selected - the motherboard support code already knows the SID locations. ## Keyboard diff --git a/CREDITS.md b/CREDITS.md index 72143f5f..d4bef889 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,11 +1,14 @@ # CREDITS to people whose work was of great help to us -## for source code we reused +## for source code/assets we reused +* Retrofan - for his Mega65 banner artwork and PXLfont * TWW/CTR - for his keyboard handling code * Graham - for his PAL/NTSC detection routine * enthusi/Onslaught - for his example Turbo Tape 64 compatible loader +* djmips - for fast 8x8 multiplication routine +* Verz - for the integer division routine ## for documentation @@ -16,6 +19,7 @@ * Jochen Adler - for the JiffyDOS protocol reverse engineering * H2Obsession - for the JiffyDOS protocol description on [his page](https://sites.google.com/site/h2obsession/CBM/C128/JiffySoft128) * SD2IEC team - the project [source code](https://github.com/rkrajnc/sd2iec) helped a lot when adding IEC and JiffyDOS support +* Luigi Di Fraia - for his tape formats [description](https://www.luigidifraia.com/c64/docs/tapeloaders.html) * slark - for his screen codes / PETSCII description at [slark.me](https://slark.me) * silverdr - for the floating point routines [description](https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics) * the [C64 Wiki](https://www.c64-wiki.com) contributors diff --git a/LICENSE b/LICENSE index 310d50d9..f4def5c1 100644 --- a/LICENSE +++ b/LICENSE @@ -3,7 +3,7 @@ The following copyright notices apply to the entirety of this package, including each source file, unless otherwise noted in each file or directory. Copyright Paul Gardner-Stephen, 2019. - Copyright Roman Standzikowski (FeralChil64), 2019-2020. + Copyright Roman Standzikowski (FeralChild64), 2019-2020. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff --git a/Makefile b/Makefile index eecfb259..2181f8c2 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,15 @@ 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 SRCDIR_KERNAL = $(SRCDIR_COMMON) \ @@ -78,6 +81,7 @@ DEP_KERNAL = $(SRC_KERNAL) $(SRCDIR_KERNAL) $(GEN_KERNAL) TOOL_COLLECT_DATA = build/tools/collect_data TOOL_COMPRESS_TEXT = build/tools/compress_text TOOL_GENERATE_CONSTANTS = build/tools/generate_constants +TOOL_PATCH_CHARGEN = build/tools/patch_chargen TOOL_PNGPREPARE = build/tools/pngprepare TOOL_BUILD_SEGMENT = build/tools/build_segment TOOL_RELEASE = build/tools/release @@ -88,29 +92,31 @@ TOOLS_LIST = $(pathsubst tools/%,build/tools/%,$(basename $(SRC_TOOLS))) # List of targets -TARGET_CUS_B = build/basic_custom.rom -TARGET_GEN_B = build/basic_generic.rom -TARGET_TST_B = build/basic_testing.rom -TARGET_U64_B = build/basic_ultimate64.rom +TARGET_CUS_B = build/basic_custom.rom +TARGET_GEN_B = build/basic_generic.rom +TARGET_TST_B = build/basic_testing.rom +TARGET_U64_B = build/basic_ultimate64.rom -TARGET_CUS_K = build/kernal_custom.rom -TARGET_GEN_K = build/kernal_generic.rom -TARGET_TST_K = build/kernal_testing.rom -TARGET_U64_K = build/kernal_ultimate64.rom +TARGET_CUS_K = build/kernal_custom.rom +TARGET_GEN_K = build/kernal_generic.rom +TARGET_TST_K = build/kernal_testing.rom +TARGET_U64_K = build/kernal_ultimate64.rom -TARGET_M65_x = build/mega65.rom -TARGET_X16_x = build/cx16-dummy.rom +TARGET_M65_x = build/mega65.rom +TARGET_M65_x_PXL = build/mega65_pxlfont.rom +TARGET_X16_x = build/cx16-dummy.rom -TARGET_LIST_CUS = $(TARGET_CUS_B) $(TARGET_CUS_K) -TARGET_LIST_GEN = $(TARGET_GEN_B) $(TARGET_GEN_K) -TARGET_LIST_TST = $(TARGET_TST_B) $(TARGET_TST_K) -TARGET_LIST_U64 = $(TARGET_U64_B) $(TARGET_U64_K) +TARGET_LIST_CUS = $(TARGET_CUS_B) $(TARGET_CUS_K) +TARGET_LIST_GEN = $(TARGET_GEN_B) $(TARGET_GEN_K) +TARGET_LIST_TST = $(TARGET_TST_B) $(TARGET_TST_K) +TARGET_LIST_U64 = $(TARGET_U64_B) $(TARGET_U64_K) -TARGET_LIST = build/chargen.rom \ +TARGET_LIST = build/chargen_openroms.rom \ $(TARGET_LIST_CUS) \ $(TARGET_LIST_GEN) \ $(TARGET_LIST_TST) \ $(TARGET_M65_x) \ + $(TARGET_M65_x_PXL) \ $(TARGET_LIST_U64) \ $(TARGET_X16_x) @@ -124,7 +130,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_LIST_U64) +REL_TARGET_LIST = $(TARGET_LIST_GEN) $(TARGET_LIST_TST) $(TARGET_M65_x) $(TARGET_M65_x_PXL) $(TARGET_LIST_U64) # Misc strings @@ -134,11 +140,14 @@ HYBRID_WARNING = "*** WARNING *** Distributing kernal_hybrid.rom violates both o GIT_COMMIT:= $(shell git log -1 --pretty='%h' | tr '[:lower:]' '[:upper:]') -# Rules - main +# Rules - main XXX fast build does not always succeed, not yet clear, why -.PHONY: all clean updatebin +.PHONY: all fast clean updatebin all: + $(MAKE) $(TARGET_LIST) $(EXT_TARGET_LIST) + +fast: $(MAKE) -j64 --output-sync=target $(TARGET_LIST) $(EXT_TARGET_LIST) clean: @@ -147,7 +156,7 @@ clean: updatebin: $(MAKE) -j64 --output-sync=target $(TARGET_LIST) $(TOOL_RELEASE) $(TOOL_RELEASE) -i ./build -o ./bin $(patsubst build/%,%,$(REL_TARGET_LIST)) - cp build/chargen.rom bin/chargen.rom + cp build/chargen_openroms.rom bin/chargen_openroms.rom # Rules - tools @@ -169,8 +178,17 @@ build/tools/%: tools/%.cc tools/common.h # Rules - CHARGEN -build/chargen.rom: $(TOOL_PNGPREPARE) assets/8x8font.png - $(TOOL_PNGPREPARE) charrom assets/8x8font.png build/chargen.rom +build/chargen_openroms.rom: $(TOOL_PNGPREPARE) assets/8x8font.png + $(TOOL_PNGPREPARE) charrom assets/8x8font.png $@ + +build/chargen_pxlfont.rom: bin/chargen_pxlfont_2.3.rom + cp $< $@ + +build/chargen_openroms.patched: $(TOOL_PATCH_CHARGEN) build/chargen_openroms.rom + $(TOOL_PATCH_CHARGEN) -i build/chargen_openroms.rom -o $@ -n 7px-OpenROMs + +build/chargen_pxlfont.patched: $(TOOL_PATCH_CHARGEN) build/chargen_pxlfont.rom + $(TOOL_PATCH_CHARGEN) -i build/chargen_pxlfont.rom -o $@ -n 6px-PXLfont # Dependencies - BASIC and KERNAL @@ -208,7 +226,7 @@ $(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1_combined.vs $(DIR_M65)/KERNAL_1_comb $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_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_M65)/KERNAL_0_combined.sym $(DIR_X16)/BASIC_0_combined.sym + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_BASIC) $(CFG_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 @@ -283,22 +301,22 @@ $(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1_combined.vs $(DIR_M65)/KERNAL_1_comb $(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-mega65 -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) $(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-mega65 -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) $(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-mega65 -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) $(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-mega65 -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) $(SRCDIR_KERNAL) $(GEN_KERNAL) # Rules - BASIC and KERNAL @@ -350,32 +368,49 @@ build/symbols_hybrid.vs: $(DIR_GEN)/KERNAL_combined.vs # Rules - platform 'Mega65' specific -$(TARGET_M65_x): $(SEG_LIST_M65) build/chargen.rom +$(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 + @echo cat build/m65_padding_08_KB > $(TARGET_M65_x) cat build/m65_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 $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x) - cat build/chargen.rom >> $(TARGET_M65_x) - cat build/chargen.rom >> $(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) + @echo + cat build/m65_padding_08_KB > $(TARGET_M65_x_PXL) + cat build/m65_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 $(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_* + @echo # Rules - platform 'Commander X16' specific -$(TARGET_X16_x): $(SEG_LIST_X16) build/chargen.rom +$(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) - cat build/chargen.rom >> $(TARGET_X16_x) + cat build/chargen_openroms.rom >> $(TARGET_X16_x) 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 @@ -401,7 +436,7 @@ 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) +test_mega65: $(TARGET_M65_x) $(TARGET_M65_PXL) ../xemu/build/bin/xmega65.native -dmarev 2 -forcerom -loadrom $(TARGET_M65_x) test_cx16: $(TARGET_X16_x) diff --git a/STATUS.md b/STATUS.md index 10c217d9..e8013b30 100644 --- a/STATUS.md +++ b/STATUS.md @@ -98,7 +98,7 @@ The following ROM features are currently missing: | Driver | Status | Remarks | | :----------------: | :------: | :------------------------------------------------: | | standard | DONE | | -| JiffyDOS | DONE | | +| JiffyDOS | PARTIAL | LOAD needs improvement for better performance | | DolphinDOS | DONE | | | CIA burst mod | NOT DONE | | | Mega65 burst | NOT DONE | | @@ -189,7 +189,7 @@ Floating point mathematical routines - not official, but well known and broadly | `$B794` | `convert_A_to_FAC1` | NOT DONE | | | `$B7B5` | `STRVAL` | NOT DONE | imports string to FAC1 | | `$B7F7` | `convert_FAC1_to_ADDR` | NOT DONE | | -| `$B849` | `add_HALF_FAC1` | NOT DONE | | +| `$B849` | `add_HALF_FAC1` | DONE | | | `$B850` | `sub_MEM_FAC1` | DONE | | | `$B853` | `sub_FAC2_FAC1` | DONE | | | `$B862` | `add_align_exponents` | DONE | | @@ -197,17 +197,15 @@ Floating point mathematical routines - not official, but well known and broadly | `$B86A` | `add_FAC2_FAC1` | DONE | | | `$B8FE` | `normal_FAC1` | DONE | | | `$B947` | `inv_FAC1_mantissa` | NOT DONE | | -| `$B983` | `MULSHF` | NOT DONE | | | `$B9EA` | `log_FAC1` | NOT DONE | | -| `$BA28` | `mul_MEM_FAC1` | PARTIAL | needs `mul_FAC2_FAC1` | -| `$BA2B` | `mul_FAC2_FAC1` | NOT DONE | some work started | -| `$BA59` | `MLTPLY` | NOT DONE | | +| `$BA28` | `mul_MEM_FAC1` | DONE | | +| `$BA2B` | `mul_FAC2_FAC1` | DONE | | | `$BA8C` | `mov_MEM_FAC2` | DONE | | | `$BA90` | `get_FAC2_via_INDEX` | NOT DONE | | -| `$BAE2` | `mul10_FAC1` | NOT DONE | | -| `$BAFE` | `div10_FAC1_p` | NOT DONE | | -| `$BB0F` | `div_MEM_FAC1` | PARTIAL | needs `div_FAC2_FAC1` | -| `$BB12` | `div_FAC2_FAC1` | NOT DONE | | +| `$BAE2` | `mul10_FAC1` | DONE | | +| `$BAFE` | `div10_FAC1_p` | DONE | | +| `$BB0F` | `div_MEM_FAC1` | DONE | | +| `$BB12` | `div_FAC2_FAC1` | DONE | | | `$BBA2` | `mov_MEM_FAC1` | DONE | | | `$BBA6` | `get_FAC2_via_INDEX` | NOT DONE | | | `$BBC7` | `mov_r_FAC1_TMP2` | PARTIAL | not fully tested yet | @@ -218,7 +216,7 @@ Floating point mathematical routines - not official, but well known and broadly | `$BC0C` | `mov_r_FAC1_FAC2` | PARTIAL | not fully tested yet | | `$BC0F` | `mov_FAC1_FAC2` | DONE | | | `$BC1B` | `round_FAC1` | PARTIAL | not fully tested yet | -| `$BC2B` | `sgn_FAC1_A` | NOT DONE | | +| `$BC2B` | `sgn_FAC1_A` | DONE | | | `$BC39` | `sgn_FAC1` | NOT DONE | | | `$BC3C` | `convert_A_to_FAC1` | NOT DONE | | | `$BC44` | `convert_i16_to_FAC1` | NOT DONE | | @@ -229,19 +227,19 @@ Floating point mathematical routines - not official, but well known and broadly | `$BCF3` | `FIN` | NOT DONE | imports string to FAC1, ignores spaces | | `$BD7E` | `FINLOG` | NOT DONE | | | `$BDDD` | `FOUT` | NOT DONE | outputs FAC1 to string at $0100 | -| `$BF71` | `sqr_FAC1` | NOT DONE | | +| `$BF71` | `sqr_FAC1` | PARTIAL | needs `sqr_FAC2` | | `$BF74` | `sqr_FAC2` | NOT DONE | | -| `$BF78` | `FPWR` | NOT DONE | set FAC1 as RAM raised to the power of FAC1 | -| `$BF7B` | `FPWRT` | NOT DONE | set FAC1 as FAC2 raised to the power of FAC1 | +| `$BF78` | `pwr_FAC2_MEM` | PARTIAL | needs `pwr_FAC2_FAC1` | +| `$BF7B` | `pwr_FAC2_FAC1` | NOT DONE | | | `$BFB4` | `toggle_sign_FAC1` | DONE | | | `$BFED` | `exp_FAC1` | NOT DONE | | | `$E043` | `poly1_FAC1` | NOT DONE | | | `$E059` | `poly2_FAC1` | NOT DONE | | -| `$E097` | `rnd_FAC1` | PARTIAL | requires `sgn_FAC1_A` | +| `$E097` | `rnd_FAC1` | DONE | | | `$E09A` | `rnd_A` | DONE | | | `$E0BE` | `rnd_generate` | DONE | | | `$E264` | `cos_FAC1` | NOT DONE | | -| `$E26B` | `sin_FAC1` | NOT DONE | | +| `$E26B` | `sin_FAC1` | NOT DONE | some work already started | | `$E2B4` | `tan_FAC1` | NOT DONE | | | `$E30E` | `atn_FAC1` | NOT DONE | | diff --git a/assembler/KickAss.jar b/assembler/KickAss.jar index 3adf7b5e..1ea5cc88 100644 Binary files a/assembler/KickAss.jar and b/assembler/KickAss.jar differ diff --git a/assembler/KickAssembler.pdf b/assembler/KickAssembler.pdf index 43d11e73..907579f9 100644 Binary files a/assembler/KickAssembler.pdf and b/assembler/KickAssembler.pdf differ diff --git a/bin/README.txt b/bin/README.txt index de60839c..7358db92 100644 --- a/bin/README.txt +++ b/bin/README.txt @@ -2,14 +2,14 @@ Follow these rules, or bad things will happen! -- Don't mix ROMs for different platforms - use generic BASIC with generic KERNAL, Mega65 BASIC with Mega65 KERNAL, etc. +- Don't mix ROMs for different platforms - use generic BASIC with generic KERNAL, Ultimate64 BASIC with Ultimate64 KERNAL, etc. - Don't mix these ROMs with any other ROMs; exceptions: - kernal_hybrid.rom, which is meant to be used (and has to be used) with the original BASIC ROM; however, this hybrid ROM cannot be distributed due to legal/copyright reasons - - chargen.rom - this one is fully interchangeable + - chargen_*.rom - these ones are fully interchangeable - Don't mix ROMs from different builds/versions (again, CHARGEN is an exception). @@ -17,3 +17,11 @@ Follow these rules, or bad things will happen! Have fun! + + +------ + + +PXL font was created by Retrofan, we got a permission to include it with OpenROMs under GNU Lesser General Public License 3.0, see: + +- https://www.forum64.de/index.php?thread/84000-neuer-c64-systemfont-auch-plus4-c128-atari/&postID=1493383#post1493383 diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 7828da6c..90679647 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 index 6d2c34fe..d062189e 100644 Binary files a/bin/basic_testing.rom and b/bin/basic_testing.rom differ diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom index 1fed28bd..57b76a75 100644 Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ diff --git a/bin/chargen.rom b/bin/chargen_openroms.rom similarity index 100% rename from bin/chargen.rom rename to bin/chargen_openroms.rom diff --git a/bin/chargen_pxlfont_2.3.rom b/bin/chargen_pxlfont_2.3.rom new file mode 100644 index 00000000..e43574b4 Binary files /dev/null and b/bin/chargen_pxlfont_2.3.rom differ diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 0df4af2e..1b49889f 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 index 6684bfdb..bf78fb72 100644 Binary files a/bin/kernal_testing.rom and b/bin/kernal_testing.rom differ diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index df018309..b0d12b36 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 ece821ce..9db58314 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 new file mode 100644 index 00000000..3389f9fa Binary files /dev/null and b/bin/mega65_pxlfont.rom differ diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s index 6bd9ee5c..60826470 100644 --- a/c64/,,config_mega65.s +++ b/c64/,,config_mega65.s @@ -51,14 +51,14 @@ #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO #define CONFIG_TAPE_AUTODETECT -// #define CONFIG_TAPE_NO_KEY_SENSE -// #define CONFIG_TAPE_NO_MOTOR_CONTROL +#define CONFIG_TAPE_NO_KEY_SENSE +#define CONFIG_TAPE_NO_MOTOR_CONTROL // #define CONFIG_TAPE_NO_ERROR_CORRECTION // Multiple SID support -#define CONFIG_SID_2ND +// #define CONFIG_SID_2ND .const CONFIG_SID_2ND_ADDRESS = $D440 // #define CONFIG_SID_3RD @@ -83,7 +83,7 @@ #define CONFIG_PROGRAMMABLE_KEYS -.const CONFIG_KEYCMD_RUN = @"LOAD\"*\"" +.const CONFIG_KEYCMD_RUN = @"\$5FL" .const CONFIG_KEYCMD_F1 = @"@" .const CONFIG_KEYCMD_F2 = @"" @@ -114,7 +114,7 @@ #define CONFIG_PANIC_SCREEN #define CONFIG_DOS_WEDGE -// #define CONFIG_TAPE_WEDGE +#define CONFIG_TAPE_WEDGE #define CONFIG_BCD_SAFE_INTERRUPTS diff --git a/c64/aliases/,aliases_config.s b/c64/aliases/,aliases_config.s index 57fb1c9f..ebf44ae2 100644 --- a/c64/aliases/,aliases_config.s +++ b/c64/aliases/,aliases_config.s @@ -42,6 +42,10 @@ #if !CONFIG_PLATFORM_COMMODORE_64 && CONFIG_BRAND_ULTIMATE_64 && .error "CONFIG_BRAND_ULTIMATE_64 can only be used with CONFIG_PLATFORM_COMMODORE_64" #endif + +#if CONFIG_MB_MEGA_65 && (CONFIG_SID_2ND || CONFIG_SID_3RD || CONFIG_SID_D4XX || CONFIG_SID_D5XX) + .error "CONFIG_MB_MEGA_65 cannot be used with CONFIG_SID_*" +#endif } @@ -108,9 +112,9 @@ #if ROM_LAYOUT_M65 && !CONFIG_CPU_M65_45GS02 .error "Mega65 ROM layout requires CONFIG_CPU_M65_45GS02" #endif -//#if ROM_LAYOUT_M65 && !CONFIG_MB_MEGA_65 -// .error "Mega65 ROM layout requires CONFIG_MB_MEGA_65" -//#endif +#if ROM_LAYOUT_M65 && !CONFIG_MB_MEGA_65 + .error "Mega65 ROM layout requires CONFIG_MB_MEGA_65" +#endif .var selected = 0; diff --git a/c64/aliases/,aliases_cpu.s b/c64/aliases/,aliases_cpu.s index b45f73f3..38a321dc 100644 --- a/c64/aliases/,aliases_cpu.s +++ b/c64/aliases/,aliases_cpu.s @@ -69,6 +69,11 @@ #if HAS_OPCODES_65CE02 +// CPU flags support + +.pseudocommand cle { .byte $02 } +.pseudocommand see { .byte $03 } + // .B register support .pseudocommand tab { .byte $5B } @@ -99,7 +104,121 @@ .byte $E3, arg } -// additional addressing modes +// Zero page bit handling + +.pseudocommand rmb0 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB0 requires zeropage address" + .byte $07, arg +} + +.pseudocommand rmb1 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB1 requires zeropage address" + .byte $17, arg +} + +.pseudocommand rmb2 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB2 requires zeropage address" + .byte $27, arg +} + +.pseudocommand rmb3 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB3 requires zeropage address" + .byte $37, arg +} + +.pseudocommand rmb4 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB4 requires zeropage address" + .byte $47, arg +} + +.pseudocommand rmb5 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB5 requires zeropage address" + .byte $57, arg +} + +.pseudocommand rmb6 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB6 requires zeropage address" + .byte $67, arg +} + +.pseudocommand rmb7 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "RMB7 requires zeropage address" + .byte $77, arg +} + +.pseudocommand smb0 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB0 requires zeropage address" + .byte $87, arg +} + +.pseudocommand smb1 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB1 requires zeropage address" + .byte $97, arg +} + +.pseudocommand smb2 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB2 requires zeropage address" + .byte $A7, arg +} + +.pseudocommand smb3 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB3 requires zeropage address" + .byte $B7, arg +} + +.pseudocommand smb4 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB4 requires zeropage address" + .byte $C7, arg +} + +.pseudocommand smb5 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB5 requires zeropage address" + .byte $D7, arg +} + +.pseudocommand smb6 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB6 requires zeropage address" + .byte $E7, arg +} + +.pseudocommand smb7 addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "SMB7 requires zeropage address" + .byte $F7, arg +} + +// Additional addressing modes .pseudocommand jsr_ind addr { diff --git a/c64/aliases/,aliases_hardware.s b/c64/aliases/,aliases_hardware.s index e7a7a51c..bdd0f5e5 100644 --- a/c64/aliases/,aliases_hardware.s +++ b/c64/aliases/,aliases_hardware.s @@ -83,6 +83,15 @@ .label __SID_BASE = $D400 // base address of the chip +#if CONFIG_MB_MEGA_65 + + .label __SID_R1_OFFSET = $00 // right SID 1, $D400 + .label __SID_R2_OFFSET = $20 // right SID 2, $D420 + .label __SID_L1_OFFSET = $40 // left SID 1, $D440 + .label __SID_L2_OFFSET = $60 // left SID 2, $D460 + +#endif + .label SID_FRELO1 = $D400 .label SID_FREHI1 = $D401 .label SID_PWLO1 = $D402 @@ -177,6 +186,8 @@ .const C65_EXTKEYS_PR = $D607 .const C65_EXTKEYS_DDR = $D608 + .const M65_BADL_SLI = $D710 + #endif diff --git a/c64/aliases/,aliases_rom_kernal.s b/c64/aliases/,aliases_rom_kernal.s index 35e89d07..2f568ce2 100644 --- a/c64/aliases/,aliases_rom_kernal.s +++ b/c64/aliases/,aliases_rom_kernal.s @@ -1,5 +1,8 @@ +// #LAYOUT# * BASIC_1 #IGNORE +// #LAYOUT# * * #TAKE // Kernal jump table + .label JCINT = $FF81 .label JIOINIT = $FF84 .label JRAMTAS = $FF87 diff --git a/c64/basic/,imports.s b/c64/basic/,imports.s index ebcf56c9..8c7b7643 100644 --- a/c64/basic/,imports.s +++ b/c64/basic/,imports.s @@ -1,3 +1,8 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_0 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 +// #LAYOUT# * * #IGNORE + // Routines imported from Kernal - our private API @@ -18,6 +23,11 @@ } +#if ROM_LAYOUT_M65 +.label map_end = KERNAL().map_end +.label map_NORMAL = KERNAL().map_NORMAL +#endif + #if CONFIG_PANIC_SCREEN .label panic = KERNAL().panic #endif diff --git a/c64/basic/,stubs_math/b983.MULSHF.s b/c64/basic/,stubs_math/b983.MULSHF.s deleted file mode 100644 index b4389b13..00000000 --- a/c64/basic/,stubs_math/b983.MULSHF.s +++ /dev/null @@ -1,18 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Math package - SHIFT routine -// -// See also: -// - [CM64] Computes Mapping the Commodore 64 - page 113 -// - -// XXX implement, test - - -MULSHF: - - STUB_IMPLEMENTATION() diff --git a/c64/basic/,stubs_math/b983.interop b/c64/basic/,stubs_math/b983.interop deleted file mode 100644 index 0d18777c..00000000 --- a/c64/basic/,stubs_math/b983.interop +++ /dev/null @@ -1,3 +0,0 @@ -This is an important floating point math routine, documented in many places. - -XXX - try to find real-life example diff --git a/c64/basic/,stubs_math/ba59.MLTPLY.s b/c64/basic/,stubs_math/ba59.MLTPLY.s deleted file mode 100644 index 294cd246..00000000 --- a/c64/basic/,stubs_math/ba59.MLTPLY.s +++ /dev/null @@ -1,18 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Math package - add a mantissa byte of FAC2 to FAC1, do it .A times -// -// See also: -// - [CM64] Computes Mapping the Commodore 64 - page 113 -// - -// XXX implement, test - - -MULTPLY: - - STUB_IMPLEMENTATION() diff --git a/c64/basic/,stubs_math/ba59.interop b/c64/basic/,stubs_math/ba59.interop deleted file mode 100644 index 0d18777c..00000000 --- a/c64/basic/,stubs_math/ba59.interop +++ /dev/null @@ -1,3 +0,0 @@ -This is an important floating point math routine, documented in many places. - -XXX - try to find real-life example diff --git a/c64/basic/,stubs_math/bae2.mul10_FAC1.s b/c64/basic/,stubs_math/bae2.mul10_FAC1.s deleted file mode 100644 index 4d6e570d..00000000 --- a/c64/basic/,stubs_math/bae2.mul10_FAC1.s +++ /dev/null @@ -1,18 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Math package - multiply FAC1 by 10 -// -// See also: -// - [CM64] Computes Mapping the Commodore 64 - page 114 -// - https://www.c64-wiki.com/wiki/Floating_point_arithmetic -// - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics -// - -// XXX provide implementation - -mul10_FAC1: - STUB_IMPLEMENTATION() diff --git a/c64/basic/,stubs_math/bb12.div_FAC2_FAC1.s b/c64/basic/,stubs_math/bb12.div_FAC2_FAC1.s deleted file mode 100644 index 03f5b8db..00000000 --- a/c64/basic/,stubs_math/bb12.div_FAC2_FAC1.s +++ /dev/null @@ -1,24 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Math package - divide FAC2 by FAC1, ignores sign -// -// Input: -// - .A - must load FAC1 exponent ($61) beforehand to set the zero flag -// -// Output: -// - leaves the quotient FAC1 and the remainder in FAC2 -// -// See also: -// - [CM64] Computes Mapping the Commodore 64 - page 114 -// - https://www.c64-wiki.com/wiki/Floating_point_arithmetic -// - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics -// - -// XXX provide implementation - -div_FAC2_FAC1: - STUB_IMPLEMENTATION() diff --git a/c64/basic/,stubs_math/bf7b.FPWRT.s b/c64/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s similarity index 97% rename from c64/basic/,stubs_math/bf7b.FPWRT.s rename to c64/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s index 1bc6264a..6bb1a7f6 100644 --- a/c64/basic/,stubs_math/bf7b.FPWRT.s +++ b/c64/basic/,stubs_math/bf7b.pwr_FAC2_FAC1.s @@ -21,5 +21,5 @@ // XXX provide implementation -FPWRT: +pwr_FAC2_FAC1: STUB_IMPLEMENTATION() diff --git a/c64/basic/,stubs_math/e26b.sin_FAC1.s b/c64/basic/,stubs_math/e26b.sin_FAC1.s index 99eb4569..82a86d2f 100644 --- a/c64/basic/,stubs_math/e26b.sin_FAC1.s +++ b/c64/basic/,stubs_math/e26b.sin_FAC1.s @@ -15,3 +15,14 @@ sin_FAC1: STUB_IMPLEMENTATION() + +poly_sin: + + .byte $05 // series length - 1 + + put_const_POLY_SIN_1() + put_const_POLY_SIN_2() + put_const_POLY_SIN_3() + put_const_POLY_SIN_4() + put_const_POLY_SIN_5() + put_const_POLY_SIN_6() diff --git a/c64/basic/a533.linkprg.s b/c64/basic/a533.linkprg.s index f272bd30..57d6bdda 100644 --- a/c64/basic/a533.linkprg.s +++ b/c64/basic/a533.linkprg.s @@ -1,6 +1,7 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_0 #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE-FLOAT // #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 -// #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // @@ -12,6 +13,14 @@ LINKPRG: +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__LINKPRG + jmp map_NORMAL + +#else + // Start by getting pointer to the first line jsr init_oldtxt @@ -19,11 +28,13 @@ linkprg_loop: // Is the pointer to the end of the program ldy #1 -#if CONFIG_MEMORY_MODEL_60K +#if ROM_LAYOUT_M65 + jsr peek_via_OLDTXT +#elif CONFIG_MEMORY_MODEL_60K ldx #$0801 + sta TXTTAB+1 + sta VARTAB+1 + lda #<$0803 + sta VARTAB+0 + + // Zero line pointer + // XXX - We should also zero $0800, i.e., TXTTAB - 1 + ldy #$00 + tya + sta (TXTTAB),y + iny + sta (TXTTAB),y + + + // Get top of memory. + // If a cart is present, then it is $7FFF, + // if not, then it is $F7FF, since we support having + // programs and variables under ROM. + // i.e., we support 56KB RAM for BASIC, keeping some space + // free for some optimisation structures, e.g., FOR/NEXT loop + // records (without them going on the stack), GOSUB stack + // (same story), expression value cache? + + sec // Read, not write value + jsr JMEMTOP + cpx #$80 + beq !+ +#if CONFIG_MEMORY_MODEL_60K + lda #>$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #>$A000 +#endif + .byte $2C +!: +#if CONFIG_MEMORY_MODEL_60K + lda #>$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #>$A000 +#endif + sta MEMSIZ+1 + sta FRETOP+1 +#if CONFIG_MEMORY_MODEL_60K + lda #<$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #<$A000 +#endif + sta MEMSIZ+0 + sta FRETOP+0 + + // FALL THROUGH + +basic_do_clr: + + // Clear variables, arrays and strings + lda VARTAB+0 + sta ARYTAB+0 + sta STREND+0 + lda VARTAB+1 + sta ARYTAB+1 + sta STREND+1 + + rts + +#endif // ROM layout diff --git a/c64/basic/board_m65/4000.mega65_vectable_basic_1.s b/c64/basic/board_m65/4000.mega65_vectable_basic_1.s new file mode 100644 index 00000000..e69e0332 --- /dev/null +++ b/c64/basic/board_m65/4000.mega65_vectable_basic_1.s @@ -0,0 +1,34 @@ +// #LAYOUT# M65 BASIC_0 #TAKE-FLOAT +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Definitions for communication with Mega65 segment BASIC_1 from BASIC_0 +// + + +#if SEGMENT_BASIC_0 + + // Label definitions + + .label VB1__INITMSG = $4000 + 2 * 0 + .label VB1__LINKPRG = $4000 + 2 * 1 + .label VB1__tokenise_line = $4000 + 2 * 2 + .label VB1__list_single_line = $4000 + 2 * 3 + .label VB1__print_packed_message = $4000 + 2 * 4 + .label VB1__basic_do_clr = $4000 + 2 * 5 + .label VB1__basic_do_new = $4000 + 2 * 6 + +#else + + // Vector table (OpenROMs private!) + + .word INITMSG + .word LINKPRG + .word tokenise_line + .word list_single_line + .word print_packed_message + .word basic_do_clr + .word basic_do_new + +#endif diff --git a/c64/basic/board_m65/mega65_dummy.s b/c64/basic/board_m65/mega65_dummy.s deleted file mode 100644 index 338a1c16..00000000 --- a/c64/basic/board_m65/mega65_dummy.s +++ /dev/null @@ -1,7 +0,0 @@ -// #LAYOUT# M65 BASIC_1 #TAKE -// #LAYOUT# * * #IGNORE - - -// Dummy, just to have anything in segment 1 - - brk diff --git a/c64/basic/board_m65/mega65_imports.s b/c64/basic/board_m65/mega65_imports.s new file mode 100644 index 00000000..de496d3b --- /dev/null +++ b/c64/basic/board_m65/mega65_imports.s @@ -0,0 +1,27 @@ +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Definitions for calling Mega65 segments BASIC_0 and KERNAL_0 routines from BASIC_1 +// + +#import "BASIC_0_combined.sym" + + +.label peek_via_OLDTXT = BASIC_0.proxy_B1_peek_via_OLDTXT +.label poke_via_OLDTXT = BASIC_0.proxy_B1_poke_via_OLDTXT +.label JCHROUT = BASIC_0.proxy_B1_JCHROUT +.label JMEMTOP = KERNAL_0.JMEMTOP +.label plot_set = KERNAL_0.plot_set +.label init_oldtxt = BASIC_0.init_oldtxt +.label rom_revision_basic_string = BASIC_0.rom_revision_basic_string +.label print_integer = BASIC_0.proxy_B1_print_integer +.label print_return = BASIC_0.proxy_B1_print_return +.label print_space = BASIC_0.proxy_B1_print_space +#if CONFIG_SHOW_PAL_NTSC +.label print_pal_ntsc = BASIC_0.proxy_B1_print_pal_ntsc +#endif +#if CONFIG_SHOW_FEATURES +.label print_features = BASIC_0.proxy_B1_print_features +#endif +.label do_STRING_TOO_LONG_error = BASIC_0.do_STRING_TOO_LONG_error diff --git a/c64/basic/board_m65/mega65_map_helpers.s b/c64/basic/board_m65/mega65_map_helpers.s new file mode 100644 index 00000000..73e22cdb --- /dev/null +++ b/c64/basic/board_m65/mega65_map_helpers.s @@ -0,0 +1,28 @@ +// #LAYOUT# M65 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// ROM mapping routines for Mega65 +// + +// Available memory maps: +// - NORMAL - nothing mapped in (taken from Kernal) +// - BASIC_1 - for calling KERNAL_1 segment code + + +map_BASIC_1: + + php + pha + phx + phy + phz + + lda #$00 + tay + taz + + lda #$20 + ldx #$42 // 0x4000 <- map 8KB from 0x22000 + + jmp map_end diff --git a/c64/basic/board_m65/mega65_proxies.s b/c64/basic/board_m65/mega65_proxies.s new file mode 100644 index 00000000..91808310 --- /dev/null +++ b/c64/basic/board_m65/mega65_proxies.s @@ -0,0 +1,76 @@ +// #LAYOUT# M65 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Proxies for calling Mega65 segment BASIC_0 and KERNAL_0 routines from BASIC_1 +// + + +proxy_B1_peek_via_OLDTXT: + + jsr map_NORMAL +#if CONFIG_MEMORY_MODEL_60K + .error "not implemented" +#else // CONFIG_MEMORY_MODEL_38K + lda (OLDTXT),y +#endif + jmp map_BASIC_1 + +proxy_B1_poke_via_OLDTXT: + + jsr map_NORMAL +#if CONFIG_MEMORY_MODEL_60K + .error "not implemented" +#else // CONFIG_MEMORY_MODEL_38K + sta (OLDTXT),y +#endif + jmp map_BASIC_1 + + +proxy_B1_JCHROUT: + + jsr map_NORMAL + jsr JCHROUT + jmp map_BASIC_1 + + +proxy_B1_print_integer: + + jsr map_NORMAL + jsr print_integer + jmp map_BASIC_1 + + +proxy_B1_print_return: + + jsr map_NORMAL + jsr print_return + jmp map_BASIC_1 + + +proxy_B1_print_space: + + jsr map_NORMAL + jsr print_space + jmp map_BASIC_1 + + +#if CONFIG_SHOW_PAL_NTSC + +proxy_B1_print_pal_ntsc: + + jsr map_NORMAL + jsr print_pal_ntsc + jmp map_BASIC_1 + +#endif + +#if CONFIG_SHOW_FEATURES + +proxy_B1_print_features: + + jsr map_NORMAL + jsr print_features + jmp map_BASIC_1 + +#endif diff --git a/c64/basic/commands/cmd_clr.s b/c64/basic/commands/cmd_clr.s new file mode 100644 index 00000000..8f7b7af5 --- /dev/null +++ b/c64/basic/commands/cmd_clr.s @@ -0,0 +1,12 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_clr: + + jsr basic_do_clr + + // CLR command does not stop execution + // (Cconfirmed on a c64) + jmp basic_execute_statement diff --git a/c64/basic/commands/cmd_list.s b/c64/basic/commands/cmd_list.s index 973ebc89..a1fcdb1d 100644 --- a/c64/basic/commands/cmd_list.s +++ b/c64/basic/commands/cmd_list.s @@ -11,6 +11,9 @@ cmd_list: // Set current line pointer to start of memory jsr init_oldtxt + // Always start with empty line, for readability + jsr print_return + list_loop: ldy #1 @@ -39,114 +42,3 @@ list_more_lines: // Now link to the next line jsr basic_find_next_line jmp list_loop - -list_single_line: // entry point needed by DOS wedge - // Print line number - ldy #3 - -#if CONFIG_MEMORY_MODEL_60K - jsr peek_under_roms -#else // CONFIG_MEMORY_MODEL_38K - lda (OLDTXT),y -#endif - - pha - dey - -#if CONFIG_MEMORY_MODEL_60K - jsr peek_under_roms -#else // CONFIG_MEMORY_MODEL_38K - 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 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 diff --git a/c64/basic/commands/cmd_load.s b/c64/basic/commands/cmd_load.s index 17f1fee7..08d2b93c 100644 --- a/c64/basic/commands/cmd_load.s +++ b/c64/basic/commands/cmd_load.s @@ -20,11 +20,40 @@ cmd_load: lda #$00 sta FNLEN - // Without tape support, LOAD must have a filename - // (This also skips any leading spaces) + // Check for the file name jsr basic_end_of_statement_check bcc !+ - jmp do_MISSING_FILENAME_error + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + // No file name given, just load the first file from tape + + ldx #$00 + stx SA // secondary address +#if CONFIG_TAPE_NORMAL + inx // 1 - for normal tape format +#else + ldx #$07 // 7 - for turbo tape format +#endif + stx FA // device number + bne cmd_load_got_secondaryaddress // branch always + +#else + + // Without tape support, try to load the first file from disk + + lda #$01 // name length + ldx #cmd_load_default_filename + jsr JSETNAM + jmp got_filename + +cmd_load_default_filename: + + .text "*" + +#endif + !: jsr basic_fetch_and_consume_character cmp #$22 diff --git a/c64/basic/commands/cmd_new.s b/c64/basic/commands/cmd_new.s index fc455a77..31c6681b 100644 --- a/c64/basic/commands/cmd_new.s +++ b/c64/basic/commands/cmd_new.s @@ -4,81 +4,9 @@ cmd_new: + jsr basic_do_new // NEW command terminates execution // (Confirmed on a C64) jmp basic_main_loop - -cmd_clr: - jsr basic_do_clr - // CLR command does not stop execution - // (Cconfirmed on a c64) - jmp basic_execute_statement - -basic_do_new: - // Setup pointers to memory storage XXX should depend on text start vector - lda #<$0801 - sta TXTTAB+0 - lda #>$0801 - sta TXTTAB+1 - sta VARTAB+1 - lda #<$0803 - sta VARTAB+0 - - // Zero line pointer - // XXX - We should also zero $0800, i.e., TXTTAB - 1 - ldy #$00 - tya - sta (TXTTAB),y - iny - sta (TXTTAB),y - - - // Get top of memory. - // If a cart is present, then it is $7FFF, - // if not, then it is $F7FF, since we support having - // programs and variables under ROM. - // i.e., we support 56KB RAM for BASIC, keeping some space - // free for some optimisation structures, e.g., FOR/NEXT loop - // records (without them going on the stack), GOSUB stack - // (same story), expression value cache? - - sec // Read, not write value - jsr JMEMTOP - cpx #$80 - beq !+ -#if CONFIG_MEMORY_MODEL_60K - lda #>$F7FF -#else // CONFIG_MEMORY_MODEL_38K - lda #>$A000 -#endif - .byte $2C -!: -#if CONFIG_MEMORY_MODEL_60K - lda #>$F7FF -#else // CONFIG_MEMORY_MODEL_38K - lda #>$A000 -#endif - sta MEMSIZ+1 - sta FRETOP+1 -#if CONFIG_MEMORY_MODEL_60K - lda #<$F7FF -#else // CONFIG_MEMORY_MODEL_38K - lda #<$A000 -#endif - sta MEMSIZ+0 - sta FRETOP+0 - - // FALL THROUGH - -basic_do_clr: - // Clear variables, arrays and strings - lda VARTAB+0 - sta ARYTAB+0 - sta STREND+0 - lda VARTAB+1 - sta ARYTAB+1 - sta STREND+1 - - rts diff --git a/c64/basic/init/e422.initmsg.jmp.s b/c64/basic/init/e422.initmsg.jmp.s index 9d69690f..591ed9ac 100644 --- a/c64/basic/init/e422.initmsg.jmp.s +++ b/c64/basic/init/e422.initmsg.jmp.s @@ -11,4 +11,15 @@ // INITMSG: + +#if ROM_LAYOUT_M65 + + jsr map_BASIC_1 + jsr_ind VB1__INITMSG + jmp map_NORMAL + +#else + jmp initmsg_real + +#endif diff --git a/c64/basic/init/initmsg_bytes_free.s b/c64/basic/init/initmsg_bytes_free.s index ee2c4fa5..0093c12a 100644 --- a/c64/basic/init/initmsg_bytes_free.s +++ b/c64/basic/init/initmsg_bytes_free.s @@ -1,5 +1,6 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // diff --git a/c64/basic/init/initmsg_real.s b/c64/basic/init/initmsg_real.s index 15ca951c..332ef462 100644 --- a/c64/basic/init/initmsg_real.s +++ b/c64/basic/init/initmsg_real.s @@ -1,13 +1,22 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // Routine is too long to fit in the original location +#if ROM_LAYOUT_M65 + +INITMSG: + +#else + initmsg_real: +#endif + // Clear the screen first, some cartridges (like IEEE-488) leeave a mess on the screen lda #147 jsr JCHROUT @@ -126,6 +135,20 @@ initmsg_real: ldy #>startup_banner jsr STROUT +#if ROM_LAYOUT_M65 + + // XXX make it different for future Mega65 native mode + + ldx #$02 + ldy #$21 + jsr plot_set + + lda #text_mode_64 + jsr STROUT + +#endif + ldx #$05 ldy #$00 jsr plot_set diff --git a/c64/basic/init/startup_banner.s b/c64/basic/init/startup_banner.s index faedc2c3..68fb173a 100644 --- a/c64/basic/init/startup_banner.s +++ b/c64/basic/init/startup_banner.s @@ -1,5 +1,6 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // @@ -78,24 +79,46 @@ pre_revision_string: #elif CONFIG_BANNER_BRAND && CONFIG_BRAND_MEGA_65 + // Fancy Mega65 banner - from Retrofan, slightly tweaked + + .byte $9A, $12, $20, $20, $7F, $A9, $20, $20, $1F, $20, $9A, $20, $20, $20, $20, $1F + .byte $20, $9A, $A9, $20, $20, $20, $92, $A1, $1F, $12, $20, $9A, $A9, $20, $20, $20 + .byte $7F, $1F, $20, $20, $9A, $A3, $A3, $A3, $A3, $A3, $A3, $A3, $1F + .byte $0D + .byte $9A, $12, $20, $20, $20, $20, $20 + .byte $20, $1F, $20, $9A, $20, $20, $92, $A2, $bb, $1F, $12, $20, $9A, $20, $20, $92 + .byte $Ac, $A2, $A2, $1F, $12, $20, $9A, $20, $20, $1F, $20, $9A, $20, $20, $1F, $20 + .byte $20, $1e, $A3, $A3, $A3, $A3, $A3, $A3, $1F + .byte $0D + .byte $9A, $12, $20, $20, $92, $7F, $A9, $12, $20, $20, $1F, $20, $9A, $20, $20, $A2 + .byte $92, $be, $1F, $12, $20, $9A, $20, $20, $92, $bc, $12, $20, $20, $1F, $20, $9A + .byte $20, $20, $20, $20, $20, $1F, $20, $20, $9e, $A3, $A3, $A3, $A3, $A3, $1F + .byte $0D + .byte $9A, $12, $20, $20, $1F, $20, $20, $9A, $20, $20, $1F, $20, $9A, $20, $20, $20 + .byte $20, $1F, $20, $9A, $20, $20, $20, $20, $20, $1F, $20, $9A, $20, $20, $1F, $20 + .byte $9A, $20, $20, $1F, $20, $20, $96, $A3, $A3, $A3, $A3, $1F, $92 + .byte $0D, $0D, $05, $00 + // Fancy Mega65 banner - from Retrofan - .byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20 - .byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20 - .byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20 - .byte $20, $20, $20, $05, $92, $4d, $45, $47, $41, $9a, $12, $20, $20, $20, $20, $20 - .byte $20, $1f, $20, $9a, $20, $20, $92, $a2, $bb, $1f, $12, $20, $9a, $20, $20, $92 - .byte $ac, $a2, $a2, $1f, $12, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20 - .byte $20, $1e, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $42 - .byte $41, $53, $49, $43, $9a, $12, $20, $20, $92, $7f, $a9, $12, $20, $20, $1f, $20 - .byte $9a, $20, $20, $a2, $92, $be, $1f, $12, $20, $9a, $20, $20, $92, $bc, $12, $20 - .byte $20, $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $20, $9e, $a3, $a3, $a3 - .byte $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $2d, $2d, $2d, $2d, $2d, $2d, $9a - .byte $12, $20, $20, $1f, $20, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $20, $20 - .byte $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20, $9a - .byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f - .byte $92, $0D, $0D, $05, $00 + // + // .byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20 + // .byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20 + // .byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20 + // .byte $20, $20, $20, $05, $92, $4d, $45, $47, $41, $9a, $12, $20, $20, $20, $20, $20 + // .byte $20, $1f, $20, $9a, $20, $20, $92, $a2, $bb, $1f, $12, $20, $9a, $20, $20, $92 + // .byte $ac, $a2, $a2, $1f, $12, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20 + // .byte $20, $1e, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $42 + // .byte $41, $53, $49, $43, $9a, $12, $20, $20, $92, $7f, $a9, $12, $20, $20, $1f, $20 + // .byte $9a, $20, $20, $a2, $92, $be, $1f, $12, $20, $9a, $20, $20, $92, $bc, $12, $20 + // .byte $20, $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $20, $9e, $a3, $a3, $a3 + // .byte $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $2d, $2d, $2d, $2d, $2d, $2d, $9a + // .byte $12, $20, $20, $1f, $20, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $20, $20 + // .byte $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20, $9a + // .byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f + // .byte $92, $0D, $0D, $05, $00 // Original Mega65 banner - supplied by Deft + // // .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0 // .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0 // .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20 @@ -112,4 +135,15 @@ pre_revision_string: // .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D // .byte $0D,$05,$92,$00 +#if ROM_LAYOUT_M65 + +text_mode_64: + + .text "LEGACY" + .byte $11, $9D, $9D, $9D, $9D, $9D + .text "MODE" + .byte $00 + +#endif + #endif diff --git a/c64/basic/math/add_align_exponents.s b/c64/basic/math/add_align_exponents.s index 3956ed9c..882cb337 100644 --- a/c64/basic/math/add_align_exponents.s +++ b/c64/basic/math/add_align_exponents.s @@ -9,8 +9,6 @@ // - [CM64] Computes Mapping the Commodore 64 - page 115 // - https://www.c64-wiki.com/wiki/BASIC-ROM -// XXX finish and test this - add_align_exponents: // XXX assume here none of the exponents is 0, check if this is true for orignal ROMs diff --git a/c64/basic/,stubs_math/b849.add_HALF_FAC1.s b/c64/basic/math/b849.add_HALF_FAC1.s similarity index 82% rename from c64/basic/,stubs_math/b849.add_HALF_FAC1.s rename to c64/basic/math/b849.add_HALF_FAC1.s index deac2795..76f21ff0 100644 --- a/c64/basic/,stubs_math/b849.add_HALF_FAC1.s +++ b/c64/basic/math/b849.add_HALF_FAC1.s @@ -9,8 +9,9 @@ // See also: // - [CM64] Computes Mapping the Commodore 64 - page 112 -// XXX implement - add_HALF_FAC1: - STUB_IMPLEMENTATION() + ldy #>const_HALF + lda #const_TEN + lda # Carry + + asl FAC2_mantissa+3 + rol FAC2_mantissa+2 + rol FAC2_mantissa+1 + rol FAC2_mantissa+0 + + // Multiply remainder by 2, lsb <- Carry + + rol RESHO+3 + rol RESHO+2 + rol RESHO+1 + rol RESHO+0 + + // Subtract divisor from the remainder, result to INDEX and .Y + + sec + lda RESHO+3 + sbc FAC1_mantissa+3 + sta INDEX+3 + + lda RESHO+2 + sbc FAC1_mantissa+2 + sta INDEX+2 + + lda RESHO+1 + sbc FAC1_mantissa+1 + sta INDEX+1 + + lda RESHO+0 + sbc FAC1_mantissa+0 + + bcc div_mantissas_skip // if Carry is not set then divisor did not fit in remainder yet + sta INDEX+0 + + // Save subtraction result as new remainder + + lda INDEX+3 + sta RESHO+3 + + lda INDEX+2 + sta RESHO+2 + + lda INDEX+1 + sta RESHO+1 + + lda INDEX+0 + sta RESHO+0 + + // Increment result cause divisor fit in 1 times + + inc FAC2_mantissa+3 + + // FALLTROUGH + +div_mantissas_skip: + + dex + bne div_mantissas_loop + + rts diff --git a/c64/basic/math/mul10_FAC1_mul2.s b/c64/basic/math/mul10_FAC1_mul2.s new file mode 100644 index 00000000..55b8f160 --- /dev/null +++ b/c64/basic/math/mul10_FAC1_mul2.s @@ -0,0 +1,16 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Multiply FAC1 by 2, do not normalize +// + +mul10_FAC1_mul2: + + // Increment the exponent + + inc FAC1_exponent + beq_16 set_FAC1_max + + rts diff --git a/c64/basic/math/mul_FAC2_FAC1.s b/c64/basic/math/mul_FAC2_FAC1.s index 35b71b39..20cafdd0 100644 --- a/c64/basic/math/mul_FAC2_FAC1.s +++ b/c64/basic/math/mul_FAC2_FAC1.s @@ -17,7 +17,14 @@ // - https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics // -// XXX provide implementation +set_FAC1_zero: + + lda #$00 + sta FAC1_exponent + +mul_FAC2_FAC1_done: + + rts mul_FAC2_FAC1: @@ -37,54 +44,152 @@ mul_FAC2_FAC1: eor FAC2_sign sta FAC1_sign - // Check if exponents can be added without overflow/underflow - - lda FAC1_exponent - and #$80 - eor FAC2_exponent - - bmi mul_FAC2_FAC1_add_exponents // exponent signs are opposite, we can add them safely - - // Both exponents are either negative (below $80), or both are non-negative ($80 or above), - // try to add them - - lda FAC1_exponent - clc - adc FAC2_exponent - bpl mul_FAC2_FAC1_sub_exp_bias // branch if we can add values - - // We cannot add them, result would over/underflow; set result as - // either 0 or maximum possible float - - lda FAC1_exponent - bmi_16 set_FAC1_max + // Add the exponents (subtract the bias) - XXX can this be optimized somehow? + + jsr muldiv_RESHO_set_0 - lda #$00 - sta FAC1_exponent - rts - -mul_FAC2_FAC1_add_exponents: - - // Add the exponents - lda FAC1_exponent - clc - adc FAC2_exponent - - // FALLTROUGH - -mul_FAC2_FAC1_sub_exp_bias: - - sec - sbc #$80 // bias + jsr muldiv_RESHO_01_add_A + + lda FAC2_exponent + jsr muldiv_RESHO_01_add_A + + lda RESHO+0 + sbc #$80 // we need to correct double BIAS + sta RESHO+0 + bcs !+ + lda RESHO+1 + sbc #$00 + bcc set_FAC1_zero + sta RESHO+1 +!: + lda RESHO+1 + bne_16 set_FAC1_max // overflow + + lda RESHO+0 sta FAC1_exponent - + // Multiply the mantissas - - // XXX - STUB_IMPLEMENTATION() + jsr muldiv_RESHO_set_0 + clc -mul_FAC2_FAC1_done: + // XXX maybe we should preserve .X on stack? this will not cost us too much + + lda FACOV + jsr mul_FAC2_FAC1_by_A + jsr mul_FAC2_FAC1_shift + bcc !+ + inc RESHO+0 +!: + lda FAC1_mantissa+3 + jsr mul_FAC2_FAC1_by_A + jsr mul_FAC2_FAC1_shift + bcc !+ + inc RESHO+0 +!: + lda FAC1_mantissa+2 + jsr mul_FAC2_FAC1_by_A + jsr mul_FAC2_FAC1_shift + bcc !+ + inc RESHO+0 +!: + lda FAC1_mantissa+1 + jsr mul_FAC2_FAC1_by_A + jsr mul_FAC2_FAC1_shift + bcc !+ + inc RESHO+0 +!: + lda FAC1_mantissa+0 + jsr mul_FAC2_FAC1_by_A + jsr mul_FAC2_FAC1_shift + bcc !+ + inc RESHO+0 +!: + // Copy RESHO to FAC1 mantissa + + lda RESHO+4 + sta FACOV + lda RESHO+3 + sta FAC1_mantissa+3 + lda RESHO+2 + sta FAC1_mantissa+2 + lda RESHO+1 + sta FAC1_mantissa+1 + lda RESHO+0 + sta FAC1_mantissa+0 + + // Correct the exponent + + lda FAC1_exponent + clc + adc #$08 + bcs_16 set_FAC1_max // branch if overflow + sta FAC1_exponent + jmp normal_FAC1 + +mul_FAC2_FAC1_by_A: + + beq mul_FAC2_FAC1_by_A_done + sta INDEX+3 + + // Multiply FAC2_mantissa+3 + + lda FAC2_mantissa+3 + jsr mul_FAC2_FAC1_8x8 + + adc RESHO+4 + sta RESHO+4 + txa + adc RESHO+3 + sta RESHO+3 + bcc !+ + inc RESHO+2 + bne !+ + inc RESHO+1 + bne !+ + inc RESHO+0 +!: + // Multiply FAC2_mantissa+2 + + lda FAC2_mantissa+2 + jsr mul_FAC2_FAC1_8x8 + + adc RESHO+3 + sta RESHO+3 + txa + adc RESHO+2 + sta RESHO+2 + bcc !+ + inc RESHO+1 + bne !+ + inc RESHO+0 +!: + // Multiply FAC2_mantissa+1 + + lda FAC2_mantissa+1 + jsr mul_FAC2_FAC1_8x8 + + adc RESHO+2 + sta RESHO+2 + txa + adc RESHO+1 + sta RESHO+1 + bcc !+ + inc RESHO+0 +!: + // Multiply FAC2_mantissa+0 + + lda FAC2_mantissa+0 + jsr mul_FAC2_FAC1_8x8 + adc RESHO+1 + sta RESHO+1 + txa + adc RESHO+0 + sta RESHO+0 + + // FALLTROUGH + +mul_FAC2_FAC1_by_A_done: rts diff --git a/c64/basic/math/mul_FAC2_FAC1_8x8.s b/c64/basic/math/mul_FAC2_FAC1_8x8.s new file mode 100644 index 00000000..aa903e0d --- /dev/null +++ b/c64/basic/math/mul_FAC2_FAC1_8x8.s @@ -0,0 +1,77 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine, based on code by djmips from: +// - https://codebase64.org/doku.php?id=base:8bit_multiplication_16bit_product_fast_no_tables +// +// input: .A (and Zero flag set according to .A), INDEX+3 +// output: .X (high byte), .A (low byte), carry always clear +// + +mul_FAC2_FAC1_8x8: + + // Special case (optimization) - handle 0 in INDEX+2 + beq mul_FAC2_FAC1_8x8_zero + + sta INDEX+2 + lda #$00 + + dec INDEX+3 // decrement because we will be adding with carry set for speed (an extra one) + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + bcc !+ + adc INDEX+3 +!: + ror + ror INDEX+2 + inc INDEX+3 + + tax + lda INDEX+2 + + clc + rts + +mul_FAC2_FAC1_8x8_zero: + + lda #$00 + tax + + clc + rts diff --git a/c64/basic/math/mul_FAC2_FAC1_shift.s b/c64/basic/math/mul_FAC2_FAC1_shift.s new file mode 100644 index 00000000..6aed5169 --- /dev/null +++ b/c64/basic/math/mul_FAC2_FAC1_shift.s @@ -0,0 +1,46 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Shift RESHO by one byte - for multiplication +// + +mul_FAC2_FAC1_shift: + + // Check if rounding is needed + + php + clc + lda RESHO+4 + bpl !+ + sec +!: + // Copy bytes + + lda RESHO+3 + sta RESHO+4 + lda RESHO+2 + sta RESHO+3 + lda RESHO+1 + sta RESHO+2 + lda RESHO+0 + sta RESHO+1 + lda #$00 + sta RESHO+0 + bcc !+ + + // Perform rounding + + inc RESHO+4 + bne !+ + inc RESHO+3 + bne !+ + inc RESHO+2 + bne !+ + inc RESHO+1 + bne !+ + inc RESHO+0 +!: + plp + rts diff --git a/c64/basic/math/muldiv_RESHO_helpers.s b/c64/basic/math/muldiv_RESHO_helpers.s new file mode 100644 index 00000000..7f73037f --- /dev/null +++ b/c64/basic/math/muldiv_RESHO_helpers.s @@ -0,0 +1,30 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Math package - helper routines for RESHO manipulation +// + + +muldiv_RESHO_set_0: + + lda #$00 + sta RESHO+0 + sta RESHO+1 + sta RESHO+2 + sta RESHO+3 + sta RESHO+4 + + rts + + +muldiv_RESHO_01_add_A: + + clc + adc RESHO+0 + sta RESHO+0 + bcc !+ + inc RESHO+1 +!: + rts diff --git a/c64/basic/math/normal_FAC1.s b/c64/basic/math/normal_FAC1.s index 5dc96fa5..5c0cc405 100644 --- a/c64/basic/math/normal_FAC1.s +++ b/c64/basic/math/normal_FAC1.s @@ -44,8 +44,7 @@ normal_FAC1_by_bit: // Multiply the mantissa by 2 - clc - rol FACOV + asl FACOV rol FAC1_mantissa+3 rol FAC1_mantissa+2 rol FAC1_mantissa+1 diff --git a/c64/basic/math/bba2.interop b/c64/basic/math_mov/bba2.interop similarity index 100% rename from c64/basic/math/bba2.interop rename to c64/basic/math_mov/bba2.interop diff --git a/c64/basic/math/bba2.mov_MEM_FAC1.jmp.s b/c64/basic/math_mov/bba2.mov_MEM_FAC1.jmp.s similarity index 100% rename from c64/basic/math/bba2.mov_MEM_FAC1.jmp.s rename to c64/basic/math_mov/bba2.mov_MEM_FAC1.jmp.s diff --git a/c64/basic/math/bbc7.interop b/c64/basic/math_mov/bbc7.interop similarity index 100% rename from c64/basic/math/bbc7.interop rename to c64/basic/math_mov/bbc7.interop diff --git a/c64/basic/math/bbc7.mov_r_FAC1_TMP2.s b/c64/basic/math_mov/bbc7.mov_r_FAC1_TMP2.s similarity index 100% rename from c64/basic/math/bbc7.mov_r_FAC1_TMP2.s rename to c64/basic/math_mov/bbc7.mov_r_FAC1_TMP2.s diff --git a/c64/basic/math/bbca.interop b/c64/basic/math_mov/bbca.interop similarity index 100% rename from c64/basic/math/bbca.interop rename to c64/basic/math_mov/bbca.interop diff --git a/c64/basic/math/bbca.mov_r_FAC1_TMP1.s b/c64/basic/math_mov/bbca.mov_r_FAC1_TMP1.s similarity index 100% rename from c64/basic/math/bbca.mov_r_FAC1_TMP1.s rename to c64/basic/math_mov/bbca.mov_r_FAC1_TMP1.s diff --git a/c64/basic/math/bbd0.interop b/c64/basic/math_mov/bbd0.interop similarity index 100% rename from c64/basic/math/bbd0.interop rename to c64/basic/math_mov/bbd0.interop diff --git a/c64/basic/math/bbd0.mov_r_FAC1_VAR.s b/c64/basic/math_mov/bbd0.mov_r_FAC1_VAR.s similarity index 100% rename from c64/basic/math/bbd0.mov_r_FAC1_VAR.s rename to c64/basic/math_mov/bbd0.mov_r_FAC1_VAR.s diff --git a/c64/basic/math/bbd4.interop b/c64/basic/math_mov/bbd4.interop similarity index 100% rename from c64/basic/math/bbd4.interop rename to c64/basic/math_mov/bbd4.interop diff --git a/c64/basic/math/bbd4.mov_r_FAC1_MEM.s b/c64/basic/math_mov/bbd4.mov_r_FAC1_MEM.s similarity index 100% rename from c64/basic/math/bbd4.mov_r_FAC1_MEM.s rename to c64/basic/math_mov/bbd4.mov_r_FAC1_MEM.s diff --git a/c64/basic/math/bbfc.interop b/c64/basic/math_mov/bbfc.interop similarity index 100% rename from c64/basic/math/bbfc.interop rename to c64/basic/math_mov/bbfc.interop diff --git a/c64/basic/math/bbfc.mov_FAC2_FAC1.s b/c64/basic/math_mov/bbfc.mov_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/bbfc.mov_FAC2_FAC1.s rename to c64/basic/math_mov/bbfc.mov_FAC2_FAC1.s diff --git a/c64/basic/math/bc0c.interop b/c64/basic/math_mov/bc0c.interop similarity index 100% rename from c64/basic/math/bc0c.interop rename to c64/basic/math_mov/bc0c.interop diff --git a/c64/basic/math/bc0c.mov_r_FAC1_FAC2.s b/c64/basic/math_mov/bc0c.mov_r_FAC1_FAC2.s similarity index 100% rename from c64/basic/math/bc0c.mov_r_FAC1_FAC2.s rename to c64/basic/math_mov/bc0c.mov_r_FAC1_FAC2.s diff --git a/c64/basic/math/bc0f.interop b/c64/basic/math_mov/bc0f.interop similarity index 100% rename from c64/basic/math/bc0f.interop rename to c64/basic/math_mov/bc0f.interop diff --git a/c64/basic/math/bc0f.mov_FAC1_FAC2.jmp.s b/c64/basic/math_mov/bc0f.mov_FAC1_FAC2.jmp.s similarity index 100% rename from c64/basic/math/bc0f.mov_FAC1_FAC2.jmp.s rename to c64/basic/math_mov/bc0f.mov_FAC1_FAC2.jmp.s diff --git a/c64/basic/math/mov_FAC1_FAC2.s b/c64/basic/math_mov/mov_FAC1_FAC2.s similarity index 100% rename from c64/basic/math/mov_FAC1_FAC2.s rename to c64/basic/math_mov/mov_FAC1_FAC2.s diff --git a/c64/basic/math/mov_FAC1_MEM.s b/c64/basic/math_mov/mov_FAC1_MEM.s similarity index 100% rename from c64/basic/math/mov_FAC1_MEM.s rename to c64/basic/math_mov/mov_FAC1_MEM.s diff --git a/c64/basic/math/mov_FAC2_FAC1.s b/c64/basic/math_mov/mov_FAC2_FAC1.s similarity index 100% rename from c64/basic/math/mov_FAC2_FAC1.s rename to c64/basic/math_mov/mov_FAC2_FAC1.s diff --git a/c64/basic/math/mov_MEM_FAC1.s b/c64/basic/math_mov/mov_MEM_FAC1.s similarity index 100% rename from c64/basic/math/mov_MEM_FAC1.s rename to c64/basic/math_mov/mov_MEM_FAC1.s diff --git a/c64/basic/math/mov_MEM_FAC2.s b/c64/basic/math_mov/mov_MEM_FAC2.s similarity index 100% rename from c64/basic/math/mov_MEM_FAC2.s rename to c64/basic/math_mov/mov_MEM_FAC2.s diff --git a/c64/basic/math/mov_r_FAC1_TMP1.s b/c64/basic/math_mov/mov_r_FAC1_TMP1.s similarity index 100% rename from c64/basic/math/mov_r_FAC1_TMP1.s rename to c64/basic/math_mov/mov_r_FAC1_TMP1.s diff --git a/c64/basic/math/mov_r_FAC1_TMP2.s b/c64/basic/math_mov/mov_r_FAC1_TMP2.s similarity index 100% rename from c64/basic/math/mov_r_FAC1_TMP2.s rename to c64/basic/math_mov/mov_r_FAC1_TMP2.s diff --git a/c64/basic/pack_word.s b/c64/basic/pack_word.s index 5b8e502e..d975ca38 100644 --- a/c64/basic/pack_word.s +++ b/c64/basic/pack_word.s @@ -1,5 +1,6 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // Pack a word using the simple compression scheme. diff --git a/c64/basic/print/list_single_line.s b/c64/basic/print/list_single_line.s new file mode 100644 index 00000000..64e6b2b4 --- /dev/null +++ b/c64/basic/print/list_single_line.s @@ -0,0 +1,134 @@ +// #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_integer.s b/c64/basic/print/print_integer.s similarity index 100% rename from c64/basic/print_integer.s rename to c64/basic/print/print_integer.s diff --git a/c64/basic/print_packed_message.s b/c64/basic/print/print_packed_message.s similarity index 94% rename from c64/basic/print_packed_message.s rename to c64/basic/print/print_packed_message.s index 8aba8b25..7a062e6a 100644 --- a/c64/basic/print_packed_message.s +++ b/c64/basic/print/print_packed_message.s @@ -1,5 +1,6 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# M65 * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // This routine prints messages that have been packed @@ -17,6 +18,14 @@ 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: @@ -230,3 +239,6 @@ is_uncommon_char: phy_trash_a jmp has_nybl + + +#endif // ROM layout diff --git a/c64/basic/ready_message.s b/c64/basic/ready_message.s index 791cb7eb..9d528c38 100644 --- a/c64/basic/ready_message.s +++ b/c64/basic/ready_message.s @@ -4,7 +4,6 @@ ready_message: - // See src/make_error_tables.c for packed message handling - // information. + ldx #29 jmp print_packed_message diff --git a/c64/basic/tokenise_line.s b/c64/basic/tokenise_line.s index 0c54eed7..0678658b 100644 --- a/c64/basic/tokenise_line.s +++ b/c64/basic/tokenise_line.s @@ -1,5 +1,6 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# M65 * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE // Tokenise a line of BASIC @@ -8,6 +9,14 @@ 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. @@ -270,3 +279,5 @@ done_searching_for_token: sec lda #$00 rts + +#endif // ROM layout diff --git a/c64/kernal/assets/kernal_messages.s b/c64/kernal/assets/kernal_messages.s index 3808770d..3c876dc9 100644 --- a/c64/kernal/assets/kernal_messages.s +++ b/c64/kernal/assets/kernal_messages.s @@ -21,6 +21,9 @@ #if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO .label __MSG_KERNAL_PRESS_PLAY = __msg_kernalplay - __msg_kernal_first .label __MSG_KERNAL_FOUND = __msg_kernalfound - __msg_kernal_first +#if CONFIG_MB_MEGA_65 +.label __MSG_KERNAL_OK_SEARCHING = __msg_kernaloksearching - __msg_kernal_first +#endif #endif #if CONFIG_SHOW_PAL_NTSC @@ -78,6 +81,16 @@ __msg_kernalfound: .text "FOUND" .byte $80 + $20 // end of string mark + space +#if CONFIG_MB_MEGA_65 + +__msg_kernaloksearching: + .text "OK" + .byte $0D, $0D + .text "SEARCHIN" + .byte $80 + $47 // end of string mark + 'G' + +#endif + #endif #if CONFIG_SHOW_PAL_NTSC diff --git a/c64/kernal/board_m65/mega65_imports.s b/c64/kernal/board_m65/mega65_imports.s index d06b0bdb..e09cabb0 100644 --- a/c64/kernal/board_m65/mega65_imports.s +++ b/c64/kernal/board_m65/mega65_imports.s @@ -25,8 +25,7 @@ #if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO -.label screen_on = KERNAL_0.screen_on -.label screen_off = KERNAL_0.screen_off +.label mega65_unhide = KERNAL_0.mega65_unhide .label tape_motor_on = KERNAL_0.tape_motor_on .label tape_motor_off = KERNAL_0.tape_motor_off @@ -45,6 +44,7 @@ .label print_return = KERNAL_0.proxy_K1_print_return .label __MSG_KERNAL_PRESS_PLAY = KERNAL_0.__MSG_KERNAL_PRESS_PLAY +.label __MSG_KERNAL_OK_SEARCHING = KERNAL_0.__MSG_KERNAL_OK_SEARCHING .label __MSG_KERNAL_FOUND = KERNAL_0.__MSG_KERNAL_FOUND #endif diff --git a/c64/kernal/board_m65/mega65_tape_normal_byte_store.s b/c64/kernal/board_m65/mega65_tape_normal_byte_store.s index 4c8cc13f..ae641f34 100644 --- a/c64/kernal/board_m65/mega65_tape_normal_byte_store.s +++ b/c64/kernal/board_m65/mega65_tape_normal_byte_store.s @@ -2,7 +2,7 @@ // #LAYOUT# * * #IGNORE // -// Tape (normal) helper routine - byte storage when ban changing is needed +// Tape (normal) helper routine - byte storage when banking change is needed // diff --git a/c64/kernal/board_m65/mega65_unhide.s b/c64/kernal/board_m65/mega65_unhide.s new file mode 100644 index 00000000..3fa9b1c9 --- /dev/null +++ b/c64/kernal/board_m65/mega65_unhide.s @@ -0,0 +1,24 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# X16 * #IGNORE +// #LAYOUT# * KERNAL_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Routine to unhide Mega65 extra registers +// + + +#if CONFIG_KEYBOARD_C65 || (CONFIG_MB_MEGA_65 && (CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO)) + + +mega65_unhide: + + lda #$A5 + sta VIC_KEY + lda #$96 + sta VIC_KEY + + rts + + +#endif diff --git a/c64/kernal/errors.s b/c64/kernal/errors.s index e1642238..e7bc9547 100644 --- a/c64/kernal/errors.s +++ b/c64/kernal/errors.s @@ -75,6 +75,17 @@ kernalerror_ILLEGAL_DEVICE_NUMBER: // FALLTROUGH +#if CONFIG_IEC_JIFFYDOS + +kernalerror_IEC_TIMEOUT_READ: + + lda #K_STS_TIMEOUT_READ + skip_2_bytes_trash_nvz + + // FALLTROUGH + +#endif // CONFIG_IEC_JIFFYDOS + kernalerror_TOP_MEM_RS232: lda #K_ERR_TOP_MEM_RS232 diff --git a/c64/kernal/iec_fast/jiffydos_load.s b/c64/kernal/iec_fast/jiffydos_load.s index 0fc3a11b..f8487e42 100644 --- a/c64/kernal/iec_fast/jiffydos_load.s +++ b/c64/kernal/iec_fast/jiffydos_load.s @@ -6,7 +6,6 @@ // JiffyDOS protocol support for IEC - optimized load loop // - #if CONFIG_IEC_JIFFYDOS && !CONFIG_MEMORY_MODEL_60K @@ -20,12 +19,15 @@ jiffydos_load: + // XXX implement JiffyDOS optimized LOAD protocol, this one is ineffective + + // Timing is critical, do not allow interrupts sei #if CONFIG_IEC_JIFFYDOS_BLANK - // Preserve register with screen status (blank/visibe) + // Preserve register with screen status (blank/visible) lda VIC_SCROLY sta TBTCNT diff --git a/c64/kernal/iec_fast/jiffydos_rx_byte.s b/c64/kernal/iec_fast/jiffydos_rx_byte.s index 13406df8..01473045 100644 --- a/c64/kernal/iec_fast/jiffydos_rx_byte.s +++ b/c64/kernal/iec_fast/jiffydos_rx_byte.s @@ -86,8 +86,11 @@ jiffydos_rx_byte: // If CLK line active - success bvc jiffydos_rx_byte_end - // XXX the DATA line can probably be used to distinguish between file not found error and normal stream EOI + // EOI or error, released DATA (highest byte set to 1) means error - see protocol analysis by Michael Steil, step R7a + lda CIA2_PRA + bmi jiffydos_rx_byte_error + // EOI - no error jsr kernalstatus_EOI // FALLTROUGH @@ -109,5 +112,10 @@ jiffydos_rx_byte_end: // End byte reception jmp iec_rx_end +jiffydos_rx_byte_error: + + jsr kernalerror_IEC_TIMEOUT_READ + bcs jiffydos_rx_byte_end // branch always + #endif // CONFIG_IEC_JIFFYDOS diff --git a/c64/kernal/iec_fast/jiffydos_tx_byte.s b/c64/kernal/iec_fast/jiffydos_tx_byte.s index d600cc3f..e3ddcd06 100644 --- a/c64/kernal/iec_fast/jiffydos_tx_byte.s +++ b/c64/kernal/iec_fast/jiffydos_tx_byte.s @@ -100,6 +100,11 @@ jiffydos_tx_byte_wait_eoi: sta CIA2_PRA jsr iec_wait20us lda C3PO + + // According to protocol analysis by Michael Steil (step S8) we should pull the DATA here + // to signal there was no error; but DATA pulled by the controller is a normal state + // (which should be stored in C3PO), so there is nothing to do here. + jmp jiffydos_tx_byte_finalize diff --git a/c64/kernal/init/fce2.hw_entry_reset.s b/c64/kernal/init/fce2.hw_entry_reset.s index 0d36a2d6..2ada16d4 100644 --- a/c64/kernal/init/fce2.hw_entry_reset.s +++ b/c64/kernal/init/fce2.hw_entry_reset.s @@ -11,10 +11,16 @@ hw_entry_reset: // The GPL program at https://github.com/Klaus2m5/6502_65C02_functional_tests/blob/master/6502_functional_test.a65 // uses the similar initial reset sequence, affirmed by c64 PRG p269 - sei // disable the interrupts, as fast as possible - they are disabled in case of HW reset, - // but this routine can be also called manually + sei // disable the interrupts, as fast as possible - they are disabled in case of HW reset, + // but this routine can be also called manually - cld // required for all CPUs - due to possibility of manual call + cld // required for all CPUs - due to possibility of manual call + +#if HAS_OPCODES_65CE02 + + see // disable extended stack + +#endif ldx #$FF txs diff --git a/c64/kernal/init/fda3.ioinit.s b/c64/kernal/init/fda3.ioinit.s index 35d07223..9e67a661 100644 --- a/c64/kernal/init/fda3.ioinit.s +++ b/c64/kernal/init/fda3.ioinit.s @@ -59,10 +59,12 @@ IOINIT: // Now silence the SID chip(s), depending on the configuration - we want them silent ASAP // - // First the standard chip (skip if it is covered by whole $D4XX range) - lda #$00 +#if !CONFIG_MB_MEGA_65 + + // First the standard chip (skip if it is covered by whole $D4XX range) + #if !CONFIG_SID_D4XX sta SID_SIGVOL #endif // !CONFIG_SID_D4XX @@ -100,6 +102,17 @@ IOINIT: #endif // CONFIG_SID_D4XX || CONFIG_SID_D5XX +#else + + // Mega65 specific handling - it contains 4 SIDs + + sta SID_SIGVOL + __SID_R1_OFFSET + sta SID_SIGVOL + __SID_R2_OFFSET + sta SID_SIGVOL + __SID_L1_OFFSET + sta SID_SIGVOL + __SID_L2_OFFSET + +#endif // CONFIG_MB_MEGA_65 + // // Now continue the CIAs initialization // diff --git a/c64/kernal/interrupts/fe66.default_brk_handler.s b/c64/kernal/interrupts/fe66.default_brk_handler.s index 668462f3..782a0d6b 100644 --- a/c64/kernal/interrupts/fe66.default_brk_handler.s +++ b/c64/kernal/interrupts/fe66.default_brk_handler.s @@ -12,11 +12,17 @@ default_brk_handler: #if CONFIG_PLATFORM_COMMODORE_64 ldx #$00 - sta VIC_SCROLX // turn the display off - we want as little screen artifacts as possible + sta VIC_SCROLX // turn the display off - we want as little screen artifacts as possible #endif - cld // make sure this dangerous flag is disabled + cld // make sure this dangerous flag is disabled + +#if HAS_OPCODES_65CE02 + + see // disable extended stack + +#endif jsr JRESTOR jsr JIOINIT diff --git a/c64/kernal/keyboard/scnkey.s b/c64/kernal/keyboard/scnkey.s index 12161598..ae1421ff 100644 --- a/c64/kernal/keyboard/scnkey.s +++ b/c64/kernal/keyboard/scnkey.s @@ -48,14 +48,10 @@ SCNKEY: // mode when done. This is not ideal, but as MEGA65s start C65 mode with VIC-IV IO mode // selected anyway, it should not be a big problem in practice. - lda #$A5 - sta VIC_KEY - lda #$96 - sta VIC_KEY - + jsr mega65_unhide jsr scnkey_viciv_mode - sta VIC_KEY + sta VIC_KEY // hide Mega65 registers rts scnkey_viciv_mode: diff --git a/c64/kernal/screen/screen_off.s b/c64/kernal/screen/screen_off.s index f7ef6d62..133127a3 100644 --- a/c64/kernal/screen/screen_off.s +++ b/c64/kernal/screen/screen_off.s @@ -8,7 +8,7 @@ // -#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO || (CONFIG_IEC_JIFFYDOS && !CONFIG_MEMORY_MODEL_60K) +#if ((CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO) && !CONFIG_MB_MEGA_65) || (CONFIG_IEC_JIFFYDOS && !CONFIG_MEMORY_MODEL_60K) screen_off: diff --git a/c64/kernal/screen/screen_on.s b/c64/kernal/screen/screen_on.s index 6d49d4a4..22853c22 100644 --- a/c64/kernal/screen/screen_on.s +++ b/c64/kernal/screen/screen_on.s @@ -8,7 +8,7 @@ // -#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO +#if (CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO) && !CONFIG_MB_MEGA_65 screen_on: @@ -19,4 +19,5 @@ screen_on: rts + #endif diff --git a/c64/kernal/tape/tape_common.s b/c64/kernal/tape/tape_common.s index 94d125b0..fa813aef 100644 --- a/c64/kernal/tape/tape_common.s +++ b/c64/kernal/tape/tape_common.s @@ -61,15 +61,40 @@ tape_wait_play_loop: #else + // The ROM is configured for tape adapter without the key sense - but it is still + // possible, that regular Datasette or Tapuino is connected + + lda CPU_R6510 + and #$10 + beq tape_wait_first_pulse // branch if button reported pressed, most likely really no key sense + + // We have key sense - perform regular waiting +!: + jsr STOP + bcs tape_break_error + + lda CPU_R6510 + and #$10 + beq !- + +tape_wait_first_pulse: + // We have no key sense - so just turn the motor on and wait for the first pulse jsr tape_motor_on - lda #$10 !: + jsr STOP + bcs tape_break_error + + lda #$10 bit CIA1_ICR // $DC0D bne !- !: + jsr STOP + bcs tape_break_error + + lda #$10 bit CIA1_ICR // $DC0D beq !- @@ -79,6 +104,15 @@ tape_wait_play_loop: tape_wait_play_done: +#if CONFIG_MB_MEGA_65 + + // Display confirmation + + ldx #__MSG_KERNAL_OK_SEARCHING + jsr print_kernal_message + +#endif + // Prepare for reading lda #$01 diff --git a/c64/kernal/tape/tape_common_autodetect.s b/c64/kernal/tape/tape_common_autodetect.s index 5ea9aebe..bad0c45e 100644 --- a/c64/kernal/tape/tape_common_autodetect.s +++ b/c64/kernal/tape/tape_common_autodetect.s @@ -17,7 +17,12 @@ tape_common_autodetect: lda #$0B sta VIC_EXTCOL lda #$00 +#if CONFIG_MB_MEGA_65 + sta SID_SIGVOL + __SID_R1_OFFSET + sta SID_SIGVOL + __SID_L1_OFFSET +#else sta SID_SIGVOL +#endif // FALLTROUGH diff --git a/c64/kernal/tape/tape_common_clean_sid.s b/c64/kernal/tape/tape_common_clean_sid.s index a320faef..41083007 100644 --- a/c64/kernal/tape/tape_common_clean_sid.s +++ b/c64/kernal/tape/tape_common_clean_sid.s @@ -15,7 +15,22 @@ tape_clean_sid: lda #$00 ldy #$1C !: + +#if CONFIG_MB_MEGA_65 + + // It should be safer than cleaning whole $D400-D47C range + + sta __SID_BASE + __SID_R1_OFFSET, y + sta __SID_BASE + __SID_R2_OFFSET, y + sta __SID_BASE + __SID_L1_OFFSET, y + sta __SID_BASE + __SID_L2_OFFSET, y + +#else + sta __SID_BASE, y + +#endif + dey bpl !- diff --git a/c64/kernal/tape/tape_common_screen.s b/c64/kernal/tape/tape_common_screen.s index aaf7a150..19264dee 100644 --- a/c64/kernal/tape/tape_common_screen.s +++ b/c64/kernal/tape/tape_common_screen.s @@ -11,6 +11,9 @@ #if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO +// XXX for Mega65 do not disable screen, just disable badline emulation + + tape_screen_on_motor_off: jsr tape_motor_off @@ -18,8 +21,23 @@ tape_screen_on_motor_off: lda COLSTORE sta VIC_EXTCOL +#if !CONFIG_MB_MEGA_65 + jmp screen_on +#else + + // On Mega65 just reenable badline emulation + + lda #$FF + sta M65_BADL_SLI + sta VIC_KEY + + rts + +#endif + + tape_screen_off_motor_on: // We do not want interrupts and CHROUT reenables them @@ -33,7 +51,22 @@ tape_screen_off_motor_on: lda VIC_EXTCOL sta COLSTORE +#if !CONFIG_MB_MEGA_65 + jsr screen_off + +#else + + // On Mega65 we do not have to turn the screen off; + // it is enough to disable badline emulation + + jsr mega65_unhide + lda #$00 + sta M65_BADL_SLI + +#endif + + jmp tape_motor_on #endif diff --git a/c64/kernal/tape/tape_turbo_get_bit.s b/c64/kernal/tape/tape_turbo_get_bit.s index a903a4d5..d2cf4f6a 100644 --- a/c64/kernal/tape/tape_turbo_get_bit.s +++ b/c64/kernal/tape/tape_turbo_get_bit.s @@ -23,7 +23,12 @@ tape_turbo_get_bit: sta __turbo_half_S // store half of the last measurement result for short pulse lda #$01 +#if CONFIG_MB_MEGA_65 + sta SID_SIGVOL + __SID_R1_OFFSET + sta SID_SIGVOL + __SID_L1_OFFSET +#else sta SID_SIGVOL +#endif lda #$06 sta VIC_EXTCOL sec @@ -34,7 +39,12 @@ tape_turbo_get_bit: sta __turbo_half_L // store half of the last measurement result for long pulse lda #$00 +#if CONFIG_MB_MEGA_65 + sta SID_SIGVOL + __SID_R1_OFFSET + sta SID_SIGVOL + __SID_L1_OFFSET +#else sta SID_SIGVOL +#endif sta VIC_EXTCOL clc rts diff --git a/doc/Development.md b/doc/Development.md index 68cd49c6..bc4c8ad7 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -59,6 +59,11 @@ 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). +#### 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: + +- Slightly different chargen. On C64 machines pressing C= + G or C= + M key combinations produces the same visual result as C= + H or C= + N, respectively - despite keycap printing suggests they should produce tinner bars. This was intentional change in the C64 ROMs (compared to VIC-20), to prevent colour problems on 80s era TVs. Screen font used in the legacy mode duplicates this change, but the font intended for native mode has this change reverted back. Additionally, the π sign is available for lower/upper case set too. ## Tinkering with OpenROMs diff --git a/strings/02A90160 b/strings/02A90160 new file mode 100644 index 00000000..e968c27e --- /dev/null +++ b/strings/02A90160 @@ -0,0 +1,3 @@ +$02 + LDA #$01 + RTS + +End of subroutine putting $01 into accumulator + some part. Trivial - not copyrightable. diff --git a/strings/066D266C266B266A b/strings/066D266C266B266A new file mode 100644 index 00000000..02122454 --- /dev/null +++ b/strings/066D266C266B266A @@ -0,0 +1,3 @@ +ASL $6D + ROL $6C + ROL $6B + ROL $6A + +Arithmetic shift left of 32-bit value. Trivial - not copyrightable. diff --git a/strings/06702665266426632662 b/strings/06702665266426632662 new file mode 100644 index 00000000..4706747d --- /dev/null +++ b/strings/06702665266426632662 @@ -0,0 +1,3 @@ +ASL $70 + ROL $65 + ROL $64 + ROL $63 + ROL $62 + +Arithmetic shift left of 40-bit value. Trivial - not copyrightable. diff --git a/strings/06E6A1D0 b/strings/06E6A1D0 new file mode 100644 index 00000000..1130f260 --- /dev/null +++ b/strings/06E6A1D0 @@ -0,0 +1,3 @@ +$06 + INC $A1 + BNE (offset does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/268562A5 b/strings/268562A5 new file mode 100644 index 00000000..5b20f62c --- /dev/null +++ b/strings/268562A5 @@ -0,0 +1,3 @@ +$26 + STA $62 + LDA (zeropage address does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/26A90085 b/strings/26A90085 new file mode 100644 index 00000000..a6115ffd --- /dev/null +++ b/strings/26A90085 @@ -0,0 +1,3 @@ +$26 + LDA #$00 + STA (zeropage address does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/288529A5 b/strings/288529A5 new file mode 100644 index 00000000..981d1241 --- /dev/null +++ b/strings/288529A5 @@ -0,0 +1,3 @@ +$28 + STA $29 + LDA (zeropage address does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/2CA9022CA9 b/strings/2CA9022CA9 new file mode 100644 index 00000000..35f257c1 --- /dev/null +++ b/strings/2CA9022CA9 @@ -0,0 +1,3 @@ +$2C + LDA #$02 + BIT (to skip 2 bytes) + LDA (value does not match) + +Part of the common 6502 trick to set accumulator value depending on jump address. Not creative - not copyrightable. diff --git a/strings/38E56185 b/strings/38E56185 new file mode 100644 index 00000000..b5a11760 --- /dev/null +++ b/strings/38E56185 @@ -0,0 +1,3 @@ +SEC + SBC $61 + STA (zeropage address does not match) + +Small piece of code subtracting two values. Trivial -not copyrightable. diff --git a/strings/4C67B820 b/strings/4C67B820 new file mode 100644 index 00000000..e6a66941 --- /dev/null +++ b/strings/4C67B820 @@ -0,0 +1,3 @@ +JMP $B867 + JSR (address does not match) + +Jump to a well-known routine + some part. Trivial - not copyrightable. diff --git a/strings/4C6AB820 b/strings/4C6AB820 new file mode 100644 index 00000000..2e7d4182 --- /dev/null +++ b/strings/4C6AB820 @@ -0,0 +1,3 @@ +JMP $B86A + JSR (address does not match) + +Jump to a well-known routine + some part. Trivial - not copyrightable. diff --git a/strings/61F006A566 b/strings/61F006A566 new file mode 100644 index 00000000..65dfe904 --- /dev/null +++ b/strings/61F006A566 @@ -0,0 +1,3 @@ +$61 + BEQ (offset matches) + LDA $66 + +Conditional jump + retrieving zeropage variable + part of one more instruction. Trivial - not copyrightable. diff --git a/strings/666366646665 b/strings/666366646665 new file mode 100644 index 00000000..97516ea2 --- /dev/null +++ b/strings/666366646665 @@ -0,0 +1,3 @@ +ROR $63 + ROR $64 + ROR $65 + +Rotating right a multi-byte value. Trivial - not copyrightable. diff --git a/strings/6BE56385 b/strings/6BE56385 new file mode 100644 index 00000000..f7b25ef9 --- /dev/null +++ b/strings/6BE56385 @@ -0,0 +1,3 @@ +$6B + STA $6D + LDA (zeropage address does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/7060A561F0 b/strings/7060A561F0 new file mode 100644 index 00000000..561705f1 --- /dev/null +++ b/strings/7060A561F0 @@ -0,0 +1,3 @@ +$70 + RTS + LDA $61 + BEQ (offset does not match) + +Jump depending whether zeropage variable is 0 or not + some small part (return + a byte) of previous routine. Trivial - not copyrightable. diff --git a/strings/8526852785288529 b/strings/8526852785288529 new file mode 100644 index 00000000..0b810b27 --- /dev/null +++ b/strings/8526852785288529 @@ -0,0 +1,3 @@ +STA $26 + STA $27 + STA $28 + STA $29 + +Part of code clearing 32-bit value. Trivial - not copyrightable. diff --git a/strings/A420D2FF b/strings/A420D2FF new file mode 100644 index 00000000..66609749 --- /dev/null +++ b/strings/A420D2FF @@ -0,0 +1,3 @@ +$A4 + JSR $FFD2 + +Call of a documented routine + some part. Trivial - not copyrightable. diff --git a/strings/A5278563A5 b/strings/A5278563A5 new file mode 100644 index 00000000..a1423910 --- /dev/null +++ b/strings/A5278563A5 @@ -0,0 +1,3 @@ +LDA $27 + STA $63 + LDA (zeropage address does not match) + +Part of code copying one floating point value to anotheer one. Trivial - not copyrightable. diff --git a/strings/A5288564A5 b/strings/A5288564A5 new file mode 100644 index 00000000..4149d6f3 --- /dev/null +++ b/strings/A5288564A5 @@ -0,0 +1,3 @@ +LDA $28 + STA $64 + LDA (zeropage address does not match) + +Part of code copying one floating point value to anotheer one. Trivial - not copyrightable. diff --git a/strings/A5298565 b/strings/A5298565 new file mode 100644 index 00000000..301d0212 --- /dev/null +++ b/strings/A5298565 @@ -0,0 +1,3 @@ +LDA $29 + STA $65 + +Part of code copying one floating point value to anotheer one. Trivial - not copyrightable. diff --git a/strings/A561F0FB b/strings/A561F0FB new file mode 100644 index 00000000..4c9abe4f --- /dev/null +++ b/strings/A561F0FB @@ -0,0 +1,3 @@ +LDA $61 + BEQ (offset matches) + +Jump depending whether zeropage variable is 0 or not. Trivial - not copyrightable. diff --git a/strings/A569D0034C b/strings/A569D0034C new file mode 100644 index 00000000..998098c2 --- /dev/null +++ b/strings/A569D0034C @@ -0,0 +1,3 @@ +LDA $69 + BNE (skip the JMP) + JMP (address does not match) + +Far jump (address does not match) depending whether zeropage variable is 0 or not. Trivial - not copyrightable. diff --git a/strings/B7A000B1 b/strings/B7A000B1 new file mode 100644 index 00000000..6c9dd366 --- /dev/null +++ b/strings/B7A000B1 @@ -0,0 +1,3 @@ +$B7 + LDY #$00 + LDA (...), Y (zeropage address does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/E0A90085 b/strings/E0A90085 new file mode 100644 index 00000000..5a60cbc6 --- /dev/null +++ b/strings/E0A90085 @@ -0,0 +1,3 @@ +$E0 + LDA #$00 + STA (zeropage address does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/E220C0FFB0 b/strings/E220C0FFB0 new file mode 100644 index 00000000..4e52ecef --- /dev/null +++ b/strings/E220C0FFB0 @@ -0,0 +1,3 @@ +$E2 + JSR $FFC0 + BCS (offset does not match) + +Call of a documented routine + some parts. Trivial - not copyrightable. diff --git a/strings/F006A56649FF8566608138AA3B29 b/strings/F006A56649FF8566608138AA3B29 new file mode 100644 index 00000000..783d54ed --- /dev/null +++ b/strings/F006A56649FF8566608138AA3B29 @@ -0,0 +1,3 @@ +BEQ (offset matches) + LDA $66 + EOR #$FF + STA $66 + RTS + floating point constant 1.0 / log_e(2.0) + +Most of a trivial routine to toggle floating point variable sign + floating point constant (generated by a special tool). The addresses has to remain as they are for compatibility. Not creative - not copyrightable. diff --git a/strings/FF20BBEE b/strings/FF20BBEE new file mode 100644 index 00000000..cf8be179 --- /dev/null +++ b/strings/FF20BBEE @@ -0,0 +1,3 @@ +$FF + JSR $EEBB + +Instruction + some part. Trivial - not copyrightable. diff --git a/tools/compress_text.c b/tools/compress_text.c index fcfc7dca..6f7b0daf 100644 --- a/tools/compress_text.c +++ b/tools/compress_text.c @@ -436,15 +436,16 @@ int main(void) exit(-1); } - printf("packed_message_chars:\n"); + printf(".macro put_packed_chars()\n{\n"); for(int i=0;i=8) { @@ -455,8 +456,9 @@ int main(void) } else printf("\t.byte $%02x\n",message_tokens[i]); } - - printf("packed_message_words:\n"); + printf("}\n"); + + printf(".macro put_packed_words()\n{\n"); for(int i=0;i=8) { @@ -467,8 +469,9 @@ int main(void) } else printf("\t.byte $%02x\n",packed_words[i]); } + printf("}\n"); - printf("packed_keywords:\n"); + printf(".macro put_packed_keywords()\n{\n"); for(int i=0;i=8) { @@ -479,7 +482,9 @@ int main(void) } else printf("\t.byte $%02x\n",packed_keywords[i]); } - printf("\t.label packed_keyword_table_len = $%X\n",packedkey_len); + printf("}\n"); + + printf(".label packed_keyword_table_len = $%X\n",packedkey_len); fprintf(stderr,"Error list takes %d bytes raw.\n",raw_size); fprintf(stderr,"%d token bytes used to encode all messages.\n",token_count); diff --git a/tools/generate_constants.cc b/tools/generate_constants.cc index 6d27caed..9e45e591 100644 --- a/tools/generate_constants.cc +++ b/tools/generate_constants.cc @@ -57,6 +57,16 @@ std::vector GLOBAL_constants = ConstEntry( "INV_SQR_2", 1.0 / std::sqrt(2.0) ), ConstEntry( "LOG_2", std::log(2.0) ), ConstEntry( "INV_LOG_2", 1.0 / std::log(2.0) ), + + // Constants for sine approximation, minimized abs. error, degree 11, for [0, pi/2], from: + // - https://publik-void.github.io/sin-cos-approximations/ + + ConstEntry( "POLY_SIN_1", -2.3794713545277060334805162803882547e-8 ), + ConstEntry( "POLY_SIN_2", 2.75188556386854406868696924998396177e-6 ), + ConstEntry( "POLY_SIN_3", -0.000198407028626057951892931706291369095 ), + ConstEntry( "POLY_SIN_4", 0.00833332926445715285723741015926085083 ), + ConstEntry( "POLY_SIN_5", -0.166666665414391662957238076832950332 ), + ConstEntry( "POLY_SIN_6", 0.99999999988985190065414932682350994 ), }; // diff --git a/tools/patch_chargen.cc b/tools/patch_chargen.cc new file mode 100644 index 00000000..49bef286 --- /dev/null +++ b/tools/patch_chargen.cc @@ -0,0 +1,144 @@ +// +// Utility to patch the character generator file to create +// font for Mega65 native mode and possibly other uses +// + +#include "common.h" + +#include + +#include +#include + +// +// Command line settings +// + +std::string CMD_inFile = "chargen.rom"; +std::string CMD_outFile = "chargen-native.rom"; +std::string CMD_name = "CHARGEN"; + +// +// Common helper functions +// + +void printUsage() +{ + std::cout << "\n" << + "usage: patch_chargen [-i ] [-o ] [-n name]" << "\n\n"; +} + +void printBanner() +{ + printBannerLineTop(); + std::cout << "// Generating patched font '" << CMD_name << "'" << "\n"; + printBannerLineBottom(); +} + +// +// Top-level functions +// + +void parseCommandLine(int argc, char **argv) +{ + int opt; + + // Retrieve command line options + + while ((opt = getopt(argc, argv, "i:o:n:")) != -1) + { + switch(opt) + { + case 'i': CMD_inFile = optarg; break; + case 'o': CMD_outFile = optarg; break; + case 'n': CMD_name = optarg; break; + default: printUsage(); ERROR(); + } + } +} + +// +// Font processing +// + +void processFont() +{ + std::vector fileContent; + + // Read the source file + + std::ifstream srcFile; + srcFile.open(CMD_inFile, std::ios::in | std::ios::binary | std::ios::ate); + + if (!srcFile.good()) ERROR(std::string("unable to open ROM file '") + CMD_inFile + "'"); + + auto srcSize = srcFile.tellg(); + if (srcSize != 4096) ERROR(std::string("incorrect size of ROM file '") + CMD_inFile + "'"); + + std::vector srcFileContent; + + fileContent.resize(srcSize); + srcFile.seekg (0, srcFile.beg); + srcFile.read((char *) fileContent.data(), fileContent.size()); + + if (!srcFile.good()) ERROR(std::string("unable to read ROM file '") + CMD_inFile + "'"); + srcFile.close(); + + // Patch the font + + for (uint8_t idx = 0; idx < 8; idx++) + { + // VENDOR + M - 2px width on C64 + + fileContent[0x67 * 8 + 0 + idx] = 0b00000001; // normal + fileContent[0x67 * 8 + 2048 + idx] = 0b00000001; // upper/lower case + fileContent[0xE7 * 8 + 0 + idx] = 0b11111110; // inversed + fileContent[0xE7 * 8 + 2048 + idx] = 0b11111110; // upper/lower case, inversed + + // VENDOR + G - 2px width on C64 + + fileContent[0x65 * 8 + 0 + idx] = 0b10000000; // normal + fileContent[0x65 * 8 + 2048 + idx] = 0b10000000; // upper/lower case + fileContent[0xE5 * 8 + 0 + idx] = 0b01111111; // inversed + fileContent[0xE5 * 8 + 2048 + idx] = 0b01111111; // upper/lower case, inversed + + // PI character restoration for upper/lower case set + + fileContent[0x5E * 8 + 2048 + idx] = fileContent[0x5E * 8 + idx]; + fileContent[0xDE * 8 + 2048 + idx] = fileContent[0xDE * 8 + idx]; + } + + // Remove old file + + unlink(CMD_outFile.c_str()); + + // Save the patched font + + std::ofstream outFile(CMD_outFile, std::fstream::out | std::ios::binary | std::fstream::trunc); + if (!outFile.good()) ERROR(std::string("can't open oputput file '") + CMD_outFile + "'"); + + outFile.write((const char*) fileContent.data(), fileContent.size()); + + if (!outFile.good()) + { + outFile.close(); + unlink(CMD_outFile.c_str()); + ERROR(std::string("can't write oputput file '") + CMD_outFile + "'"); + } + + outFile.close(); +} + +// +// Main function +// + +int main(int argc, char **argv) +{ + parseCommandLine(argc, argv); + + printBanner(); + processFont(); + + return 0; +}