diff --git a/CONFIG.md b/CONFIG.md index 3df98c2d..39dec2bd 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -3,9 +3,11 @@ It's not possible to provide ROM builds that suit everyone needs - therefore configuration files were introduced, few predefined configurations are provided with sane defaults: +* [`c64/,,config_custom.s`](c64/,,config_custom.s) * [`c64/,,config_generic.s`](c64/,,config_generic.s) * [`c64/,,config_mega65.s`](c64/,,config_mega65.s) * [`c64/,,config_ultimate64.s`](c64/,,config_ultimate64.s) +* [`c64/,,config_testing.s`](c64/,,config_testing.s) Just edit them and recompile the project. To enable particular option - uncomment it by removing leading `//` from before `#define` directive (as you probably guessed, commenting out disables it). Some options are followed by constants - you can change them too to further fine-tune the build. @@ -27,6 +29,10 @@ Since Open ROMs is highly modular, it should be possible to add other platforms Select if the ROM is going to be used exclusively on the specific motherboard. It prevents from enabling options not having sense, skips initialization of C128-only registers, etc. +### `CONFIG_BRAND_CUSTOM` + +Intended for custom builds, which are not to be redistributed. Allows to configure branding with `CONFIG_CUSTOM_BRAND` varaible + ### `CONFIG_BRAND_GENERIC` If you don't know which variant to choose - select this one. @@ -107,17 +113,35 @@ Needs over 1000 bytes in KERNAL segment. If unsure - enable. Causes screen blanking during some IEC operations (currently only JiffyDOS file loading) to increase the data transfer performance. +### `CONFIG_IEC_DOLPHINDOS` + +Adds support for DolphinDOS fast protocol to the IEC bus, using UserPort cable. + +Needs about 160 buytes in KERNAL segment. If unsure - enable. + +### `CONFIG_IEC_DOLPHINDOS_FAST` + +Faster `LOAD` loop implementation for DolphinDOS protocol. + +Needs 20 more bytes in KERNAL segment. + ### `CONFIG_IEC_JIFFYDOS` Adds support for JiffyDOS fast protocol to the IEC bus. Needs about 430 bytes in KERNAL segment. If unsure - enable. +### `CONFIG_TAPE_NORMAL` + +Adds a minimal normal (standard Commodore format) tape support - just LOAD command. + +Needs about 700 bytes in KERNAL segment (if both normal and turbo are enabled, about 900 bytes are needed, as they share some code). If unsure - enable. + ### `CONFIG_TAPE_TURBO` Adds a minimal turbo tape support - just LOAD command (device 7, like on _Action Replay_ and _Final_ cartridges) -Needs about 400 bytes in KERNAL segment. If unsure - enable. +Needs about 650 bytes in KERNAL segment (if both normal and turbo are enabled, about 950 bytes are needed, as they share some code). If unsure - enable. ## Multiple SID support diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 2bb826fe..c2bcde66 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -1,2 +1,3 @@ -Although the project itself is LGPL3, I (FeralChild64) allow to redistribute my contributions to this project under any OSI (Open Source Initiative) approved open source license. +Although the project itself is LGPL3, I (FeralChild64 - Roman St********ski) allow to redistribute +my contributions to this project under any OSI (Open Source Initiative) approved open source license. diff --git a/Makefile b/Makefile index 4f22c87b..6e5edbf5 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Test files TESTDISK = testsuite/testdisk.d64 -TESTTAPE = testsuite/testtape-turbo.tap +TESTTAPE = testsuite/testtape-c64-pal-normal.tap # Source files @@ -55,13 +55,14 @@ TOOLS_LIST = $(pathsubst src/tools/%,build/tools/%,$(basename $(SRC_TOOLS))) # List of targets -STD_TARGET_LIST = build/kernal_generic.rom build/basic_generic.rom \ +STD_TARGET_LIST = build/kernal_custom.rom build/basic_custom.rom \ + build/kernal_generic.rom build/basic_generic.rom \ build/kernal_testing.rom build/basic_testing.rom \ build/kernal_mega65.rom build/basic_mega65.rom \ build/kernal_ultimate64.rom build/basic_ultimate64.rom \ build/chargen.rom -EXT_TARGET_LIST = build/newc65.rom +EXT_TARGET_LIST = build/mega65.rom REL_TARGET_LIST = $(pathsubst build/%,bin/%, $(STD_TARGET_LIST)) @@ -85,7 +86,7 @@ clean: updatebin: $(MAKE) -j64 --output-sync=target $(STD_TARGET_LIST) $(EXT_TARGET_LIST) $(TOOL_RELEASE) - $(TOOL_RELEASE) -i ./build -o ./bin basic_generic.rom kernal_generic.rom basic_testing.rom kernal_testing.rom basic_mega65.rom kernal_mega65.rom basic_ultimate64.rom kernal_ultimate64.rom newc65.rom + $(TOOL_RELEASE) -i ./build -o ./bin basic_generic.rom kernal_generic.rom basic_testing.rom kernal_testing.rom basic_ultimate64.rom kernal_ultimate64.rom mega65.rom cp build/chargen.rom bin/chargen.rom # Rules - tools @@ -113,11 +114,15 @@ build/chargen.rom: $(TOOL_PNGPREPARE) assets/8x8font.png # Dependencies - BASIC and KERNAL +build/target_custom/OUTB.BIN build/target_custom/BASIC_combined.vs: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC) \ + c64/,,config_custom.s build/target_custom/KERNAL_combined.sym \ + $(foreach dir,$(SRCDIR_BASIC),$(wildcard $(dir)/*.s)) build/target_generic/OUTB.BIN build/target_generic/BASIC_combined.vs: \ $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC) \ c64/,,config_generic.s build/target_generic/KERNAL_combined.sym \ $(foreach dir,$(SRCDIR_BASIC),$(wildcard $(dir)/*.s)) -build/target_testing/OUTB.BIN build/target_generic/BASIC_combined.vs: \ +build/target_testing/OUTB.BIN build/target_testing/BASIC_combined.vs: \ $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC) \ c64/,,config_testing.s build/target_testing/KERNAL_combined.sym \ $(foreach dir,$(SRCDIR_BASIC),$(wildcard $(dir)/*.s)) @@ -130,6 +135,10 @@ build/target_ultimate64/OUTB.BIN build/target_ultimate64/BASIC_combined.vs: \ c64/,,config_ultimate64.s build/target_ultimate64/KERNAL_combined.sym \ $(foreach dir,$(SRCDIR_BASIC),$(wildcard $(dir)/*.s)) +build/target_custom/OUTK.BIN build/target_custom/KERNAL_combined.vs build/target_custom/KERNAL_combined.sym: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL) \ + c64/,,config_custom.s \ + $(foreach dir,$(SRCDIR_KERNAL),$(wildcard $(dir)/*.s)) build/target_generic/OUTK.BIN build/target_generic/KERNAL_combined.vs build/target_generic/KERNAL_combined.sym: \ $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL) \ c64/,,config_generic.s \ @@ -147,21 +156,25 @@ build/target_ultimate64/OUTK.BIN build/target_ultimate64/KERNAL_combined.vs bu c64/,,config_ultimate64.s \ $(foreach dir,$(SRCDIR_KERNAL),$(wildcard $(dir)/*.s)) +build/target_custom/newrom: build/target_custom/OUTB.BIN build/target_custom/OUTK.BIN build/target_generic/newrom: build/target_generic/OUTB.BIN build/target_generic/OUTK.BIN build/target_testing/newrom: build/target_testing/OUTB.BIN build/target_testing/OUTK.BIN build/target_mega65/newrom: build/target_mega65/OUTB.BIN build/target_mega65/OUTK.BIN build/target_ultimate64/newrom: build/target_ultimate64/OUTB.BIN build/target_ultimate64/OUTK.BIN +build/kernal_custom.rom: build/target_custom/newrom build/kernal_generic.rom: build/target_generic/newrom build/kernal_testing.rom: build/target_testing/newrom build/kernal_mega65.rom: build/target_mega65/newrom build/kernal_ultimate64.rom: build/target_ultimate64/newrom +build/basic_custom.rom: build/target_custom/newrom build/basic_generic.rom: build/target_generic/newrom build/basic_testing.rom: build/target_testing/newrom build/basic_mega65.rom: build/target_mega65/newrom build/basic_ultimate64.rom: build/target_ultimate64/newrom +build/symbols_custom.vs: build/target_custom/BASIC_combined.vs build/target_custom/KERNAL_combined.vs build/symbols_generic.vs: build/target_generic/BASIC_combined.vs build/target_generic/KERNAL_combined.vs build/symbols_testing.vs: build/target_testing/BASIC_combined.vs build/target_testing/KERNAL_combined.vs build/symbols_mega65.vs: build/target_mega65/BASIC_combined.vs build/target_mega65/KERNAL_combined.vs @@ -215,11 +228,11 @@ build/symbols_hybrid.vs: build/target_generic/KERNAL_combined.vs # Rules - platform 'Mega 65' specific -build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.rom - dd if=/dev/zero bs=4096 count=10 of=build/newc65.rom - cat build/basic_mega65.rom build/chargen.rom build/chargen.rom build/kernal_mega65.rom >> build/newc65.rom +build/mega65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.rom + dd if=/dev/zero bs=4096 count=10 of=build/mega65.rom + cat build/basic_mega65.rom build/chargen.rom build/chargen.rom build/kernal_mega65.rom >> build/mega65.rom dd if=/dev/zero bs=65536 count=1 of=build/padding - cat build/padding >> build/newc65.rom + cat build/padding >> build/mega65.rom rm -f build/padding # Rules - tests @@ -229,7 +242,10 @@ build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.r test_ultimate64 \ testremote testsimilarity -test: test_generic +test: test_custom + +test_custom: build/kernal_custom.rom build/basic_custom.rom build/symbols_custom.vs + x64 -kernal build/kernal_custom.rom -basic build/basic_custom.rom -moncommands build/symbols_custom.vs -1 $(TESTTAPE) -8 $(TESTDISK) test_generic: build/kernal_generic.rom build/basic_generic.rom build/symbols_generic.vs x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -moncommands build/symbols_generic.vs -1 $(TESTTAPE) -8 $(TESTDISK) @@ -240,11 +256,11 @@ test_generic_x128: build/kernal_generic.rom build/basic_generic.rom build/symbol test_testing: build/kernal_testing.rom build/basic_testing.rom build/symbols_testing.vs x64 -kernal build/kernal_testing.rom -basic build/basic_testing.rom -moncommands build/symbols_testing.vs -1 $(TESTTAPE) -8 $(TESTDISK) -test_mega65: build/kernal_mega65.rom build/basic_mega65.rom build/symbols_mega65.vs +test_mega65_vice: build/kernal_mega65.rom build/basic_mega65.rom build/symbols_mega65.vs x64 -kernal build/kernal_mega65.rom -basic build/basic_mega65.rom -moncommands build/symbols_mega65.vs -1 $(TESTTAPE) -8 $(TESTDISK) -test_mega65_xemu: build/newc65.rom - ../xemu/build/bin/xmega65.native -dmarev 2 -forcerom -loadrom build/newc65.rom +test_mega65: build/mega65.rom + ../xemu/build/bin/xmega65.native -dmarev 2 -forcerom -loadrom build/mega65.rom 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) @@ -258,11 +274,11 @@ test_hybrid: build/kernal_hybrid.rom build/symbols_hybrid.vs @echo $(HYBRID_WARNING) @echo -test_m65: build/newc65.rom - m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65.rom -4 +test_m65: build/mega65.rom + m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/mega65.rom -4 -testremote: build/kernal_generic.rom build/basic_generic.rom build/symbols_generic.vs - x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -moncommands build/symbols_generic.vs -remotemonitor +testremote: build/kernal_custom.rom build/basic_custom.rom build/symbols_custom.vs + x64 -kernal build/kernal_custom.rom -basic build/basic_custom.rom -moncommands build/symbols_custom.vs -remotemonitor testsimilarity: build/target_generic/newrom $(TOOL_SIMILARITY) kernal basic $(TOOL_SIMILARITY) kernal build/target_generic/newrom diff --git a/STATUS.md b/STATUS.md index 110815b5..865001d7 100644 --- a/STATUS.md +++ b/STATUS.md @@ -3,19 +3,26 @@ Here are the features of the Open ROMs not found in the original ROMs from the 80s (many of them are [configurable](CONFIG.md) during compilation): + * improved keyboard scanning, resistant to ghosting and joystick interference (one variant even supports multi-keyy rollover), supports additional C128 keys * joystick can be used to move text cursor * pre-defined function keys -* uses RAM under ROM and I/O: 61438 bytes free -* cold/warm start silences multiple SID chips - all $D4xx and $D5xx addresses, configured addresses -* warm start due to BRK prints out the instruction address + +* JiffyDOS protocol support +* partial DolphinDOS protocol support +* DOS wedge (direct mode only) - `@`, `@`, `@$`, `@$`, `@` + +* turbo tape load support (as device 7, or using `←L`), up to 250 blocks (can store bytes under I/O) + * extended `LOAD` command * start/end addresses are displayed, in the Final cartridge style * command with just the file name tries to use the last device if it's number seems sane; otherwise uses 8 * secondary address over 255 is considered a start address -* JiffyDOS protocol support -* turbo tape load support (as device 7 or using `←L`) -* DOS wedge (direct mode only) - `@`, `@`, `@$`, `@$`, `@` + +* uses RAM under ROM and I/O: 61438 bytes free +* cold/warm start silences multiple SID chips - all $D4xx and $D5xx addresses, configured addresses +* warm start due to BRK prints out the instruction address + NOTE: extra features and their syntax can change in the future! @@ -33,7 +40,6 @@ The following ROM features are currently missing: * BASIC variables * BASIC expression parsing * floating point routines -* tape (normal mode) support * RS-232 support * NMI handling is incomplete @@ -46,30 +52,59 @@ The following ROM features are currently missing: | :-----------: | :------: | :------------------------------------------------: | | C64 | DONE | | | C128 | DONE | | -| C65 / Mega65 | NOT DONE | code should be complete, but is not tested yet | +| Mega65 | NOT DONE | code should be complete, but is not tested yet | -## Tape storage (LOAD only!) +## Screen | Driver | Status | Remarks | | :-----------: | :------: | :------------------------------------------------: | -| normal | NOT DONE | | -| turbo | PARTIAL | works, to do: use sync to calibrate read speed | +| VIC-II | PARTIAL | 80 chars in logical line support is very buggy | +| VDC 80 col. | NOT DONE | | -## IEC bus (disk drives, etc.) +## Tape port (LOAD only!) + +* Tapuino +* Datasette + +| Driver | Status | Remarks | +| :-----------: | :------: | :------------------------------------------------: | +| normal | PARTIAL | no error correction, no tape speed calibratrion | +| turbo | PARTIAL | up to 250 blocks, no tape speed calibratrion yet | + +## IEC bus + +* SD2IEC, petSD+, µIEC +* Pi1541, Ultimate II +* most disk drives and printers +* some hard drives | Driver | Status | Remarks | | :-----------: | :------: | :------------------------------------------------: | | standard | DONE | | | JiffyDOS | DONE | | -| DolphinDOS | NOT DONE | | +| DolphinDOS | DONE | | | CIA burst mod | NOT DONE | | +| Mega65 burst | NOT DONE | pure software implementation should be feasible | + +## IEEE-488 bus + +* petSD+ +* PET era disk drives and printers +* various scientific equipment + +| Driver | Status | Remarks | +| :-----------: | :------: | :------------------------------------------------: | +| CBM cartridge | NOT DONE | | ## RS-232 +* modems (telephone, WiFi) +* parallel port printers + | Driver | Status | Remarks | | :-----------: | :------: | :------------------------------------------------: | | UP2400 | NOT DONE | | -| UP9600 | NOT DONE | work in progress, not functional yet | +| UP9600 | NOT DONE | work started, not functional yet | | ACIA 6551 | NOT DONE | | diff --git a/assembler/KickAss.jar b/assembler/KickAss.jar index 9eb0e2b4..82560fa2 100644 Binary files a/assembler/KickAss.jar and b/assembler/KickAss.jar differ diff --git a/assembler/KickAssembler.pdf b/assembler/KickAssembler.pdf index da4dab4e..3a68ed58 100644 Binary files a/assembler/KickAssembler.pdf and b/assembler/KickAssembler.pdf differ diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index d09f539f..5adcd38c 100644 Binary files a/bin/basic_generic.rom and b/bin/basic_generic.rom differ diff --git a/bin/basic_mega65.rom b/bin/basic_mega65.rom deleted file mode 100644 index 06e4b304..00000000 Binary files a/bin/basic_mega65.rom and /dev/null differ diff --git a/bin/basic_testing.rom b/bin/basic_testing.rom index 008bb835..d39223eb 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 4c147b6c..d03026e6 100644 Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 749b319e..5cf03a31 100644 Binary files a/bin/kernal_generic.rom and b/bin/kernal_generic.rom differ diff --git a/bin/kernal_mega65.rom b/bin/kernal_mega65.rom deleted file mode 100644 index 58a7a0c7..00000000 Binary files a/bin/kernal_mega65.rom and /dev/null differ diff --git a/bin/kernal_testing.rom b/bin/kernal_testing.rom index 4f8f4734..4db16e98 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 2106f3ec..cd8e33aa 100644 Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ diff --git a/bin/newc65.rom b/bin/mega65.rom similarity index 86% rename from bin/newc65.rom rename to bin/mega65.rom index 90f97c65..63418690 100644 Binary files a/bin/newc65.rom and b/bin/mega65.rom differ diff --git a/c64/,,config_custom.s b/c64/,,config_custom.s new file mode 100644 index 00000000..2e6799c1 --- /dev/null +++ b/c64/,,config_custom.s @@ -0,0 +1,135 @@ + +.const CONFIG_ID = $00 // should be 1 byte, different for each config file! +.encoding "petscii_upper" + +// +// Please read CONFIG.md before modifying this file! +// + +// Idea: +// - configuration for custom builds and for development +// - file contains options to enable unfinished functionalities + + + +// Hardware platform and brand + +#define CONFIG_PLATFORM_COMMODORE_64 + +// #define CONFIG_MB_MEGA_65 +// #define CONFIG_MB_ULTIMATE_64 + +#define CONFIG_BRAND_CUSTOM_BUILD +// #define CONFIG_BRAND_GENERIC +// #define CONFIG_BRAND_TESTING +// #define CONFIG_BRAND_MEGA_65 +// #define CONFIG_BRAND_ULTIMATE_64 + +.const CONFIG_CUSTOM_BRAND = @"CUSTOM BUILD" + + +// Processor instruction set + +#define CONFIG_CPU_MOS_6502 +// #define CONFIG_CPU_WDC_65C02 +// #define CONFIG_CPU_CSG_65CE02 +// #define CONFIG_CPU_WDC_65816 + + +// Memory model + +#define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_60K + + +// I/O devices + +#define CONFIG_IEC +#define CONFIG_IEC_BLANK_SCREEN +#define CONFIG_IEC_DOLPHINDOS // not finished yet, but LOAD works +#define CONFIG_IEC_DOLPHINDOS_FAST +#define CONFIG_IEC_JIFFYDOS + +#define CONFIG_TAPE_NORMAL +#define CONFIG_TAPE_TURBO + +// #define CONFIG_RS232_UP2400 // please keep disabled for now +// #define CONFIG_RS232_UP9600 // please keep disabled for now + + +// Multiple SID support + +// #define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +// #define CONFIG_SID_D4XX +// #define CONFIG_SID_D5XX + + +// Keyboard settings + +// #define CONFIG_LEGACY_SCNKEY +// #define CONFIG_KEYBOARD_C128 +// #define CONFIG_KEYBOARD_C128_CAPS_LOCK +// #define CONFIG_KEYBOARD_C65 // untested +// #define CONFIG_KEYBOARD_C65_CAPS_LOCK // untested +// #define CONFIG_KEY_REPEAT_DEFAULT +// #define CONFIG_KEY_REPEAT_ALWAYS +#define CONFIG_KEY_FAST_SCAN +#define CONFIG_JOY1_CURSOR +#define CONFIG_JOY2_CURSOR + +#define CONFIG_PROGRAMMABLE_KEYS + +.const CONFIG_KEYCMD_RUN = @"\$5FL" + +.const CONFIG_KEYCMD_F1 = @"@" +.const CONFIG_KEYCMD_F2 = @"" +.const CONFIG_KEYCMD_F3 = @"RUN:" +.const CONFIG_KEYCMD_F4 = @"" +.const CONFIG_KEYCMD_F5 = @"LOAD" +.const CONFIG_KEYCMD_F6 = @"" +.const CONFIG_KEYCMD_F7 = @"@$" +.const CONFIG_KEYCMD_F8 = @"" + +.const CONFIG_KEYCMD_HELP = @"LIST" + +.const CONFIG_KEYCMD_F9 = @"" +.const CONFIG_KEYCMD_F10 = @"" +.const CONFIG_KEYCMD_F11 = @"" +.const CONFIG_KEYCMD_F12 = @"" +.const CONFIG_KEYCMD_F13 = @"" +.const CONFIG_KEYCMD_F14 = @"" + + +// Screen editor + +#define CONFIG_EDIT_STOPQUOTE +#define CONFIG_EDIT_TABULATORS + + +// Software features + +#define CONFIG_PANIC_SCREEN +#define CONFIG_DOS_WEDGE +#define CONFIG_TAPE_WEDGE +#define CONFIG_BCD_SAFE_INTERRUPTS + + +// Eye candy + +// #define CONFIG_COLORS_BRAND +// #define CONFIG_BANNER_SIMPLE +#define CONFIG_BANNER_FANCY +// #define CONFIG_BANNER_BRAND +#define CONFIG_SHOW_FEATURES +#define CONFIG_SHOW_PAL_NTSC + + +// Debug options + +// #define CONFIG_DBG_STUBS_BRK +// #define CONFIG_DBG_PRINTF diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s index cba2e0d3..258caf5a 100644 --- a/c64/,,config_generic.s +++ b/c64/,,config_generic.s @@ -1,5 +1,5 @@ -.const CONFIG_ID = $00 // should be 1 byte, different for each config file! +.const CONFIG_ID = $01 // should be 1 byte, different for each config file! .encoding "petscii_upper" // @@ -11,6 +11,7 @@ // - do not enable features which are a significant compatibility risk + // Hardware platform and brand #define CONFIG_PLATFORM_COMMODORE_64 @@ -42,11 +43,12 @@ #define CONFIG_IEC #define CONFIG_IEC_BLANK_SCREEN +#define CONFIG_IEC_DOLPHINDOS +#define CONFIG_IEC_DOLPHINDOS_FAST #define CONFIG_IEC_JIFFYDOS -// #define CONFIG_TAPE_NORMAL // please keep disabled for now + +#define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -// #define CONFIG_RS232_UP2400 // please keep disabled for now -// #define CONFIG_RS232_UP9600 // please keep disabled for now // Multiple SID support diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s index b2087518..eebb62e4 100644 --- a/c64/,,config_mega65.s +++ b/c64/,,config_mega65.s @@ -1,5 +1,5 @@ -.const CONFIG_ID = $01 // should be 1 byte, different for each config file! +.const CONFIG_ID = $02 // should be 1 byte, different for each config file! .encoding "petscii_upper" // @@ -9,8 +9,7 @@ // Idea: // - sane defaults for the Mega 65 FPGA computer // - do not enable features which are a significant compatibility risk -// - unless VICE gains Commodore 65 (or at least Flash8 cartridge) emulation support, -// do not enable CPU-specific optimizations; ROMs would be hard to test + // Hardware platform and brand @@ -28,9 +27,9 @@ // Processor instruction set -#define CONFIG_CPU_MOS_6502 +// #define CONFIG_CPU_MOS_6502 // #define CONFIG_CPU_WDC_65C02 -// #define CONFIG_CPU_CSG_65CE02 +#define CONFIG_CPU_CSG_65CE02 // #define CONFIG_CPU_WDC_65816 @@ -44,11 +43,12 @@ #define CONFIG_IEC #define CONFIG_IEC_BLANK_SCREEN +// #define CONFIG_IEC_DOLPHINDOS +// #define CONFIG_IEC_DOLPHINDOS_FAST #define CONFIG_IEC_JIFFYDOS -// #define CONFIG_TAPE_NORMAL // please keep disabled for now + +// #define CONFIG_TAPE_NORMAL // #define CONFIG_TAPE_TURBO -// #define CONFIG_RS232_UP2400 // please keep disabled for now -// #define CONFIG_RS232_UP9600 // please keep disabled for now // Multiple SID support @@ -91,12 +91,12 @@ .const CONFIG_KEYCMD_HELP = @"LIST" -.const CONFIG_KEYCMD_F9 = @"" -.const CONFIG_KEYCMD_F10 = @"" -.const CONFIG_KEYCMD_F11 = @"" -.const CONFIG_KEYCMD_F12 = @"" -.const CONFIG_KEYCMD_F13 = @"" -.const CONFIG_KEYCMD_F14 = @"" +.const CONFIG_KEYCMD_F9 = @"REM F9" +.const CONFIG_KEYCMD_F10 = @"REM F10" +.const CONFIG_KEYCMD_F11 = @"REM F11" +.const CONFIG_KEYCMD_F12 = @"REM F12" +.const CONFIG_KEYCMD_F13 = @"REM F13" +.const CONFIG_KEYCMD_F14 = @"REM F14" // Screen editor @@ -117,8 +117,8 @@ #define CONFIG_COLORS_BRAND // #define CONFIG_BANNER_SIMPLE -#define CONFIG_BANNER_FANCY -// #define CONFIG_BANNER_BRAND // do not enable for now, triggers screen editor bug under XEMU +// #define CONFIG_BANNER_FANCY +#define CONFIG_BANNER_BRAND #define CONFIG_SHOW_FEATURES // #define CONFIG_SHOW_PAL_NTSC diff --git a/c64/,,config_testing.s b/c64/,,config_testing.s index 19376b5a..317eeed9 100644 --- a/c64/,,config_testing.s +++ b/c64/,,config_testing.s @@ -43,11 +43,12 @@ #define CONFIG_IEC // #define CONFIG_IEC_BLANK_SCREEN +#define CONFIG_IEC_DOLPHINDOS +// #define CONFIG_IEC_DOLPHINDOS_FAST #define CONFIG_IEC_JIFFYDOS -// #define CONFIG_TAPE_NORMAL // please keep disabled for now + +// #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -// #define CONFIG_RS232_UP2400 // please keep disabled for now -// #define CONFIG_RS232_UP9600 // please keep disabled for now // Multiple SID support diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s index 1856fd44..3d4cce51 100644 --- a/c64/,,config_ultimate64.s +++ b/c64/,,config_ultimate64.s @@ -1,5 +1,5 @@ -.const CONFIG_ID = $02 // should be 1 byte, different for each config file! +.const CONFIG_ID = $03 // should be 1 byte, different for each config file! .encoding "petscii_upper" // @@ -11,6 +11,7 @@ // - do not enable features which are a significant compatibility risk + // Hardware platform and brand #define CONFIG_PLATFORM_COMMODORE_64 @@ -42,11 +43,12 @@ #define CONFIG_IEC #define CONFIG_IEC_BLANK_SCREEN +#define CONFIG_IEC_DOLPHINDOS +#define CONFIG_IEC_DOLPHINDOS_FAST #define CONFIG_IEC_JIFFYDOS -// #define CONFIG_TAPE_NORMAL // please keep disabled for now + +#define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -// #define CONFIG_RS232_UP2400 // please keep disabled for now -// #define CONFIG_RS232_UP9600 // please keep disabled for now // Multiple SID support @@ -113,7 +115,7 @@ // Eye candy -// #define CONFIG_COLORS_BRAND +#define CONFIG_COLORS_BRAND // #define CONFIG_BANNER_SIMPLE #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND diff --git a/c64/aliases/,aliases_config.s b/c64/aliases/,aliases_config.s index 99b2d2c9..c9a096d9 100644 --- a/c64/aliases/,aliases_config.s +++ b/c64/aliases/,aliases_config.s @@ -47,6 +47,9 @@ { .var selected = 0; +#if CONFIG_BRAND_CUSTOM_BUILD + .eval selected++ +#endif #if CONFIG_BRAND_GENERIC .eval selected++ #endif @@ -62,11 +65,11 @@ .if (selected != 1) .error "Please select exactly one CONFIG_BRAND_* option" -#if CONFIG_MB_MEGA_65 && !(CONFIG_BRAND_MEGA_65 || CONFIG_BRAND_TESTING) - .error "Please select brand either matching the CONFIG_MB_*, or a testing one" +#if CONFIG_MB_MEGA_65 && !(CONFIG_BRAND_MEGA_65 || CONFIG_BRAND_TESTING || CONFIG_BRAND_CUSTOM_BUILD) + .error "Please select brand either matching the CONFIG_MB_*, or a testing/custom one" #endif -#if CONFIG_MB_ULTIMATE_64 && !(CONFIG_BRAND_ULTIMATE_64 || CONFIG_BRAND_TESTING) - .error "Please select brand either matching the CONFIG_MB_*, or a testing one" +#if CONFIG_MB_ULTIMATE_64 && !(CONFIG_BRAND_ULTIMATE_64 || CONFIG_BRAND_TESTING || CONFIG_BRAND_CUSTOM_BUILD) + .error "Please select brand either matching the CONFIG_MB_*, or a testing/custom one" #endif } @@ -111,6 +114,18 @@ // Check that I/O configuration is correct { +#if CONFIG_RS232_UP9600 && (CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO) + .error "CONFIG_RS232_UP9600 is not compatible with CONFIG_TAPE_*" +#endif + +#if CONFIG_IEC_DOLPHINDOS && !CONFIG_IEC + .error "CONFIG_IEC_DOLPHINDOS requires CONFIG_IEC" +#endif + +#if CONFIG_IEC_DOLPHINDOS_FAST && !CONFIG_IEC_DOLPHINDOS + .error "CONFIG_IEC_DOLPHINDOS_FAST requires CONFIG_IEC_DOLPHINDOS" +#endif + #if CONFIG_IEC_JIFFYDOS && !CONFIG_IEC .error "CONFIG_IEC_JIFFYDOS requires CONFIG_IEC" #endif @@ -166,6 +181,9 @@ #if CONFIG_LEGACY_SCNKEY && CONFIG_RS232_UP9600 .error "CONFIG_LEGACY_SCNKEY is not compatible with CONFIG_RS232_UP9600" #endif +#if CONFIG_LEGACY_SCNKEY && CONFIG_TAPE_NORMAL + .error "CONFIG_LEGACY_SCNKEY is not compatible with CONFIG_TAPE_NORMAL" +#endif #if CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C128_CAPS_LOCK || CONFIG_KEYBOARD_C65 || CONFIG_KEYBOARD_C65_CAPS_LOCK) .error "CONFIG_LEGACY_SCNKEY and CONFIG_KEYBOARD_C128* / CONFIG_KEYBOARD_C65* are mutually exclusive" #endif @@ -225,20 +243,6 @@ -// Handle processor configuration - -#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 - -#define HAS_BCD_SAFE_INTERRUPTS - - .pseudocommand phx { .byte $DA } - .pseudocommand phy { .byte $5A } - .pseudocommand plx { .byte $FA } - .pseudocommand ply { .byte $7A } - -#endif - - // Handle I/O configuration #if CONFIG_RS232_UP2400 || CONFIG_RS232_UP9600 @@ -246,6 +250,7 @@ #endif + // Handle configuration of various features #if CONFIG_BCD_SAFE_INTERRUPTS @@ -303,11 +308,13 @@ { .var features_str = "" -#if CONFIG_TAPE_NORMAL +#if CONFIG_TAPE_NORMAL && !CONFIG_TAPE_TURBO .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD NORMAL") -#elif CONFIG_TAPE_TURBO +#endif +#if !CONFIG_TAPE_NORMAL && CONFIG_TAPE_TURBO .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD TURBO") -#elif CONFIG_TAPE_NORMAL && CONFIG_TAPE_TURBO +#endif +#if CONFIG_TAPE_NORMAL && CONFIG_TAPE_TURBO .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD NORMAL TURBO") #endif @@ -316,7 +323,7 @@ #if CONFIG_IEC .var iec_features_str = "IEC" #if CONFIG_IEC_DOLPHINDOS - .eval iec_features_str = iec_features_str + " DOLPHIN-DEV" + .eval iec_features_str = iec_features_str + " DOLPHIN" #endif #if CONFIG_IEC_JIFFYDOS .eval iec_features_str = iec_features_str + " JIFFY" diff --git a/c64/aliases/,aliases_cpu.s b/c64/aliases/,aliases_cpu.s index 79caf2d8..023e7558 100644 --- a/c64/aliases/,aliases_cpu.s +++ b/c64/aliases/,aliases_cpu.s @@ -1,8 +1,27 @@ // -// Provide pseudocommands to make CPU optimizations easier +// Provide pseudocommands (and other goodies) to make CPU optimizations easier // +#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 + .cpu _65c02 + #define HAS_OPCODES_65C02 +#endif + +#if CONFIG_CPU_CSG_65CE02 + #define HAS_OPCODES_65CE02 +#endif + +#if CONFIG_CPU_WDC_65816 + #define HAS_OPCODES_65816 +#endif + + +#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 + #define HAS_BCD_SAFE_INTERRUPTS +#endif + + // // These are not exactly for optimization - but to encourage proper usage of panic screen // @@ -28,6 +47,30 @@ } +// +// Some additional 65CE02 instructions +// + + +#if HAS_OPCODES_65CE02 + +.pseudocommand dew addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "DEW requires zeropage address" + .byte $C3, arg +} + +.pseudocommand inw addr +{ + .var arg = addr.getValue() + .if (arg > $FF) .error "INW requires zeropage address" + .byte $E3, arg +} + +#endif + + // // Stack manipulation - some CPUs will leave .A unchanged, some will use it as temporary storage, so consider .A trashed // @@ -35,7 +78,7 @@ .pseudocommand phx_trash_a { -#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 +#if HAS_OPCODES_65C02 phx #else txa @@ -45,7 +88,7 @@ .pseudocommand phy_trash_a { -#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 +#if HAS_OPCODES_65C02 phy #else tya @@ -55,7 +98,7 @@ .pseudocommand plx_trash_a { -#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 +#if HAS_OPCODES_65C02 plx #else pla @@ -65,7 +108,7 @@ .pseudocommand ply_trash_a { -#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_WDC_65816 +#if HAS_OPCODES_65C02 ply #else pla @@ -81,7 +124,7 @@ .pseudocommand bcs_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $B3, mod(offset, $100), floor(offset / $100) #else @@ -93,7 +136,7 @@ __l: .pseudocommand bcc_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $93, mod(offset, $100), floor(offset / $100) #else @@ -105,7 +148,7 @@ __l: .pseudocommand beq_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 && XXX_DISABLED // XXX causes problems with XEMU, investigate why .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $F3, mod(offset, $100), floor(offset / $100) #else @@ -117,7 +160,7 @@ __l: .pseudocommand bne_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $D3, mod(offset, $100), floor(offset / $100) #else @@ -129,7 +172,7 @@ __l: .pseudocommand bmi_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $33, mod(offset, $100), floor(offset / $100) #else @@ -141,7 +184,7 @@ __l: .pseudocommand bpl_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $13, mod(offset, $100), floor(offset / $100) #else @@ -153,7 +196,7 @@ __l: .pseudocommand bvc_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $53, mod(offset, $100), floor(offset / $100) #else @@ -165,7 +208,7 @@ __l: .pseudocommand bvs_far dst { -#if CONFIG_CPU_CSG_65CE02 +#if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) .byte $73, mod(offset, $100), floor(offset / $100) #else diff --git a/c64/aliases/,aliases_ram_lowmem.s b/c64/aliases/,aliases_ram_lowmem.s index 814aff63..c554e0de 100644 --- a/c64/aliases/,aliases_ram_lowmem.s +++ b/c64/aliases/,aliases_ram_lowmem.s @@ -89,7 +89,7 @@ .label C3PO = $94 // flag - is BSOUR content valid .label BSOUR = $95 // serial bus buffered output byte .label SYNO = $96 // -- NOT IMPLEMENTED -- - .label XSAV = $97 // temporary register storage for ASCII related routines [!] usage details might differ + .label XSAV = $97 // temporary register storage for ASCII/tape related routines [!] usage details might differ .label LDTND = $98 // number of entries in LAT / FAT / SAT tables .label DFLTN = $99 // default input device .label DFLTO = $9A // default output device @@ -103,7 +103,7 @@ .label PTR1 = $9E // -- NOT IMPLEMENTED -- .label PTR2 = $9F // -- NOT IMPLEMENTED -- .label TIME = $A0 // $A0-$A2 jiffy clock -#if !CONFIG_IEC_JIFFYDOS +#if !CONFIG_IEC_JIFFYDOS && !CONFIG_IEC_DOLPHINDOS .label TSFCNT = $A3 // temporary variable for tape and IEC, [!] our usage differs #else .label IECPROTO = $A3 // -- WIP -- [!] 0 = normal, 1 = JiffyDOS, >= $80 for unknown @@ -111,12 +111,12 @@ .label TBTCNT = $A4 // temporary variable for tape and IEC, [!] our usage probably differs in details .label CNTDN = $A5 // -- NOT IMPLEMENTED -- .label BUFPNT = $A6 // -- NOT IMPLEMENTED -- - .label INBIT = $A7 // -- NOT IMPLEMENTED -- + .label INBIT = $A7 // temporary storage for tape / RS-232 received bits #if !CONFIG_LEGACY_SCNKEY .label BITCI = $A8 // -- NOT IMPLEMENTED -- .label RINONE = $A9 // -- WIP -- (UP9600 only) RS-232 check for start bit flag .label RIDDATA = $AA // -- NOT IMPLEMENTED -- - .label RIPRTY = $AB // -- NOT IMPLEMENTED -- + .label RIPRTY = $AB // -- WIP -- checksum while reading tape #endif .label SAL = $AC // $AC-$AD -- NOT IMPLEMENTED -- (implemented screen part) .label EAL = $AE // $AE-$AF -- NOT IMPLEMENTED -- [!] used also by screen editor, for temporary color storage when scrolling @@ -135,8 +135,8 @@ .label SA = $B9 // current secondary address .label FA = $BA // current device number .label FNADDR = $BB // $BB-$BC current file name pointer - .label ROPRTY = $BD // tape / RS-232 temporary storage - .label FSBLK = $BE // -- NOT IMPLEMENTED -- + .label ROPRTY = $BD // -- NOT IMPLEMENTED -- tape / RS-232 temporary storage + .label FSBLK = $BE // -- NOT IMPLEMENTED -- tape / RS-232 temporary storage .label MYCH = $BF // -- NOT IMPLEMENTED -- .label CAS1 = $C0 // tape motor interlock .label STAL = $C1 // $C1-$C2 LOAD/SAVE start address @@ -281,8 +281,9 @@ // $314 $334-$33B -- UNUSED -- free for user software +#if !CONFIG_RS232_UP9600 .label TBUFFR = $33C // $33C-$3FB [!] tape buffer, our usage details differ -#if CONFIG_RS232_UP9600 +#else .label REVTAB = $37C // $37C-$3FB -- WIP -- [!] RS-232 precalculated data #endif diff --git a/c64/basic/init/initmsg_real.s b/c64/basic/init/initmsg_real.s index 5cb951a3..923b74a6 100644 --- a/c64/basic/init/initmsg_real.s +++ b/c64/basic/init/initmsg_real.s @@ -10,6 +10,8 @@ initmsg_real: ldy #>startup_banner jsr STROUT +#if !CONFIG_BRAND_CUSTOM_BUILD + ldx #$01 ldy #$04 jsr plot_set @@ -18,13 +20,23 @@ initmsg_real: ldy #>rom_revision_basic_string jsr STROUT +#endif // no CONFIG_BRAND_CUSTOM_BUILD + +#if !CONFIG_BRAND_CUSTOM_BUILD ldx #$03 +#else + ldx #$02 +#endif ldy #$04 jsr plot_set jsr initmsg_bytes_free +#if !CONFIG_BRAND_CUSTOM_BUILD ldx #$06 +#else + ldx #$05 +#endif ldy #$00 #if CONFIG_SHOW_PAL_NTSC && CONFIG_SHOW_FEATURES jsr plot_set @@ -54,6 +66,8 @@ initmsg_real: ldy #>startup_banner jsr STROUT +#if !CONFIG_BRAND_CUSTOM_BUILD + ldx #$01 ldy #$0A jsr plot_set @@ -66,13 +80,23 @@ initmsg_real: ldy #>rom_revision_basic_string jsr STROUT +#endif // no CONFIG_BRAND_CUSTOM_BUILD + +#if !CONFIG_BRAND_CUSTOM_BUILD ldx #$03 +#else + ldx #$02 +#endif ldy #$0A jsr plot_set jsr initmsg_bytes_free +#if !CONFIG_BRAND_CUSTOM_BUILD ldx #$06 +#else + ldx #$05 +#endif ldy #$00 #if CONFIG_SHOW_PAL_NTSC && CONFIG_SHOW_FEATURES jsr plot_set @@ -94,18 +118,22 @@ initmsg_real: ldy #>startup_banner jsr STROUT + ldx #$04 + ldy #$00 + jsr plot_set + lda #rom_revision_basic_string jsr STROUT - ldx #$03 + ldx #$04 ldy #$12 jsr plot_set jsr initmsg_bytes_free #if CONFIG_SHOW_FEATURES - ldx #$04 + ldx #$05 ldy #$00 jsr plot_set jsr print_features diff --git a/c64/basic/init/startup_banner.s b/c64/basic/init/startup_banner.s index 8736df64..7543ef0a 100644 --- a/c64/basic/init/startup_banner.s +++ b/c64/basic/init/startup_banner.s @@ -8,7 +8,10 @@ .macro BANNER_TEXT() { -#if CONFIG_BRAND_GENERIC +#if CONFIG_BRAND_CUSTOM_BUILD + .text "OPEN ROMS " + .text CONFIG_CUSTOM_BRAND +#elif CONFIG_BRAND_GENERIC .text "OPEN ROMS GENERIC BUILD" #elif CONFIG_BRAND_TESTING .text "OPEN ROMS TESTING BUILD" @@ -61,11 +64,15 @@ rainbow_logo: .byte SET_COLOR_0, $00 } +#if !CONFIG_BRAND_CUSTOM_BUILD + pre_revision_string: .text "RELEASE " .byte $00 +#endif // no CONFIG_BRAND_CUSTOM_BUILD + #elif CONFIG_BANNER_BRAND && CONFIG_BRAND_MEGA_65 // Fancy Mega65 banner - from Retrofan diff --git a/c64/basic/rom_revision/bf52.rom_revision_basic.s b/c64/basic/rom_revision/bf52.rom_revision_basic.s index 30c9e65d..8fe574c8 100644 --- a/c64/basic/rom_revision/bf52.rom_revision_basic.s +++ b/c64/basic/rom_revision/bf52.rom_revision_basic.s @@ -21,7 +21,12 @@ rom_revision_basic_string: // $BF55 +#if !CONFIG_BRAND_CUSTOM_BUILD .text "(DEVEL SNAPSHOT)" // actual ROM revision string; up to 16 characters +#else + .text "(CUSTOM BUILD)" +#endif + .byte $00 // marks the end of string __rom_revision_basic_end: diff --git a/c64/basic/rom_revision/e4b7.rom_revision_kernal.s b/c64/basic/rom_revision/e4b7.rom_revision_kernal.s index 996baeec..e98bb1a8 100644 --- a/c64/basic/rom_revision/e4b7.rom_revision_kernal.s +++ b/c64/basic/rom_revision/e4b7.rom_revision_kernal.s @@ -35,7 +35,12 @@ rom_revision_kernal_string: // $E4BC +#if !CONFIG_BRAND_CUSTOM_BUILD .text "(DEVEL SNAPSHOT)" // actual ROM revision string; up to 16 characters +#else + .text "(CUSTOM BUILD)" +#endif + .byte $00 // marks the end of string __rom_revision_kernal_end: diff --git a/c64/kernal/iec/acptr.s b/c64/kernal/iec/acptr.s index e5e818e7..2ed7962d 100644 --- a/c64/kernal/iec/acptr.s +++ b/c64/kernal/iec/acptr.s @@ -14,15 +14,15 @@ ACPTR: lda IOSTATUS beq !+ - lda #$0D // tested on real ROMs clc + lda #$0D // tested on real ROMs rts !: #if CONFIG_IEC #if CONFIG_IEC_JIFFYDOS jmp iec_rx_dispatch -#else // no turbo supported +#else jmp iec_rx_byte #endif #else diff --git a/c64/kernal/iec/ciout.s b/c64/kernal/iec/ciout.s index 4c6137bd..3b92cc14 100644 --- a/c64/kernal/iec/ciout.s +++ b/c64/kernal/iec/ciout.s @@ -32,13 +32,13 @@ ciout_store_in_buffer: ciout_send_byte: - clc // don't send with EOI + clc // send without EOI #if CONFIG_IEC_JIFFYDOS jsr iec_tx_dispatch -#else // no turbo supported +#else jsr iec_tx_byte #endif - inc C3PO // iec_tx_byte sets it to 0, but we still have something to send + inc C3PO // tx byte routine sets to 0, but we still have something to send jmp ciout_store_in_buffer #else diff --git a/c64/kernal/iec/iec_cmd_open.s b/c64/kernal/iec/iec_cmd_open.s index 48fceb28..54159d78 100644 --- a/c64/kernal/iec/iec_cmd_open.s +++ b/c64/kernal/iec/iec_cmd_open.s @@ -17,8 +17,21 @@ iec_cmd_open: // similar to TKSA, but without turnaround !: ora #$F0 +#if CONFIG_IEC_DOLPHINDOS + + sta TBTCNT + jsr iec_tx_command + bcs !+ // branch if error + + jsr dolphindos_detect + jmp iec_tx_command_finalize + +#else + // FALLTROUGH +#endif + common_open_close_unlsn_second: // common part of several commands sta TBTCNT diff --git a/c64/kernal/iec/iec_rx_byte.s b/c64/kernal/iec/iec_rx_byte.s index 5297a4ae..56d54aa6 100644 --- a/c64/kernal/iec/iec_rx_byte.s +++ b/c64/kernal/iec/iec_rx_byte.s @@ -8,6 +8,19 @@ #if CONFIG_IEC +#if CONFIG_IEC_JIFFYDOS + +iec_rx_dispatch: + + lda IECPROTO + cmp #$01 + beq_far jiffydos_rx_byte + + // FALLTROUGH + +#endif // CONFIG_IEC_JIFFYDOS + + iec_rx_byte: // Store .X and .Y on the stack - preserve them @@ -24,36 +37,30 @@ iec_rx_byte: jsr iec_wait_for_clk_release // We then release the DATA to signal we are ready - // We can use this routine, since we weren't pulling CLK anyway + // We can use this routine, since we were not pulling CLK anyway jsr iec_release_clk_data // Wait till data line is released (someone else might be holding it) jsr iec_wait_for_data_release - // Wait for talker to pull CLK. - // If over 200 usec (205 cycles on NTSC machine) , then it is EOI. - // Loop iteraction takes 13 cycles, 17 full iterations are enough + // Check if EOI + jsr iec_rx_check_eoi - ldx #$11 // 2 cycles -iec_rx_clk_wait1: - lda CIA2_PRA // 4 cycles - rol // 2 cycles, to put CLK in as the last bit - bpl iec_rx_not_eoi // 2 cycles if not jumped - dex // 2 cycles - bne iec_rx_clk_wait1 // 3 cycles if jumped - - // Timeout - either this is the last byte of stream, or the stream is empty at all. - // Mark end of stream in IOSTATUS - jsr kernalstatus_EOI +#if CONFIG_IEC_DOLPHINDOS -iec_rx_not_empty: + // Check if DolphinDOS was detected + lda IECPROTO + cmp #$02 + bne iec_rx_no_dolphindos - // Pull data for 60 usec to confirm it - jsr iec_release_clk_pull_data - jsr iec_wait60us - jsr iec_release_clk_data + // For DolphinDOS just fetch the byte from parallel port + lda CIA2_PRB + pha + jmp iec_rx_acknowledge -iec_rx_not_eoi: +iec_rx_no_dolphindos: + +#endif // CONFIG_IEC_DOLPHINDOS // Latch input bits in on rising edge of CLK, eight times for eight bits. ldx #7 @@ -68,7 +75,7 @@ iec_rx_bit_loop: jsr iec_wait_for_clk_release // (we do this implicitly below, with a tighter routine, - // so that we don't have timing problems, as the requirements + // so that we do not have timing problems, as the requirements // are quite tight. Basically we need to read the clock and data // bit from the same byte read. @@ -118,7 +125,11 @@ iec_rx_clk_wait2: dex bpl iec_rx_bit_loop - // Then we must within 1000 usec acknowledge the frame by + // FALLTROUGH + +iec_rx_acknowledge: + + // Then we must within 1000 usec acknowledge the byte by // pulling DATA. At this point, CLK is pulled by the // talker and DATA by us, i.e., we are ready to receive // the next byte. (p11). diff --git a/c64/kernal/iec/iec_rx_check_eoi.s b/c64/kernal/iec/iec_rx_check_eoi.s new file mode 100644 index 00000000..b36d840e --- /dev/null +++ b/c64/kernal/iec/iec_rx_check_eoi.s @@ -0,0 +1,35 @@ + +// +// Helper routine to check for EOI while receiving byte from IEC +// + +iec_rx_check_eoi: + + // Wait for talker to pull CLK. + // If over 200 usec (205 cycles on NTSC machine) , then it is EOI. + // Loop iteraction takes 11 cycles, 19 full iterations are enough + + ldx #$13 // 2 cycles + +!: + bit CIA2_PRA // 4 cycles + bvc iec_rx_check_eoi_done // 2 cycles if not jumped + dex // 2 cycles + bne !- // 3 cycles if jumped + + // FALLTROUGH + +iec_rx_check_eoi_confirm: + + // Timeout - either this is the last byte of stream, or the stream is empty at all. + // Mark end of stream in IOSTATUS + jsr kernalstatus_EOI + + // Pull data for 60 usec to confirm it + jsr iec_release_clk_pull_data + jsr iec_wait60us + jsr iec_release_clk_data + +iec_rx_check_eoi_done: + + rts diff --git a/c64/kernal/iec/iec_send_file_name.s b/c64/kernal/iec/iec_send_file_name.s index 7530f7a0..72f107bf 100644 --- a/c64/kernal/iec/iec_send_file_name.s +++ b/c64/kernal/iec/iec_send_file_name.s @@ -32,7 +32,7 @@ iec_send_file_name_loop: sta TBTCNT #if CONFIG_IEC_JIFFYDOS jsr iec_tx_dispatch -#else // no turbo supported +#else jsr iec_tx_byte #endif jmp iec_send_file_name_loop diff --git a/c64/kernal/iec/iec_tx_byte.s b/c64/kernal/iec/iec_tx_byte.s index 5dcca324..91b91abb 100644 --- a/c64/kernal/iec/iec_tx_byte.s +++ b/c64/kernal/iec/iec_tx_byte.s @@ -9,6 +9,26 @@ #if CONFIG_IEC + +#if CONFIG_IEC_JIFFYDOS + +iec_tx_dispatch: + + php // preserve C flag for EOI indication + lda IECPROTO + cmp #$01 + bne !+ + + plp + jmp jiffydos_tx_byte +!: + plp + + // FALLTROUGH + +#endif // CONFIG_IEC_JIFFYDOS + + iec_tx_byte: // Store .X and .Y on the stack - preserve them @@ -44,6 +64,29 @@ iec_tx_common: jsr iec_wait_for_data_pull jsr iec_wait_for_data_release !: +#if CONFIG_IEC_DOLPHINDOS + + // Check if DolphinDOS was detected + lda IECPROTO + cmp #$02 + bne iec_tx_no_dolphindos + + // For DolphinDOS just push the byte to parallel port (set it to output first) + lda #$FF + sta CIA2_DDRB + lda TBTCNT + sta CIA2_PRB + + // Pull CLK to indicate data is now valid (we should not hold DATA nevertheless) + jsr iec_pull_clk_release_data_oneshot + + // Finish the flow + jmp iec_tx_common_finalize + +iec_tx_no_dolphindos: + +#endif // CONFIG_IEC_DOLPHINDOS + // Pull CLK back to indicate that DATA is not valid, keep it for 60us // We can use this routine as we don't hold DATA anyway (and its state doesn't even matter) @@ -95,6 +138,10 @@ iec_tx_common_bit_is_sent: dex bpl iec_tx_common_sendbit + // FALLTROUGH + +iec_tx_common_finalize: + cli // Give devices time to tell if they are busy by pulling DATA diff --git a/c64/kernal/iec/iec_wait60us.s b/c64/kernal/iec/iec_wait60us.s index f748ea28..5673d528 100644 --- a/c64/kernal/iec/iec_wait60us.s +++ b/c64/kernal/iec/iec_wait60us.s @@ -1,4 +1,8 @@ +// +// Note: damages .X +// + #if CONFIG_IEC @@ -14,8 +18,8 @@ iec_wait60us: // Waste cycles in a loop - ldy #$0A // 2 cycles -!: dey // 2 cycles * 10 + ldx #$0A // 2 cycles +!: dex // 2 cycles * 10 bpl !- // 3 cycles * 9 + 2 cycles rts // 6 cycles diff --git a/c64/kernal/iec/load_iec.s b/c64/kernal/iec/load_iec.s index 0ab544ff..d901e6a7 100644 --- a/c64/kernal/iec/load_iec.s +++ b/c64/kernal/iec/load_iec.s @@ -62,6 +62,12 @@ load_iec: jsr iec_tx_command bcs load_iec_error +#if CONFIG_IEC_DOLPHINDOS + + jsr dolphindos_detect + +#endif + // We are currently talker, so do the IEC turn around so that we // are the listener (p16) jsr iec_turnaround_to_listen @@ -87,18 +93,23 @@ load_iec: // Display start address jsr lvs_display_loading_verifying -#if CONFIG_IEC_JIFFYDOS && !CONFIG_MEMORY_MODEL_60K +#if (CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS) && !CONFIG_MEMORY_MODEL_60K - // If feasible, use JiffyDOS optimized LOAD loop + // If feasible, use protocol-specific optimized LOAD loop lda VERCKK bne load_iec_loop // branch if VERIFY - lda IECPROTO - cmp #$01 - bne load_iec_loop // branch if not JiffyDOS - jmp load_jiffydos +#if CONFIG_IEC_JIFFYDOS + cmp #$01 + beq_far jiffydos_load // branch if JiffyDOS +#endif + +#if CONFIG_IEC_DOLPHINDOS + cmp #$02 + beq_far dolphindos_load // branch if DolphinDOS +#endif #endif @@ -107,7 +118,7 @@ load_iec_loop: // We are now ready to receive bytes #if CONFIG_IEC_JIFFYDOS jsr iec_rx_dispatch -#else // no turbo supported +#else jsr iec_rx_byte #endif bcs load_iec_error @@ -118,8 +129,15 @@ load_iec_loop: // Advance pointer to data; it is OK if it advances past $FFFF, // one autostart technique does exactly this - jsr lvs_advance_EAL - +#if !HAS_OPCODES_65CE02 + inc EAL+0 + bne !+ + inc EAL+1 +!: +#else + inw EAL+0 +#endif + // Handle STOP key; it is probably an overkill to do it // with every byte, once per 32 bytes should be enough lda EAL @@ -128,13 +146,12 @@ load_iec_loop: phx_trash_a jsr udtim_keyboard jsr STOP - bcs load_break_error + bcs_far load_break_error plx_trash_a !: // Check for EOI - if so, this was the last byte - lda IOSTATUS - and #K_STS_EOI - beq load_iec_loop + bit IOSTATUS + bvc load_iec_loop // FALLTROUGH diff --git a/c64/kernal/iec/save_iec.s b/c64/kernal/iec/save_iec.s index e06d4a9e..bd6aade5 100644 --- a/c64/kernal/iec/save_iec.s +++ b/c64/kernal/iec/save_iec.s @@ -44,13 +44,19 @@ save_iec: jsr iec_tx_command bcs save_iec_dev_not_found +#if CONFIG_IEC_DOLPHINDOS + + jsr dolphindos_detect + +#endif + // Save start address lda STAL+0 sta TBTCNT clc #if CONFIG_IEC_JIFFYDOS jsr iec_tx_dispatch -#else // no turbo supported +#else jsr iec_tx_byte #endif @@ -59,7 +65,7 @@ save_iec: clc #if CONFIG_IEC_JIFFYDOS jsr iec_tx_dispatch -#else // no turbo supported +#else jsr iec_tx_byte #endif @@ -80,12 +86,17 @@ iec_save_loop: clc #if CONFIG_IEC_JIFFYDOS jsr iec_tx_dispatch -#else // no turbo supported +#else jsr iec_tx_byte #endif // Next iteration - jsr lvs_advance_MEMUSS_check_EAL +#if !HAS_OPCODES_65CE02 + jsr lvs_advance_MEMUSS +#else + inw MEMUSS+0 +#endif + jsr lvs_check_EAL bne iec_save_loop iec_save_loop_end: diff --git a/c64/kernal/iec/talk.s b/c64/kernal/iec/talk.s index d0c11e65..f9726d4d 100644 --- a/c64/kernal/iec/talk.s +++ b/c64/kernal/iec/talk.s @@ -32,15 +32,12 @@ common_talk_listen: // common part of TALK and LISTEN sta TBTCNT -#if CONFIG_IEC_JIFFYDOS +#if CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS - // It seems that only TALK/LISTEN is used to detect the JiffyDOS support - - lda #$FF // unknown protocol - check what is supported + lda #$FF // force JiffyDOS detection, clear DolphinDOS mark sta IECPROTO -#endif // CONFIG_IEC_JIFFYDOS - +#endif jmp iec_tx_command diff --git a/c64/kernal/iec/unlsn.s b/c64/kernal/iec/unlsn.s index 4681c089..857956c6 100644 --- a/c64/kernal/iec/unlsn.s +++ b/c64/kernal/iec/unlsn.s @@ -18,9 +18,9 @@ UNLSN: // According to serial-bus.pdf (page 15) this routine flushes the IEC out buffer jsr iec_tx_flush -#if CONFIG_IEC_JIFFYDOS +#if CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS - lda #$FF // XXX + lda #$FF // do not use JiffyDOS / DolphinDOS anymore, trigger JiffyDOS detection sta IECPROTO #endif diff --git a/c64/kernal/iec/untlk.s b/c64/kernal/iec/untlk.s index d8db0fb1..e4bb2717 100644 --- a/c64/kernal/iec/untlk.s +++ b/c64/kernal/iec/untlk.s @@ -18,9 +18,9 @@ UNTLK: // According to serial-bus.pdf (page 15) this routine flushes the IEC out buffer jsr iec_tx_flush -#if CONFIG_IEC_JIFFYDOS +#if CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS - lda #$FF // XXX + lda #$FF // do not use JiffyDOS / DolphinDOS anymore, trigger JiffyDOS detection sta IECPROTO #endif diff --git a/c64/kernal/iec_fast/dolphindos_detect.s b/c64/kernal/iec_fast/dolphindos_detect.s new file mode 100644 index 00000000..3f622482 --- /dev/null +++ b/c64/kernal/iec_fast/dolphindos_detect.s @@ -0,0 +1,69 @@ + +// +// Helper routine for JiffyDOS detection +// + +// The standard parallel cable (used by SpeedDOS, DolphinDOS 2, etc.) connects the following UserPort lines: +// - PB0-PB7 - CIA2_PRB ($DD01), CIA #2 port B +// - PC2, FLAG2 - CIA2_ICR ($DD0D), CIA #2 handshaking line +// +// See: +// - http://sta.c64.org/cbmpar41c.html +// - http://sta.c64.org/cbmpar71c.html +// - Commodore 64 Programers Referencee Guide, pages 360-361, 429 +// - Computes Mapping the C64, page 183 + + + +#if CONFIG_IEC_DOLPHINDOS + + +dolphindos_detect: + +#if CONFIG_IEC_JIFFYDOS + + lda IECPROTO + bne dolphindos_detect_fail // skip if other protocol already detected + +#endif + + // Make sure the port settings are correct + + lda #$7F + sta CIA2_ICR // disable interrupt generation + lda #$00 + sta CIA2_DDRB // set all port B lines as input + + // According to logs collected from modified VICE emulator, original DolphinDOS ROM + // constantly reads $DD0D and $DD01 until handshake bit of $DD0D is set, or some kind + // of timeout occurs + + ldx #$20 + +dolphindos_detect_loop: + + lda CIA2_ICR + cmp #$10 + beq dolphindos_detect_success + lda CIA2_PRB // XXX do we need this read? + + dex + bne dolphindos_detect_loop + + // FALLTROUGH - protocol not detected + +dolphindos_detect_fail: + + rts + +dolphindos_detect_success: + + // Protocol detected + + lda #$02 + sta IECPROTO + + rts + + +#endif // CONFIG_IEC_DOLPHINDOS diff --git a/c64/kernal/iec_fast/dolphindos_load.s b/c64/kernal/iec_fast/dolphindos_load.s new file mode 100644 index 00000000..849f3948 --- /dev/null +++ b/c64/kernal/iec_fast/dolphindos_load.s @@ -0,0 +1,119 @@ + +// +// DolphinDOS protocol support for IEC - optimized load loop +// + + +#if CONFIG_IEC_DOLPHINDOS && !CONFIG_MEMORY_MODEL_60K + + +dolphindos_load: + + // Timing is critical for some parts, do not allow interrupts + sei + + // A trick to shorten EAL update time + ldy #$00 + +#if CONFIG_IEC_DOLPHINDOS_FAST + // Another trick: prepare values for quickly setting/releasing DATA + lda CIA2_PRA + and #$FF - BIT_CIA2_PRA_DAT_OUT - BIT_CIA2_PRA_CLK_OUT - BIT_CIA2_PRA_ATN_OUT + sta IECPROTO // release DATA + ora #BIT_CIA2_PRA_DAT_OUT + sta TBTCNT // pull DATA +#endif + + // FALLTROUGH + +dolphindos_load_loop: + +#if !CONFIG_IEC_DOLPHINDOS_FAST + // Check if this was EOI + bit IOSTATUS + bvs dolphindos_load_end +#endif + + // Wait for the talker to release the CLK line +!: + bit CIA2_PRA + bvc !- + + // Release the DATA to signal we are ready +#if !CONFIG_IEC_DOLPHINDOS_FAST + lda CIA2_PRA + and #$FF - BIT_CIA2_PRA_DAT_OUT // release +#else + lda IECPROTO +#endif + sta CIA2_PRA + +#if !CONFIG_IEC_DOLPHINDOS_FAST + + // Check if EOI + jsr iec_rx_check_eoi // can damage .X, but this is safe + +#else + + // Check if EOI - inlined code to avoid wasting cycles on RTS + ldx #$13 +!: + bit CIA2_PRA + bvc dolphindos_load_no_eoi + dex + bne !- + + // EOI - mark it and retrieve the last byte + jsr iec_rx_check_eoi_confirm + lda CIA2_PRB + sta (EAL),y + + // Update EAL for the last time + sec + jsr iec_update_EAL_by_Y + + // Restore proper IECPROTO value + lda #$02 + sta IECPROTO + + // End of load loop + jmp load_iec_loop_end + +dolphindos_load_no_eoi: + +#endif + + // Retrieve and store byte + lda CIA2_PRB + sta (EAL),y + + // Pull DATA to acknowledge +#if !CONFIG_IEC_DOLPHINDOS_FAST + lda CIA2_PRA + ora #BIT_CIA2_PRA_DAT_OUT +#else + lda TBTCNT +#endif + sta CIA2_PRA + + // Handle EAL + iny + bne dolphindos_load_loop + inc EAL+1 + jmp dolphindos_load_loop + +#if !CONFIG_IEC_DOLPHINDOS_FAST + +dolphindos_load_end: + + // Update EAL + clc + jsr iec_update_EAL_by_Y + + // End of load loop + jmp load_iec_loop_end + +#endif + + +#endif // CONFIG_IEC_DOLPHINDOS and not CONFIG_MEMORY_MODEL_60K diff --git a/c64/kernal/iec_fast/iec_fast_common.s b/c64/kernal/iec_fast/iec_fast_common.s new file mode 100644 index 00000000..a7ce0bb6 --- /dev/null +++ b/c64/kernal/iec_fast/iec_fast_common.s @@ -0,0 +1,21 @@ + +// +// Common routines for multiple IEC fact protocols +// + + +#if (CONFIG_IEC_JIFFYDOS || CONFIG_IEC_DOLPHINDOS) && !CONFIG_MEMORY_MODEL_60K + + +iec_update_EAL_by_Y: // note: Carry has to be set by caller! + + tya + adc EAL+0 + sta EAL+0 + bcc !+ + inc EAL+1 +!: + rts + + +#endif diff --git a/c64/kernal/iec_fast/iec_rx_dispatch.s b/c64/kernal/iec_fast/iec_rx_dispatch.s deleted file mode 100644 index 465ee4b5..00000000 --- a/c64/kernal/iec_fast/iec_rx_dispatch.s +++ /dev/null @@ -1,22 +0,0 @@ - -// -// Arbitration code for normal/turbo transfer -// - - -#if CONFIG_IEC_JIFFYDOS - - -iec_rx_dispatch: - - lda IECPROTO - -#if CONFIG_IEC_JIFFYDOS - cmp #$01 - beq_far iec_rx_byte_jiffydos -#endif // CONFIG_IEC_JIFFYDOS - - jmp iec_rx_byte - - -#endif // any turbo supported diff --git a/c64/kernal/iec_fast/iec_tx_dispatch.s b/c64/kernal/iec_fast/iec_tx_dispatch.s deleted file mode 100644 index 88898664..00000000 --- a/c64/kernal/iec_fast/iec_tx_dispatch.s +++ /dev/null @@ -1,34 +0,0 @@ - -// -// Arbitration code for normal/turbo transfer -// - - -#if CONFIG_IEC_JIFFYDOS - - -iec_tx_dispatch: - - php // preserve C flag for EOI indication - lda IECPROTO - -#if CONFIG_IEC_JIFFYDOS - cmp #$01 - beq iec_tx_dispatch_jiffydos -#endif // CONFIG_IEC_JIFFYDOS - - // FALLTROUGH - -iec_tx_dispatch_normal: - - plp - jmp iec_tx_byte - -#if CONFIG_IEC_JIFFYDOS -iec_tx_dispatch_jiffydos: - plp - jmp iec_tx_byte_jiffydos -#endif // CONFIG_IEC_JIFFYDOS - - -#endif // any turbo supported diff --git a/c64/kernal/iec_fast/load_jiffydos.s b/c64/kernal/iec_fast/jiffydos_load.s similarity index 94% rename from c64/kernal/iec_fast/load_jiffydos.s rename to c64/kernal/iec_fast/jiffydos_load.s index acb0c7e5..5b6ca0c4 100644 --- a/c64/kernal/iec_fast/load_jiffydos.s +++ b/c64/kernal/iec_fast/jiffydos_load.s @@ -15,7 +15,7 @@ // will want to terminate the loading. -load_jiffydos: +jiffydos_load: // Timing is critical, do not allow interrupts sei @@ -48,7 +48,7 @@ load_jiffydos: // FALLTROUGH -load_jiffydos_loop: +jiffydos_load_loop: // Wait until device is ready to send (releases CLK) jsr iec_wait_for_clk_release @@ -118,27 +118,23 @@ load_jiffydos_loop: stx CIA2_PRA // If CLK line not active - this was the last byte - bvs load_jiffydos_end + bvs jiffydos_load_end // Handle EAL cpy #$FF - bne load_jiffydos_loop + bne jiffydos_load_loop inc EAL+1 - jmp load_jiffydos_loop + jmp jiffydos_load_loop -load_jiffydos_end: +jiffydos_load_end: // Save last byte tax // Update EAL - tya sec - adc EAL+0 - sta EAL+0 - bcc !+ - inc EAL+1 -!: + jsr iec_update_EAL_by_Y + // Indicate that no byte waits in output buffer lda #$00 sta C3PO diff --git a/c64/kernal/iec_fast/iec_rx_byte_jiffydos.s b/c64/kernal/iec_fast/jiffydos_rx_byte.s similarity index 96% rename from c64/kernal/iec_fast/iec_rx_byte_jiffydos.s rename to c64/kernal/iec_fast/jiffydos_rx_byte.s index d796a88f..cb55f3ec 100644 --- a/c64/kernal/iec_fast/iec_rx_byte_jiffydos.s +++ b/c64/kernal/iec_fast/jiffydos_rx_byte.s @@ -7,7 +7,7 @@ #if CONFIG_IEC_JIFFYDOS -iec_rx_byte_jiffydos: +jiffydos_rx_byte: // Timing is critical, do not allow interrupts sei @@ -81,14 +81,15 @@ iec_rx_byte_jiffydos: stx CIA2_PRA // If CLK line active - success - bvc iec_rx_byte_jiffydos_end + bvc jiffydos_rx_byte_end + // XXX the DATA line can probably be used to distinguish between file not found error and normal stream EOI jsr kernalstatus_EOI // FALLTROUGH -iec_rx_byte_jiffydos_end: +jiffydos_rx_byte_end: // Indicate that no byte waits in output buffer lda #$00 diff --git a/c64/kernal/iec_fast/iec_tx_byte_jiffydos.s b/c64/kernal/iec_fast/jiffydos_tx_byte.s similarity index 93% rename from c64/kernal/iec_fast/iec_tx_byte_jiffydos.s rename to c64/kernal/iec_fast/jiffydos_tx_byte.s index dd33e378..26be0860 100644 --- a/c64/kernal/iec_fast/iec_tx_byte_jiffydos.s +++ b/c64/kernal/iec_fast/jiffydos_tx_byte.s @@ -7,7 +7,7 @@ #if CONFIG_IEC_JIFFYDOS -iec_tx_byte_jiffydos: +jiffydos_tx_byte: // Timing is critical, do not allow interrupts sei @@ -70,11 +70,11 @@ iec_tx_byte_jiffydos: // Signal EOI if needed; cycles till no EOI: 3 + 3 + 2 + 2 + 4 = 14 lda C3PO ldx IECPROTO - beq iec_tx_byte_jiffydos_wait_eoi + beq jiffydos_tx_byte_wait_eoi // FALLTROUGH -iec_tx_byte_jiffydos_finalize: +jiffydos_tx_byte_finalize: ora #BIT_CIA2_PRA_CLK_OUT // pull CLK sta CIA2_PRA @@ -92,12 +92,12 @@ iec_tx_byte_jiffydos_finalize: jmp iec_return_success -iec_tx_byte_jiffydos_wait_eoi: +jiffydos_tx_byte_wait_eoi: sta CIA2_PRA jsr iec_wait20us lda C3PO - jmp iec_tx_byte_jiffydos_finalize + jmp jiffydos_tx_byte_finalize #endif // CONFIG_IEC_JIFFYDOS diff --git a/c64/kernal/iostack/load_save_common.s b/c64/kernal/iostack/load_save_common.s index 8f43b96b..a2d31714 100644 --- a/c64/kernal/iostack/load_save_common.s +++ b/c64/kernal/iostack/load_save_common.s @@ -75,19 +75,6 @@ lvs_handle_byte_verify: sec rts -#if CONFIG_IEC - -lvs_advance_EAL: - - // Advance pointer - inc EAL+0 - bne !+ - inc EAL+1 -!: - rts - -#endif - #if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO || CONFIG_IEC lvs_setup_MEMUSS: @@ -98,13 +85,26 @@ lvs_setup_MEMUSS: sta MEMUSS+1 rts -lvs_advance_MEMUSS_check_EAL: +#endif + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO || CONFIG_IEC + +#if !HAS_OPCODES_65CE02 + +lvs_advance_MEMUSS: // Advance pointer + inc MEMUSS+0 bne !+ inc MEMUSS+1 !: + rts + +#endif + +lvs_check_EAL: + lda MEMUSS+1 cmp EAL+1 bne !+ @@ -113,7 +113,6 @@ lvs_advance_MEMUSS_check_EAL: !: rts -#endif lvs_display_searching_for: diff --git a/c64/kernal/screen/chrout_screen_control.s b/c64/kernal/screen/chrout_screen_control.s index 83686dde..05f5f828 100644 --- a/c64/kernal/screen/chrout_screen_control.s +++ b/c64/kernal/screen/chrout_screen_control.s @@ -34,11 +34,18 @@ chrout_try_jumptable_loop_noquote: bne !+ // Found, perform a jump to subroutine +#if !HAS_OPCODES_65C02 lda chrout_screen_jumptable_hi, x pha lda chrout_screen_jumptable_lo, x pha rts +#else + txa + asl + tax + jmp (chrout_screen_jumptable, x) +#endif !: dex bpl chrout_try_jumptable_loop diff --git a/c64/kernal/screen/chrout_screen_jumptable_codes.s b/c64/kernal/screen/chrout_screen_jumptable_codes.s index 448c3f96..321309bc 100644 --- a/c64/kernal/screen/chrout_screen_jumptable_codes.s +++ b/c64/kernal/screen/chrout_screen_jumptable_codes.s @@ -1,6 +1,6 @@ // -// Jumptable for screen control coldes support. To improve performance, should be sorted +// Jumptable for screen control codes support. To improve performance, should be sorted // starting from the least probable routine. // @@ -36,6 +36,8 @@ __chrout_screen_jumptable_quote_guard: __chrout_screen_jumptable_codes_end: +#if !HAS_OPCODES_65C02 + chrout_screen_jumptable_lo: .byte <(chrout_screen_CLR - 1) @@ -85,3 +87,32 @@ chrout_screen_jumptable_hi: .byte >(chrout_screen_INS - 1) .byte >(chrout_screen_DEL - 1) .byte >(chrout_screen_RETURN - 1) + +#else + +chrout_screen_jumptable: + + .word chrout_screen_CLR + .word chrout_screen_HOME + .word chrout_screen_SHIFT_OFF + .word chrout_screen_SHIFT_ON + .word chrout_screen_TXT + .word chrout_screen_GFX + .word chrout_screen_RVS_OFF + .word chrout_screen_RVS_ON + .word chrout_screen_CRSR_RIGHT + .word chrout_screen_CRSR_LEFT + .word chrout_screen_CRSR_DOWN + .word chrout_screen_CRSR_UP +#if CONFIG_EDIT_STOPQUOTE + .word chrout_screen_STOP +#endif +#if CONFIG_EDIT_TABULATORS + .word chrout_screen_TAB_BW + .word chrout_screen_TAB_FW +#endif + .word chrout_screen_INS + .word chrout_screen_DEL + .word chrout_screen_RETURN + +#endif diff --git a/c64/kernal/screen/screen_add_40_to_pntr.s b/c64/kernal/screen/screen_add_40_to_pntr.s new file mode 100644 index 00000000..ff5d9f36 --- /dev/null +++ b/c64/kernal/screen/screen_add_40_to_pntr.s @@ -0,0 +1,10 @@ + + +screen_add_40_to_PNTR: + + lda PNTR + clc + adc #40 + sta PNTR + + rts diff --git a/c64/kernal/screen/screen_grow_logical_line.s b/c64/kernal/screen/screen_grow_logical_line.s index b90f36de..a4ac0b48 100644 --- a/c64/kernal/screen/screen_grow_logical_line.s +++ b/c64/kernal/screen/screen_grow_logical_line.s @@ -1,11 +1,24 @@ + +screen_grow_logical_line_done: + rts + screen_grow_logical_line: + + // Do not grow line if it is already grown ldy TBLX - // Don't grow line if it is already grown lda LDTBL,y - bpl !+ - jmp not_last_line // doneb grow line + bmi screen_grow_logical_line_done + + // Do not grow line if previous grown + dey + bmi !+ + lda LDTBL,y + bmi screen_grow_logical_line_done !: + iny + + // Mark current line as grown lda #$80 sta LDTBL,y @@ -13,29 +26,31 @@ screen_grow_logical_line: // If we are on the last physical line of the screen, // Then we need to scroll the screen up jsr screen_scroll_up_if_on_last_line - + + // Count the number of physical lines to scroll down + ldx #$01 + ldy TBLX +!: + iny + cpy #23 + bcs !+ + + lda LDTBL,y + bmi !- + inx + bne !- // branch always +!: + cpx #$00 + beq no_copy_down + // Scroll screen down to make space // As we are scrolling down, we start from the end, - // and work backwards. We can't be as simple and efficient + // and work backwards. We can't be as simple and efficient // here as we are for scrolling up, because we don't know // how much must be scrolled. // Simple solution is to work out how many physical lines // need shifting down, and then move lines at a time after // initialising the pointers to the end area of the screen. - ldx #25-2 - ldy #0 -count_rows_loop: - dex - lda LDTBL,y - bpl !+ - dex -!: iny - cpy TBLX - bne count_rows_loop - - cpx #0 - beq no_copy_down - bmi no_copy_down // Preserve EAL lda EAL+0 @@ -43,6 +58,8 @@ count_rows_loop: lda EAL+1 pha + // XXX fix TBLX value, it seems to show logical line number, which is wrong! + // Set pointers to end of screen line, and one line // above. (It is always one physical line, because // this can only happen when expanding a line from 40 to @@ -79,6 +96,12 @@ cl_inner: dey bpl cl_inner + // This ugly hack prevents cursor blink interference XXX solve this in better way + php + sei + jsr cursor_hide_if_visible + plp + // Decrement all pointers by 40 // Low bytes are in common pairs @@ -128,7 +151,7 @@ no_copy_down: lda #$20 sta (PNT),y dey - cpy #40 + cpy #39 bne !- rts diff --git a/c64/kernal/screen/screen_normalize_xy.s b/c64/kernal/screen/screen_normalize_xy.s index 147895a4..b4dc6ecd 100644 --- a/c64/kernal/screen/screen_normalize_xy.s +++ b/c64/kernal/screen/screen_normalize_xy.s @@ -14,13 +14,13 @@ screen_normalize_xy: lda #0 sta TBLX -!: jsr add_40_to_screen_x +!: jsr screen_add_40_to_PNTR // Check if line is linked, if so, add 40 again ldy TBLX lda LDTBL,y bpl !+ - jsr add_40_to_screen_x + jsr screen_add_40_to_PNTR !: x_not_negative: @@ -29,7 +29,7 @@ x_not_negative: lda LDTBL,y bpl !+ lda #79 - .byte $2C // BIT $nnnn, used to skip next instruction + skip_2_bytes_trash_nvz !: lda #39 cmp PNTR bcs x_not_too_big @@ -73,10 +73,3 @@ link_count_loop: sta TBLX y_ok: rts - -add_40_to_screen_x: - lda PNTR - clc - adc #40 - sta PNTR - rts diff --git a/c64/kernal/tape/load_tape_normal.s b/c64/kernal/tape/load_tape_normal.s index e9e69370..d35d59ce 100644 --- a/c64/kernal/tape/load_tape_normal.s +++ b/c64/kernal/tape/load_tape_normal.s @@ -7,30 +7,129 @@ // We have the following possible CPU frequencies: // - C64    PAL:  CPU frequency 0.985248 MHz // - C64    NTSC: CPU frequency 1.022727 MHz -// - VIC-20 PAL:  CPU frequency 1.108405 MHz -// - VIC-20 NTSC: CPU frequency 1.022727 MHz -// Since VIC-20 tapes are not expected to be loaded often, routine will be optimized for C64 timings - +// The clock difference is about 4% - it is unlikely to cause problems. +// // We have to distinguish the following pulse lengths (http://sidpreservation.6581.org/tape-format/): -// - S (short)    352 us -// - M (medium)   512 us -// - L (long)     672 us -// This gives us the following thresholds (where average CPU frequency is 1.0039875 MHz): -// - S vs M       432 us (54 8-cycle periods) -// - M vs L       592 us (74 8-cycle periods) - -// The following encoding is used: +// - S (short)    tap value $30 (PAL: 352 us) +// - M (medium)   tap value $42 (PAL: 512 us) +// - L (long)     tap value $56 (PAL: 672 us) +// +// The TAP format (http://unusedino.de/ec64/technical/formats/tap.html) uses a resolution of 8 PAL ticks; +// this implementation sets the timer for twice the precision (timer B is triggered every 4 CPU cycles), +// probably an overkill, but in realityy it does not cost us anything. +// +// So - we have the following thresholds: +// - S vs M       $72 (in our units of 4 ticks) +// - M vs L       $98 (in our units of 4 ticks) +// +// We need to recognize the following pulse sequences: +// // (S,M) = 0 bit // (M,S) = 1 bit // (L,M) = new-data marker // (L,S) = end-of-data marker +// XXX use pilot to calibrate reading speed + + #if CONFIG_TAPE_NORMAL load_tape_normal: - STUB_IMPLEMENTATION() + + jsr tape_ditch_verify // only LOAD is supported, no VERIFY + + // Setup CIA #2 timers + + ldx #$03 // set timer A to 4 ticks + stx CIA2_TIMALO // $DD04 + ldx #$00 + stx CIA2_TIMAHI // $DD05 + + stx CIA2_TIMBHI // $DD07 + dex // puts $FF - for running timer B as long as possible + stx CIA2_TIMBLO // $DD06 + + // Let timer A run continuously + + ldx #%00010001 // start timer, force latch reload + stx CIA2_CRA // $DD0E + + // Temporarily store MEMUSS in EAL + + lda MEMUSS+1 + sta EAL+1 + lda MEMUSS+0 + sta EAL+0 + + // Start playing + + jsr tape_ask_play + + // FALLTROUGH + +load_tape_normal_header: + + // Try to load header into tape buffer + + lda TAPE1+1 + sta MEMUSS+1 + lda TAPE1+0 + sta MEMUSS+0 + + // Retrieve the header + + jsr tape_normal_pilot_header + ldy #$C1 // size limit (including checksum) + jsr tape_normal_get_data + bcs load_tape_normal_header // unable to read block, try again + + // Check header type + + ldy #$00 // XXX probably can be optimized for 65C02 + lda (TAPE1),y + + cmp #$05 + beq_far tape_load_error // end of tape mark, nothing to load + + cmp #$01 + beq !+ + cmp #$03 + bne load_tape_normal_header // header types 1 and 3 are loadable, see Mapping the C64, page 77 + + lda #$01 + sta SA // this file is non-relocatable; override secondary address with 1 +!: + // Handle the header + + // Restore MEMUSS + + lda EAL+1 + sta MEMUSS+1 + lda EAL+0 + sta MEMUSS+0 + + // Handle the header + + jsr tape_handle_header + bcs load_tape_normal_header // if name does not match, look for other header + + // FALLTROUGH + +load_tape_normal_payload: + + // Retrieve data + + jsr tape_normal_pilot_data + ldy #$00 // no data size limit + jsr tape_normal_get_data + bcs_far tape_load_error + + jsr lvs_check_EAL + bne_far tape_load_error // amount of data read does not match header info + + jmp tape_load_success #endif diff --git a/c64/kernal/tape/load_tape_turbo.s b/c64/kernal/tape/load_tape_turbo.s index a676d6d5..d70facfc 100644 --- a/c64/kernal/tape/load_tape_turbo.s +++ b/c64/kernal/tape/load_tape_turbo.s @@ -8,6 +8,8 @@ // XXX use calibration bits to improve reading +// XXX find out how to use B0 tape timing +// XXX put header type into (TAPE1) #if CONFIG_TAPE_TURBO @@ -22,7 +24,10 @@ load_tape_turbo: lda #$FE // timer threshold for TurboTape sta CIA2_TIMALO // $DD04 + // Prepare for sound effects jsr tape_clean_sid + + // Start playing jsr tape_ask_play // FALLTROUGH @@ -32,37 +37,63 @@ load_tape_turbo_header: // Read file header; structure described here: // - https://www.luigidifraia.com/c64/docs/tapeloaders.html#turbotape64 // - // 1 byte (skipped) - file type (0 = data, odd value = relocatable, even value = non-relocatable) + // 1 byte - file type (0 = data, odd value = relocatable, even value = non-relocatable) // 2 bytes - start address // 2 bytes - end address + 1 - // 1 byte - if $0B (tape timing) contained at the time of saving + // 1 byte - if $B0 (tape timing) contained at the time of saving + // (we skip this one to match normal system header) // 16 bytes - filename, padded with 0x20 jsr tape_turbo_sync_header - ldy #$10 + ldy #$00 + sta (TAPE1), y // store header type + iny // FALLTROUGH -load_tape_turbo_header_loop: // this strange loop puts metadata after file name +load_tape_turbo_header_loop: jsr tape_turbo_get_byte sta (TAPE1), y iny - cpy #$15 + cpy #$05 bne !+ - ldy #$00 + jsr tape_turbo_get_byte // tape timing - skip this one !: - cpy #$10 + cpy #$C0 // header is 192 bytes long in total bne load_tape_turbo_header_loop + // For non-relocatable files, override secondary address + ldy #$00 // XXX optimize out for 65C02 + lda (TAPE1), y + beq !+ + and #$01 + bne !+ + lda #$01 // XXX for 65C02 just set the bit with one instruction + sta SA +!: + // Handle the header + jsr tape_clean_sid - jsr tape_handle_header + jsr tape_handle_header // XXX handle non-relocatable programs - any non-0 even header type bcs load_tape_turbo_header // if name does not match, look for other header // FALLTROUGH load_tape_turbo_payload: + // Copy helper byte store routine to RAM, provide default memory mapping + + ldx #(__tape_turbo_bytestore_size - 1) +!: + lda tape_turbo_bytestore_source, x + sta __tape_turbo_bytestore, x + dex + bpl !- + + lda CPU_R6510 + sta __tape_turbo_bytestore_defmap + // Initial checksum value lda #$00 @@ -77,13 +108,18 @@ load_tape_turbo_payload: load_tape_turbo_loop: jsr tape_turbo_get_byte - sta (MEMUSS),y + jsr __tape_turbo_bytestore // like 'sta (MEMUSS),y' - but under I/O eor PRTY // handle checksum sta PRTY // Advance MEMUSS (see Mapping the C64, page 36) - jsr lvs_advance_MEMUSS_check_EAL +#if !HAS_OPCODES_65CE02 + jsr lvs_advance_MEMUSS +#else + inw MEMUSS+0 +#endif + jsr lvs_check_EAL bne load_tape_turbo_loop // Get the checksum @@ -98,88 +134,5 @@ load_tape_turbo_loop: beq_far tape_load_success jmp tape_load_error -tape_turbo_get_byte: - - lda #$01 - sta ROPRTY // init the to-be-read byte with 1 -!: - jsr tape_turbo_get_bit - rol ROPRTY - bcc !- // is the initial 1 shifted into carry already? - lda ROPRTY // much nicer than ldx #8: dex: loop - - rts - - -tape_turbo_get_bit: - - lda #$10 -!: - bit CIA1_ICR // $DC0D - beq !- // busy loop to detect signal - lda CIA2_ICR // $DD0D - pha - lda #$19 - sta CIA2_CRA // $DD0E - pla - - pha // audio/video effects - asl - sta SID_SIGVOL - beq !+ -#if CONFIG_COLORS_BRAND && CONFIG_BRAND_ULTIMATE_64 - lda #$0B -#else - lda #$06 -#endif -!: - sta VIC_EXTCOL - pla - - lsr - rts - -tape_turbo_sync_common: - - jsr tape_turbo_get_bit - rol ROPRTY - lda ROPRTY - cmp #$02 - bne tape_turbo_sync_common - rts - -tape_turbo_sync_header: - - ldx #$FF -!: - ldy #$03 -!: - jsr tape_turbo_sync_common - dey - bne !- - dex - bne !-- - - // FALLTROUGH - -tape_turbo_sync_payload: - - jsr tape_turbo_sync_common -!: - ldx #$09 // 9,8,... is real turboTape -!: // I sometimes used 8,7,6... to avoid it being listed in vice :) - jsr tape_turbo_get_byte - cmp #$02 - beq !- - ldy #$00 -!: - cpx ROPRTY - bne tape_turbo_sync_payload - jsr tape_turbo_get_byte - dex - bne !- - - rts - #endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_common.s b/c64/kernal/tape/tape_common.s index 9a630bb0..a74db3af 100644 --- a/c64/kernal/tape/tape_common.s +++ b/c64/kernal/tape/tape_common.s @@ -7,21 +7,6 @@ #if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO -// -// Check if VERIFY asked - if yes, terminate loading -// - -tape_ditch_verify: - - lda VERCKK - bne !+ - rts -!: - pla - pla - jmp lvs_device_not_found_error - - // // Loading terminated by user // @@ -34,63 +19,6 @@ tape_break_error: jmp kernalerror_ROUTINE_TERMINATED -// -// Handle tape deck motor -// - -tape_motor_off: - - lda CPU_R6510 - ora #$20 - bne !+ // branch always - -tape_motor_on: - - lda CPU_R6510 - and #($FF - $20) -!: - sta CPU_R6510 - rts - - -// -// Handle screen (visible/blanked) + tape deck motor (on/off), -// store/restore screen color -// - -tape_screen_on_motor_off: - - jsr tape_motor_off - - lda COLSTORE - sta VIC_EXTCOL - - jmp screen_on - -tape_screen_off_motor_on: - lda VIC_EXTCOL - sta COLSTORE - - jsr screen_off - jmp tape_motor_on - - -// -// Clear the SID settings - for sound effects during LOAD -// - -tape_clean_sid: - - lda #$00 - ldy #$1C -!: - sta __SID_BASE, y - dey - bpl !- - - rts - - // // Ask user to press PLAY on tape deck, // Unless user cancelled loading, blank screen and start motor @@ -147,12 +75,12 @@ tape_handle_header: ldx #__MSG_KERNAL_FOUND jsr print_kernal_message - ldy #$00 + ldy #$05 !: lda (TAPE1), y jsr JCHROUT iny - cpy #$10 + cpy #$15 bne !- // Header, wait for user decision @@ -167,7 +95,7 @@ tape_handle_header: // Setup STAL and EAL - ldy #$10 + ldy #$01 lda (TAPE1), y sta STAL+0 diff --git a/c64/kernal/tape/tape_common_clean_sid.s b/c64/kernal/tape/tape_common_clean_sid.s new file mode 100644 index 00000000..fa135bf4 --- /dev/null +++ b/c64/kernal/tape/tape_common_clean_sid.s @@ -0,0 +1,22 @@ + +// +// Clear the SID settings - for sound effects during LOAD +// + + +#if CONFIG_TAPE_TURBO + + +tape_clean_sid: + + lda #$00 + ldy #$1C +!: + sta __SID_BASE, y + dey + bpl !- + + rts + + +#endif diff --git a/c64/kernal/tape/tape_common_ditch_verify.s b/c64/kernal/tape/tape_common_ditch_verify.s new file mode 100644 index 00000000..c0c6edb0 --- /dev/null +++ b/c64/kernal/tape/tape_common_ditch_verify.s @@ -0,0 +1,21 @@ + +// +// Check if VERIFY asked - if yes, terminate loading +// + + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + +tape_ditch_verify: + + lda VERCKK + bne !+ + rts +!: + pla + pla + jmp lvs_device_not_found_error + + +#endif diff --git a/c64/kernal/tape/tape_common_motor.s b/c64/kernal/tape/tape_common_motor.s new file mode 100644 index 00000000..800a25df --- /dev/null +++ b/c64/kernal/tape/tape_common_motor.s @@ -0,0 +1,25 @@ + +// +// Handle tape deck motor +// + + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + +tape_motor_off: + + lda CPU_R6510 + ora #$20 + bne !+ // branch always + +tape_motor_on: + + lda CPU_R6510 + and #($FF - $20) +!: + sta CPU_R6510 + rts + + +#endif diff --git a/c64/kernal/tape/tape_common_screen.s b/c64/kernal/tape/tape_common_screen.s new file mode 100644 index 00000000..f8fb8814 --- /dev/null +++ b/c64/kernal/tape/tape_common_screen.s @@ -0,0 +1,27 @@ + +// +// Handle screen (visible/blanked) + tape deck motor (on/off), +// store/restore screen color +// + + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + +tape_screen_on_motor_off: + + jsr tape_motor_off + + lda COLSTORE + sta VIC_EXTCOL + + jmp screen_on + +tape_screen_off_motor_on: + lda VIC_EXTCOL + sta COLSTORE + + jsr screen_off + jmp tape_motor_on + +#endif diff --git a/c64/kernal/tape/tape_normal_get_bit.s b/c64/kernal/tape/tape_normal_get_bit.s new file mode 100644 index 00000000..54f9b969 --- /dev/null +++ b/c64/kernal/tape/tape_normal_get_bit.s @@ -0,0 +1,57 @@ + +// +// Tape (normal) helper routine - bit reading +// +// Returns bit in Zero flag, Carry set means error, on 0 bit .A is 0 too +// + + +#if CONFIG_TAPE_NORMAL + + +tape_normal_get_bit: + + // Fetch the first pulse + + jsr tape_normal_get_pulse + bcc tape_normal_get_bit_1 + + // First impulse was short, second should be medium + + jsr tape_normal_get_pulse + bcs tape_normal_get_bit_error + + // We have a bit '0' + + // Carry flag already clear + lda #$00 + + // FALLTROUGH + +tape_normal_get_bit_done: + + sta VIC_EXTCOL + rts + + +tape_normal_get_bit_1: + + // First impulse was medium, second should be short + + jsr tape_normal_get_pulse + bcc tape_normal_get_bit_error + + // We have a bit '1' + + clc + lda #$06 + bne tape_normal_get_bit_done // branch always + + +tape_normal_get_bit_error: + + sec + rts + + +#endif // CONFIG_TAPE_NORMAL diff --git a/c64/kernal/tape/tape_normal_get_byte.s b/c64/kernal/tape/tape_normal_get_byte.s new file mode 100644 index 00000000..d63c1d0d --- /dev/null +++ b/c64/kernal/tape/tape_normal_get_byte.s @@ -0,0 +1,70 @@ + +// +// Tape (normal) helper routine - byte reading +// +// Returns byte in .A (also sotred in INBIT), Carry flag set = error +// + + +#if CONFIG_TAPE_NORMAL + + +tape_normal_get_byte: + + // Init parity bit and canary bit + lda #$01 + sta PRTY + lda #%01111111 // canary bit is 0 + sta INBIT + + // Now fetch individual bits + +tape_normal_get_byte_loop: + + jsr tape_normal_get_bit + bcs tape_normal_get_byte_error + beq !+ + + // Handle parity bit + lda #$01 + eor PRTY + sta PRTY + + sec +!: // moved bit state from Zero to Carry flag + + ror INBIT // put the bit in + bcs tape_normal_get_byte_loop // loop if no canary bit reached + + // Byte retrieved (on stack), now we need to validate the parity + + jsr tape_normal_get_bit + bcs tape_normal_get_byte_error + beq !+ + lda #$01 +!: + eor PRTY + bne tape_normal_get_byte_error + + // Checksum validated succesfully + + ldx #$0B + // Carry already clear + + // FALLTROUGH + +tape_normal_get_byte_done: + + stx VIC_EXTCOL + lda INBIT + rts + + +tape_normal_get_byte_error: + + ldx #$09 + sec // make sure Carry is set to indicate error + bcs tape_normal_get_byte_done + + +#endif diff --git a/c64/kernal/tape/tape_normal_get_data.s b/c64/kernal/tape/tape_normal_get_data.s new file mode 100644 index 00000000..21972deb --- /dev/null +++ b/c64/kernal/tape/tape_normal_get_data.s @@ -0,0 +1,73 @@ + +// +// Tape (normal) helper routine - data block reading +// +// Stores data starting from MEMUSS, Carry set means error, on 0 bit .A is 0 too +// .Y not equal to 0 - returns error if data block is longer (length includes checksum) + + +// XXX improve error handling - do not ignore second copy, handle damaged sync part + + +#if CONFIG_TAPE_NORMAL + + +tape_normal_get_data: + + // Store block size limit + sty XSAV + + // Initialize checksum (RIPRTY, see http://sta.c64.org/cbm64mem.html) + lda #$00 + sta RIPRTY + + // Read the pilot and sync of the block + ldy #$89 + jsr tape_normal_sync + bcs tape_normal_get_block_done // XXX make it more error resistant + jsr tape_normal_get_marker + +tape_normal_get_data_loop: + + jsr tape_normal_get_byte + bcs tape_normal_get_block_done // error reading byte - fatal for now + jsr tape_normal_get_marker + bcs tape_normal_get_checksum // end of data for the block + + // Store byte, calculate checksum + lda INBIT + ldy #$00 // XXX probably can be optimized out for 65C02 + sta (MEMUSS), y + eor RIPRTY + sta RIPRTY + + // Advance pointer +#if !HAS_OPCODES_65CE02 + jsr lvs_advance_MEMUSS +#else + inw MEMUSS+0 +#endif + + // Check block length limit + lda XSAV + beq tape_normal_get_data_loop // no limit requested + dec XSAV + bne tape_normal_get_data_loop + + sec + rts + +tape_normal_get_checksum: // XXX handle second copy, with pilot starting from $09 + + lda INBIT + eor RIPRTY + cmp #$01 // sets Carry if checksum verification fails + + // FALLTROUGH + +tape_normal_get_block_done: + + rts + + +#endif diff --git a/c64/kernal/tape/tape_normal_get_marker.s b/c64/kernal/tape/tape_normal_get_marker.s new file mode 100644 index 00000000..eaa6c219 --- /dev/null +++ b/c64/kernal/tape/tape_normal_get_marker.s @@ -0,0 +1,23 @@ + +// +// Tape (normal) helper routine - marker reading +// +// Reeturns marker type in Carry flag, set = end of data +// + + +#if CONFIG_TAPE_NORMAL + + +tape_normal_get_marker: + + // (L,M) - end of byte, (L,S) - end of data + + jsr tape_normal_get_pulse + cmp #($FF - $98 - $04) + bcs tape_normal_get_marker // too short for a long pulse + + jmp tape_normal_get_pulse + + +#endif diff --git a/c64/kernal/tape/tape_normal_get_pulse.s b/c64/kernal/tape/tape_normal_get_pulse.s new file mode 100644 index 00000000..cbddc175 --- /dev/null +++ b/c64/kernal/tape/tape_normal_get_pulse.s @@ -0,0 +1,41 @@ + +// +// Tape (normal) helper routine - pulse reading +// +// Returns pulse length (with a bias, see comments) in .A +// + + +#if CONFIG_TAPE_NORMAL + + +tape_normal_get_pulse: + + // Contrary to original ROM implementation we do not use interrupts + // (see http://unusedino.de/ec64/technical/formats/tap.html) - busy wait + // implementation is probably just shorter + + lda #$10 +!: + bit CIA1_ICR // $DC0D + beq !- // busy loop to detect signal, restart timer afterwards + lda CIA2_TIMBLO // $DD06 + ldx #%01010001 // start timer, force latch reload, count timer A underflows + stx CIA2_CRB // $DD0F + + // Since the signal appeared to the point of timer restart we used: + // bit - 4 cycles + // beq - 2 cycles + // lda - 4 cycles + // ldx - 2 cycles + // stx - 4 cycles + // plus average 3 cycles (bit + beq time divided by 2) from value change to 'bit' instruction + // minus average 2 cycles due to timer A running continouslyy (might start before the pulse) + // this is total 17 cycles, or $4 periods of 4 ticks (timer A) each - we need to take it into account + // every time we check the pulse length + + cmp #($FF - $72 - $04) // short vs medium is the default check + rts + + +#endif diff --git a/c64/kernal/tape/tape_normal_pilot.s b/c64/kernal/tape/tape_normal_pilot.s new file mode 100644 index 00000000..a6f1e577 --- /dev/null +++ b/c64/kernal/tape/tape_normal_pilot.s @@ -0,0 +1,72 @@ + +// +// Tape (turbo) helper routine - handling the pilot +// + +// Injest the pilot - series of short pulses. According to http://sidpreservation.6581.org/tape-format/ +// it consist of the following number of pulses: +// - $6A00 for header +// - $1A00 for data and seq block header +// - $4F for repeated header/data + + +#if CONFIG_TAPE_NORMAL + + + +tape_normal_pilot_short: // require 1x $40 pulses + + lda #$01 + + // FALLTROUGH + +tape_normal_pilot_common: + + sta FSBLK + + // FALLTROUGH + +tape_normal_pilot_common_restart: + + lda FSBLK + sta ROPRTY + + // FALLTROUGH + +tape_normal_pilot_common_loop_outer: + + ldy #$40 + + // FALLTROUGH + +tape_normal_pilot_common_loop_inner: + + jsr tape_normal_get_pulse + bcc tape_normal_pilot_common_restart // not a pilot - try again + + dey + bne tape_normal_pilot_common_loop_inner + + dec ROPRTY + bne tape_normal_pilot_common_loop_outer + + rts + + + +tape_normal_pilot_data: // require 4x $40 pulses + + lda #$04 + + skip_2_bytes_trash_nvz + + // FALLTROUGH + +tape_normal_pilot_header: // require 128x $40 pulses + + lda #$80 + + jmp tape_normal_pilot_common // XXX calibrate tape speed afterwards + + +#endif diff --git a/c64/kernal/tape/tape_normal_sync.s b/c64/kernal/tape/tape_normal_sync.s new file mode 100644 index 00000000..7969f958 --- /dev/null +++ b/c64/kernal/tape/tape_normal_sync.s @@ -0,0 +1,37 @@ + +// +// Tape (turbo) helper routine - synchronization handling +// +// .Y should contain start value (either $89 or $09) +// Carry set = failed + + +#if CONFIG_TAPE_NORMAL + + +tape_normal_sync: + + // Injest bytes of decreasing values + + jsr tape_normal_get_marker // XXX handle result + jsr tape_normal_get_byte + bcs tape_normal_sync_fail + + cpy INBIT // INBIT contains same value as .A + bne tape_normal_sync_fail + + dey + and #%01111110 + bne tape_normal_sync // branch if not $80 and not $00 + + clc + rts + + +tape_normal_sync_fail: + + sec + rts + + +#endif diff --git a/c64/kernal/tape/tape_turbo_bytestore.s b/c64/kernal/tape/tape_turbo_bytestore.s new file mode 100644 index 00000000..66c94081 --- /dev/null +++ b/c64/kernal/tape/tape_turbo_bytestore.s @@ -0,0 +1,40 @@ + +// +// Tape (turbo) helper routine - storing byte uder I/O +// + +// This helper routine is meant to be copiet to the start of CPU stack. +// Original ROM tape loading routines uses this area to store information +// about bytes that did not read properly for the first time +// (see Mapping the C64, page 47); this mechanism is useless for turbo tape, +// but it means we can safely use this area for our purposes + + +#if CONFIG_TAPE_TURBO + + +.label __tape_turbo_bytestore = STACK +.label __tape_turbo_bytestore_defmap = __tape_turbo_bytestore + 7 +.label __tape_turbo_bytestore_size = __tape_turbo_bytestore_source_end - tape_turbo_bytestore_source + + +tape_turbo_bytestore_source: + + // Set all memory as RAM, tape motor ON + ldx #$00 + stx CPU_R6510 + + // Store byte in memory + sta (MEMUSS), y + + // Restore default memory layout + ldx #$00 // value will be determined later, offset from start: 7 bytes + stx CPU_R6510 + + // Go back + rts + +__tape_turbo_bytestore_source_end: + + +#endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_turbo_get_bit.s b/c64/kernal/tape/tape_turbo_get_bit.s new file mode 100644 index 00000000..a6cf343a --- /dev/null +++ b/c64/kernal/tape/tape_turbo_get_bit.s @@ -0,0 +1,38 @@ + +// +// Tape (turbo) helper routine - bit reading +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +#if CONFIG_TAPE_TURBO + + +tape_turbo_get_bit: + + lda #$10 +!: + bit CIA1_ICR // $DC0D + beq !- // busy loop to detect signal + lda CIA2_ICR // $DD0D + pha + lda #%00011001 // start timer, one-shot, force latch reload + sta CIA2_CRA // $DD0E + pla + + pha // audio/video effects + asl + sta SID_SIGVOL + beq !+ + lda #$06 +!: + sta VIC_EXTCOL + pla + + lsr + rts + + +#endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_turbo_get_byte.s b/c64/kernal/tape/tape_turbo_get_byte.s new file mode 100644 index 00000000..d1ee0ded --- /dev/null +++ b/c64/kernal/tape/tape_turbo_get_byte.s @@ -0,0 +1,28 @@ + +// +// Tape (turbo) helper routine - byte reading +// +// Returns byte in .A +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +#if CONFIG_TAPE_TURBO + + +tape_turbo_get_byte: + + lda #$01 + sta INBIT // init the to-be-read byte with 1 (canary bit to mark loop end) +!: + jsr tape_turbo_get_bit + rol INBIT + bcc !- // is the initial 1 shifted into carry already? + lda INBIT // much nicer than ldx #8: dex: loop + + rts + + +#endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_turbo_sync.s b/c64/kernal/tape/tape_turbo_sync.s new file mode 100644 index 00000000..1c1aedc6 --- /dev/null +++ b/c64/kernal/tape/tape_turbo_sync.s @@ -0,0 +1,56 @@ + +// +// Tape (turbo) helper routine - synchronization handling +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +#if CONFIG_TAPE_TURBO + + +tape_turbo_sync_common: + + jsr tape_turbo_get_bit + rol INBIT + lda INBIT + cmp #$02 + bne tape_turbo_sync_common + rts + +tape_turbo_sync_header: + + ldx #$FF +!: + ldy #$03 +!: + jsr tape_turbo_sync_common + dey + bne !- + dex + bne !-- + + // FALLTROUGH + +tape_turbo_sync_payload: + + jsr tape_turbo_sync_common +!: + ldx #$09 // 9, 8, ... +!: + jsr tape_turbo_get_byte + cmp #$02 + beq !- + ldy #$00 +!: + cpx INBIT + bne tape_turbo_sync_payload + jsr tape_turbo_get_byte + dex + bne !- + + rts + + +#endif // CONFIG_TAPE_TURBO diff --git a/c64/kernal/time/udtim.s b/c64/kernal/time/udtim.s index 65dc6aaf..01bb3b91 100644 --- a/c64/kernal/time/udtim.s +++ b/c64/kernal/time/udtim.s @@ -14,9 +14,13 @@ UDTIM: // (24 hours * 60 minutes * 60 seconds * 60 jiffies), // after this time we have to reset the clock. +#if !HAS_OPCODES_65CE02 inc TIME+0 bne udtim_time_done // done with clock inc TIME+1 +#else + inw TIME+0 +#endif bne udtim_clock_rollover inc TIME+2 diff --git a/doc/Protocol-DolphinDOS.md b/doc/Protocol-DolphinDOS.md new file mode 100644 index 00000000..776cf55c --- /dev/null +++ b/doc/Protocol-DolphinDOS.md @@ -0,0 +1,42 @@ + +# DolphinDOS fast protocol description + +Here is a description of the DolphinDOS protocol, as implemented in Open ROMs, from the perspective of IEC bus controller. It is reverse engineered by observing IEC logs generated by VICE emulator. + +For legal reasons, no disassembling of the DolphinDOS ROMs was performed (only IEC transmission logs and hardware register usage was checked, using specially prepared emulator). Thus, the information provided here might be incomplete or not fully accurate! + +## Documents, samples + +None, I'm afraid - AFAIK this is the first attempt to document the protocol. Please make sure you are familiar with the IEC protocol in general, I highly recommend studying a guide by Michael Steil, available here: https://www.pagetable.com/?p=1135. + +## Tools + +- for experimentation and debugging VICE emulator was used - you'll need a custom compilation with `--enable-debug`, either from SVN or release >= 3.4. Additionally, you will need the logs from CIA access - I have added mine in *c64cia.c* file - you'll need to know access to $DD01 (CIA2 port B - for data transfer), $DD03 (it's direction register), and $DD0D (CIA2 ICR - interrupt control register). + +## Timing information + +Timing is no more strict than standard IEC protocol - I have checked using VICE monitor (added watches), that DolphinDOS ROM does not touch VIC-II registers to disable sprites (`SPENA` - $D015) or observe incoming badlines (`RASTER` - $D012, `SCROLY` - $D011), one can observe that it does not blank the screen either. It's enoguh to just mask the interrupts, like with a standard IEC protocol. + +## Protocol detection + +Detection happens after `OPEN` (0xF0 - 0xFF) or `REOPEN` (0x60 - 0x6F) IEC command is sent from the controller and is very simple. + +The CIA2 port B has to be set for reading (interrupts for the port are disabled by writing $7F to $DD0D). The controller constantly reads (not sure if there is a countdown or timeout in the original DolphinDOS ROM, countdoown started from $20 seems more than enough) the CIA2 interrupt control and port B registers; when ICR reads $10 (again - not sure if just the bit is checked, or the whole register), bus controller assumes the receiver talks the DolphinDOS protocol. + +Note: detection only works under ATN, should be performed before the controller performs a turnover to listener! + +## Sending a command + +IEC commands are sent normally, with the additional protocol detection flow after some of them (see above). + +## Turnover + +Turnover (both to listener and to back to talker) is performed as usual. + +## Sending a byte + +Byte transmission reuses quite some part of the standard IEC byte transmission mechanism. At the moment where EOI has been possibly signalled, controller using the standard protocol pulls CLK to indicate invalid DATA - but when DolphinDOS is in use, the C64 instead puts the byte in CIA2 port B (has to be set for output) and pulls the CLK to indicate data is now valid. Afterwards, the reader can pull DATA to indicate it's busy - everything continues the standard way. + +## Receiving a byte + +Byte reception works almost exactly like with the original IEC protocol, with one notable exception, saving immense amount of time: just after checking for EOI, when talker already pulled CLK line, the C64 retrieves a byte by simply reading CIA2 port B register (after protocol detection flow it's direction should already be set accordingly). Afterwards, C64 acknowledges the byte by pulling DATA line - like with a standard IEC communication flow. diff --git a/doc/Protocol-JiffyDOS.md b/doc/Protocol-JiffyDOS.md index f3773ad7..32893373 100644 --- a/doc/Protocol-JiffyDOS.md +++ b/doc/Protocol-JiffyDOS.md @@ -3,7 +3,7 @@ Here is a description of the JiffyDOS protocol, as implemented in Open ROMs, from the perspective of IEC bus controller. It is partially based on the documentation found on the internet, and partially reverse engineered by observing IEC logs generated by VICE emulator. -For legal reasons, no disassembling of the JiffyDOS ROMs was performed (only IEC transmission logs were checked), I also refrained myself from checking non-commercial 6502 JiffyDOS implementations (as they might be based on disassembled ROMs) - this, unfortunately, ruled out most of the documentation from www.nlq.de page, as it mostly shows the commented original source code. +For legal reasons, no disassembling of the JiffyDOS ROMs was performed (only IEC transmission logs were checked), I also refrained myself from checking non-commercial 6502 JiffyDOS implementations (as they might be based on disassembled ROMs) - this, unfortunately, ruled out most of the documentation from www.nlq.de page, as it mostly shows the commented original source code. Thus, the information provided here might be incomplete or not fully accurate! ## Documents, samples @@ -11,6 +11,8 @@ For legal reasons, no disassembling of the JiffyDOS ROMs was performed (only IEC - [2] SD2IEC source code - see https://github.com/rkrajnc/sd2iec/blob/master/src/ especially files: [lpc17xx/fastloader-ll.c](https://github.com/rkrajnc/sd2iec/blob/master/src/lpc17xx/fastloader-ll.c), [avr/fastloader-ll.S](https://github.com/rkrajnc/sd2iec/blob/master/src/avr/fastloader-ll.S) and [iec.c](https://github.com/rkrajnc/sd2iec/blob/master/src/iec.c) - [3] Fast loader idea and sample code - https://www.pagetable.com/?p=568 +Also please make sure you are familiar with the IEC protocol in general, I highly recommend studying a guide by Michael Steil, available here: https://www.pagetable.com/?p=1135. + ## Tools - for experimentation and debugging VICE emulator was used - you'll need a custom compilation with `--enable-debug`, either from SVN or release >= 3.4 @@ -19,8 +21,8 @@ For legal reasons, no disassembling of the JiffyDOS ROMs was performed (only IEC When sending/receiving a byte, the JiffyDOS protocol timing is much more strict than the standard IEC. It is not enough to mask the interrupts - one has to make sure nothing will steal the CPU cycles. There are two ways to achieve this: -- disable the screen completely for the duration of transmission; since VIC-II checks the bit in SCROLY register once per frame only, the code has to wait till the beginning of the next frame -- disable the sprites for the duration of transmission and synchronize with VIC-II RASTER/SCROLY registers to avoid badlines. Current implementation simply avoids transmission two lines before the badline; I suspect it can be reduced to one line, but it would need even more careful timing and would definitely mean inlining some subroutines - probably not worth the effort and increased code size +- disable the screen completely for the duration of transmission; since VIC-II checks the bit in `SCROLY` register once per frame only, the code has to wait till the beginning of the next frame +- disable the sprites for the duration of transmission and synchronize with VIC-II `RASTER` ($D012) / `SCROLY` ($D011) registers to avoid badlines. Current implementation simply avoids transmission two lines before the badline; I suspect it can be reduced to one line, but it would need even more careful timing and would definitely mean inlining some subroutines - probably not worth the effort and increased code size Timing details are omitted by purpose - they are already described in [2], besides most of the time it was determined by observing VICE IEC logs and (for example) adding NOPs when necessary. The protocool is not cycle-exact, so our implementation probably behaves slightly differently than the original one. @@ -33,7 +35,7 @@ Protocol detection happens when the IEC bus controller sends a command (under AT ## Sending a command -IEC commands are sent from the normally (with the additional protocol detection flow before the last bit). Althought it would be enough to perform detection within the TALK and LISTEN commands only, the original JiffyDOS ROMs tries to detect it every time. Omitting the detection is definitely not safe (depending on the command, it migh even cause the communication with device to fail, at least the 1541 JiffyDOS ROM shows such behavior). Moreover, it seems that only TALK/LISTEN commands cause the device to respond by pulling DATA; the controller side implementation has to be prepared for this. +IEC commands are sent normally (with the additional protocol detection flow before the last bit). Althought it would be enough to perform detection within the TALK and LISTEN commands only, the original JiffyDOS ROMs tries to detect it every time. Omitting the detection is definitely not safe (depending on the command, it migh even cause the communication with device to fail, at least the 1541 JiffyDOS ROM shows such behavior). Moreover, it seems that only TALK/LISTEN commands cause the device to respond by pulling DATA; the controller side implementation has to be prepared for this. ## Turnover diff --git a/src/build_segment.cc b/src/build_segment.cc index a55a1b96..d1dc4e59 100644 --- a/src/build_segment.cc +++ b/src/build_segment.cc @@ -420,7 +420,7 @@ void prepareBinningProblem() logOutput << "\n" << "free space (after floating routines are placed): " << - std::to_string(CMD_hiAddress - CMD_loAddress - GLOBAL_totalRoutinesSize) << "\n" << + std::to_string(CMD_hiAddress - CMD_loAddress + 1 - GLOBAL_totalRoutinesSize) << "\n" << "number of floating routines: " << std::to_string(GLOBAL_binningProblem.floatingRoutines.size()) << "\n" << "number of gaps for the floating routines: " << @@ -730,7 +730,6 @@ void BinningProblem::fillGap(DualStream &logOutput, int gapAddress, const std::l else if (!isSolved()) { logOutput << "filled in - dropped bytes: " << gaps[gapAddress] - offset << "\n"; - statFree -= gaps[gapAddress] - offset; statWasted += gaps[gapAddress] - offset; } else @@ -748,7 +747,8 @@ void BinningProblem::performObviousSteps(DualStream &logOutput) std::string spacing; - bool repeat = true; + bool repeat = true; + bool lastGap = false; while (repeat && !floatingRoutines.empty() && !gaps.empty()) { repeat = false; @@ -766,6 +766,13 @@ void BinningProblem::performObviousSteps(DualStream &logOutput) } } + if (!lastGap && gaps.size() == 1) + { + lastGap = true; + logOutput << "selected gap: $" << std::hex << gapAddress << std::dec << + " (size: " << gaps[gapAddress] << ") - the last remaining" << "\n"; + } + if (matchingGaps == 1) { // Routine can only be placed in this particular gap - do so @@ -775,8 +782,11 @@ void BinningProblem::performObviousSteps(DualStream &logOutput) fixedRoutines[targetAddr] = floatingRoutines.back(); statFree -= routineSize; - logOutput << "forced reducing gap $" << std::hex << gapAddress << std::dec << " to size " << - gaps[gapAddress] << "\n"; + if (gaps.size() > 1) + { + logOutput << "forced reducing gap $" << std::hex << gapAddress << std::dec << + " to size " << gaps[gapAddress] << "\n"; + } spacing.resize(GLOBAL_maxFileNameLen + 4 - floatingRoutines.back()->fileName.length(), ' '); logOutput << " $" << std::hex << targetAddr << std::dec << ": " << @@ -867,7 +877,7 @@ void Solver::run() logOutput << "segment statistics:" << "\n"; // logOutput << " - total size: " << problem.statSize << "\n"; - for BASIC contains filling gap too logOutput << " - wasted bytes: " << problem.statWasted << "\n"; - logOutput << " - still free: " << problem.statFree << "\n\n"; + logOutput << " - still free: " << problem.statFree - problem.statWasted << "\n\n"; } // Close the log file diff --git a/strings/0091B2C8 b/strings/0091B2C8 new file mode 100644 index 00000000..e6edd32c --- /dev/null +++ b/strings/0091B2C8 @@ -0,0 +1,3 @@ +$00 + STA ($B2),Y + INY + +Small part of the loop storing data in a tape buffer - trivial, not copyrightable. diff --git a/strings/00B1B2C905 b/strings/00B1B2C905 new file mode 100644 index 00000000..4984bdc1 --- /dev/null +++ b/strings/00B1B2C905 @@ -0,0 +1,3 @@ +$00 + LDA ($B2),Y + CMP #$05 + +Check if end of tape mark - trivial, not copyrightable. diff --git a/strings/01459B859B b/strings/01459B859B new file mode 100644 index 00000000..74af77ab --- /dev/null +++ b/strings/01459B859B @@ -0,0 +1,3 @@ +$01 + EOR $9B + STA $9B + +Small part of code calculating parity/XOR type checksum. Trivial, not copyrightable. diff --git a/strings/01B1B285 b/strings/01B1B285 new file mode 100644 index 00000000..4d60d6e5 --- /dev/null +++ b/strings/01B1B285 @@ -0,0 +1,3 @@ +$01 + LDA ($B2),Y + STA (zeropage address does not match) + +Instruction + some parts. Trivial, not copyrightable. diff --git a/strings/01F008C903 b/strings/01F008C903 new file mode 100644 index 00000000..cf84a034 --- /dev/null +++ b/strings/01F008C903 @@ -0,0 +1,3 @@ +$01 + BEQ (offset matches) + CMP #$03 + +Comparing .A with #$03 depending on a CPU flag - nothing creative, not copyrightable. diff --git a/strings/02D0034C b/strings/02D0034C new file mode 100644 index 00000000..27f96238 --- /dev/null +++ b/strings/02D0034C @@ -0,0 +1,3 @@ +$02 + BNE (skip next instruction) + JMP (address does not match) + +Instruction + some parts. Trivial, not copyrightable. diff --git a/strings/04A90185 b/strings/04A90185 new file mode 100644 index 00000000..95920e5c --- /dev/null +++ b/strings/04A90185 @@ -0,0 +1,3 @@ +$04 + LDA #$01 + STA (zeropage address does not match) + +Instruction + some parts. Trivial, not copyrightable. diff --git a/strings/18D049028D18D0 b/strings/18D049028D18D0 new file mode 100644 index 00000000..733902f0 --- /dev/null +++ b/strings/18D049028D18D0 @@ -0,0 +1,3 @@ +$D018 + EOR #$02 + STA $D018 + +Small part of code manipulating a bit in a documented I/O register. Trivial, not copyrightable. diff --git a/strings/22F007A9 b/strings/22F007A9 new file mode 100644 index 00000000..5be542fd --- /dev/null +++ b/strings/22F007A9 @@ -0,0 +1,3 @@ +$22 + BEQ (offset matches) + LDA (immediate value does not match) + +Instruction + some parts. Trivial, not copyrightable. diff --git a/strings/45AB85AB b/strings/45AB85AB new file mode 100644 index 00000000..316490e2 --- /dev/null +++ b/strings/45AB85AB @@ -0,0 +1,3 @@ +LDA $A7 + EOR $AB + +Small part of code calculating parity/XOR type checksum. Trivial, not copyrightable. diff --git a/strings/45AB85AB20 b/strings/45AB85AB20 new file mode 100644 index 00000000..3d39e074 --- /dev/null +++ b/strings/45AB85AB20 @@ -0,0 +1,3 @@ +EOR $AB + STA $AB + RTS + +Small part of code calculating parity/XOR type checksum. Trivial, not copyrightable. diff --git a/strings/52443643465458375947384248555639494A304D4B4F4E2B504C2D2E3A402C5C2A3B13 b/strings/52443643465458375947384248555639494A304D4B4F4E2B504C2D2E3A402C5C2A3B13 new file mode 100644 index 00000000..6b6aa28d --- /dev/null +++ b/strings/52443643465458375947384248555639494A304D4B4F4E2B504C2D2E3A402C5C2A3B13 @@ -0,0 +1,16 @@ +List of key codes generated when certain key combinations are pressed + +This sequence is a list of which ASCII/PETSCII code should be generated +when certain key combinations are pressed, based on the keyboard matrix +position. That is, it is a sequence in keyboard matrix order, of the +codes that should be generated. Thus it is a list of facts, which cannot +be copyright, according to the long standing precedent under US copyright law: + +https://www.law.cornell.edu/copyright/cases/499_US_340.htm + +Similar decisions exist in other jurisidctions. + +Note also that the matrix order list of keys is a fact of the C64 hardware, +and which has been repeated in many publications, such as Compute's Mapping the 64, +without challenge from the C64 ROM copyright owners, which serves to reinforce the +claim that this sequence of bytes is not copyrightable. diff --git a/strings/60A20086 b/strings/60A20086 new file mode 100644 index 00000000..633cd01f --- /dev/null +++ b/strings/60A20086 @@ -0,0 +1,3 @@ +RTS + LDX #$00 + STX (zeropage address does not match) + +Subroutine starting buy using .X to store 0 somewhere (place does not match). Trivial - not copyrightable. diff --git a/strings/60A5010920 b/strings/60A5010920 new file mode 100644 index 00000000..4ce39500 --- /dev/null +++ b/strings/60A5010920 @@ -0,0 +1,3 @@ +RTS + LDA $01 + ORA #$20 (turning motor off) + +Small part of code manipulating a bit in a documented I/O register. Trivial, not copyrightable. diff --git a/strings/60A590F004 b/strings/60A590F004 new file mode 100644 index 00000000..b7fca629 --- /dev/null +++ b/strings/60A590F004 @@ -0,0 +1,3 @@ +RTS + LDA $90 (IOSTATUS) + BEQ (offset matches) + +Subroutine started with decision based on IOSTATUS value (zero or not) - trivial, not copyrightable. diff --git a/strings/7F8D0DDDA9 b/strings/7F8D0DDDA9 new file mode 100644 index 00000000..44e2bb5b --- /dev/null +++ b/strings/7F8D0DDDA9 @@ -0,0 +1,3 @@ +$7F + STA $DD0D + LDA (value does not match) + +Instruction (accessing a documented I/O register) + some parts. Trivial, not copyrightable. diff --git a/strings/8D00DCA2 b/strings/8D00DCA2 new file mode 100644 index 00000000..9aa4cc19 --- /dev/null +++ b/strings/8D00DCA2 @@ -0,0 +1,3 @@ +STA $DC00 + LDX (value does not match) + +Instruction (accessing a documented I/O register) + some part. Trivial, not copyrightable. diff --git a/strings/8D0DDDA9 b/strings/8D0DDDA9 new file mode 100644 index 00000000..1e014b12 --- /dev/null +++ b/strings/8D0DDDA9 @@ -0,0 +1,4 @@ +STA $DD0D + LDA (value does not match) + +Instruction (accessing a documented I/O register) + some part. Trivial, not copyrightable. + diff --git a/strings/8D0DDDA9008D b/strings/8D0DDDA9008D new file mode 100644 index 00000000..f8ef80fe --- /dev/null +++ b/strings/8D0DDDA9008D @@ -0,0 +1,3 @@ +STA $DD0D + LDA #$00 + STA (address does not match) + +Store a value in a documented I/O register, afterwards store 0 somewhere else (address does not match). Trivial, not copyrightable. diff --git a/strings/A005B1B220D2FFC8C015D0F6 b/strings/A005B1B220D2FFC8C015D0F6 new file mode 100644 index 00000000..7dfd107a --- /dev/null +++ b/strings/A005B1B220D2FFC8C015D0F6 @@ -0,0 +1,3 @@ +LDY #$05 + LDA ($B2),Y + JSR $FFD2 (display character, documented routine) + INY + CPY #$15 + BNE (offset matches) + +A simple loop displaying a constant-size string pointed by a zeropage vector - nothing more. Due to 6502 addressing modes limiations, such a code will always look this way - this is not creative, and thus not copyrightable. diff --git a/strings/A5A745AB b/strings/A5A745AB new file mode 100644 index 00000000..316490e2 --- /dev/null +++ b/strings/A5A745AB @@ -0,0 +1,3 @@ +LDA $A7 + EOR $AB + +Small part of code calculating parity/XOR type checksum. Trivial, not copyrightable. diff --git a/strings/A5C485AF b/strings/A5C485AF new file mode 100644 index 00000000..74a534e9 --- /dev/null +++ b/strings/A5C485AF @@ -0,0 +1,3 @@ +LDA $C4 + STA $AF + +Move value from one zeropage location to another one (both documented, MEMUSS and EAL) - trivial, not copyrightable. diff --git a/strings/A9042CA9 b/strings/A9042CA9 new file mode 100644 index 00000000..6706b637 --- /dev/null +++ b/strings/A9042CA9 @@ -0,0 +1,3 @@ +LDA #$04 + $2C (BIT) + LDA (value does not match) + +Put $04 to acumulator and skip thee next 2 bytes (common space optimization) - trivial, not copyrightable. diff --git a/strings/A9042CA980 b/strings/A9042CA980 new file mode 100644 index 00000000..16074181 --- /dev/null +++ b/strings/A9042CA980 @@ -0,0 +1,3 @@ +LDA #$04 + $2C (BIT) + LDA #$80 + +Part of the code putting $04 or $80 to accumulator depending on some condition (not included in a similarity) - trivial, not copyrightable. diff --git a/strings/AD00DD0910 b/strings/AD00DD0910 new file mode 100644 index 00000000..e3611385 --- /dev/null +++ b/strings/AD00DD0910 @@ -0,0 +1,3 @@ +LDA $DD00 + ORA #$10 + +Small part of code manipulating a bit in a documented I/O register. Trivial, not copyrightable. diff --git a/strings/AD18D029 b/strings/AD18D029 new file mode 100644 index 00000000..80f2e2db --- /dev/null +++ b/strings/AD18D029 @@ -0,0 +1,3 @@ +LDA $D018 + AND (value does not match) + +Instruction (accessing a documented I/O register) + some part. Trivial, not copyrightable. diff --git a/strings/B1B285 b/strings/B1B285 new file mode 100644 index 00000000..fe9ee8e5 --- /dev/null +++ b/strings/B1B285 @@ -0,0 +1,3 @@ +LDA ($B2),Y + STA (zeropage address does not match) + +Instruction and some part. Trivial, not copyrightable. diff --git a/strings/C485AFA5C385 b/strings/C485AFA5C385 new file mode 100644 index 00000000..28cac505 --- /dev/null +++ b/strings/C485AFA5C385 @@ -0,0 +1,3 @@ +$C4 + STA $AF + LDA $C3 + STA (zeropage address does not match) + +Manipulation on some zeropage variables (copying one to another) - trivial, not copyrightable. diff --git a/strings/C902D0034C b/strings/C902D0034C new file mode 100644 index 00000000..e15f6a26 --- /dev/null +++ b/strings/C902D0034C @@ -0,0 +1,3 @@ +CMP #$02 + BNE (skip next instruction) + JMP (address does not match) + +Decision based on a check if accumulator contains 2 - trivial, not copyrightable. diff --git a/strings/D029EF8D11D0AD b/strings/D029EF8D11D0AD new file mode 100644 index 00000000..c8b41a4b --- /dev/null +++ b/strings/D029EF8D11D0AD @@ -0,0 +1,3 @@ +$D0 + AND #$EF + STA $D011 + LDA (address does not match) + +Small part of code manipulating a bit in a documented I/O register. Trivial, not copyrightable. diff --git a/strings/D0F4A23C b/strings/D0F4A23C new file mode 100644 index 00000000..3e905a9a --- /dev/null +++ b/strings/D0F4A23C @@ -0,0 +1,3 @@ +BNE (offset matches) + LDX #$3C + +Putting a value to .X depending on some condition - trivial, not copyrightable. diff --git a/strings/D185F3A5D2 b/strings/D185F3A5D2 new file mode 100644 index 00000000..51eeda82 --- /dev/null +++ b/strings/D185F3A5D2 @@ -0,0 +1,3 @@ +$D1 + STA $F3 + LDA $D2 + +Manipulation on some zeropage variables (copying one to another) - trivial, not copyrightable. diff --git a/strings/D885F460 b/strings/D885F460 new file mode 100644 index 00000000..013ec63b --- /dev/null +++ b/strings/D885F460 @@ -0,0 +1,3 @@ +$D8 + STA $F4 + RTS + +Store acumulator in a documented zeropage location and return from subroutine - trivial, not copyrightable. diff --git a/strings/DDA2008E b/strings/DDA2008E new file mode 100644 index 00000000..02ffb8dd --- /dev/null +++ b/strings/DDA2008E @@ -0,0 +1,3 @@ +$DD + LDX #$00 + STX (address does not match) + +Instruction + some parts. Trivial, not copyrightable. diff --git a/testsuite/testtape-c128-ntsc.tap b/testsuite/testtape-c128-ntsc.tap new file mode 100644 index 00000000..1ffbe117 Binary files /dev/null and b/testsuite/testtape-c128-ntsc.tap differ diff --git a/testsuite/testtape-c128-pal.tap b/testsuite/testtape-c128-pal.tap new file mode 100644 index 00000000..1ffbe117 Binary files /dev/null and b/testsuite/testtape-c128-pal.tap differ diff --git a/testsuite/testtape-c64-ntsc-normal.tap b/testsuite/testtape-c64-ntsc-normal.tap new file mode 100644 index 00000000..66eae3dd Binary files /dev/null and b/testsuite/testtape-c64-ntsc-normal.tap differ diff --git a/testsuite/testtape-normal.tap b/testsuite/testtape-c64-pal-normal.tap similarity index 100% rename from testsuite/testtape-normal.tap rename to testsuite/testtape-c64-pal-normal.tap diff --git a/testsuite/testtape-turbo.tap b/testsuite/testtape-c64-pal-turbo.tap similarity index 100% rename from testsuite/testtape-turbo.tap rename to testsuite/testtape-c64-pal-turbo.tap diff --git a/testsuite/testtape-plus4-ntsc.tap b/testsuite/testtape-plus4-ntsc.tap new file mode 100644 index 00000000..b713b7c2 Binary files /dev/null and b/testsuite/testtape-plus4-ntsc.tap differ diff --git a/testsuite/testtape-plus4-pal.tap b/testsuite/testtape-plus4-pal.tap new file mode 100644 index 00000000..f9705db5 Binary files /dev/null and b/testsuite/testtape-plus4-pal.tap differ diff --git a/testsuite/testtape-vic20-ntsc.tap b/testsuite/testtape-vic20-ntsc.tap new file mode 100644 index 00000000..b6d93f23 Binary files /dev/null and b/testsuite/testtape-vic20-ntsc.tap differ diff --git a/testsuite/testtape-vic20-pal.tap b/testsuite/testtape-vic20-pal.tap new file mode 100644 index 00000000..9b34c3c5 Binary files /dev/null and b/testsuite/testtape-vic20-pal.tap differ