diff --git a/.gitignore b/.gitignore index bd558ebd..e4515487 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ kernal_hybrid.rom # Compilation related files -assembler/KickAss* build/* # Input to the similarity tool - copyrighted material, we can't check it in! @@ -15,5 +14,6 @@ build/* # Various IDE project files, temporary files, etc. +dump.mem *project .*swp diff --git a/CONFIG.md b/CONFIG.md index 463a7307..3df98c2d 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -91,9 +91,33 @@ Planned for the future - not available yet. ### `CONFIG_MEMORY_MODEL_60K` -Uses RAM under BASIC, I/O and KERNAL, takes over `$C000`-`$CFFF` area requires special helper routines installed in `$2A7`-`$2FF` area (normally unused and free for the user). Gives the most free memory for BASIC programs, but it's the slowest and the least compatible model. +Uses RAM under BASIC, I/O and KERNAL, takes over `$C000`-`$CFFF` area requires special helper routines installed in `$2A7`-`$2FF` area (normally unused and free for the user). Gives the most free memory for BASIC programs, but it's the slowest (for example, forces disabling optimized LOAD loop for JiffyDOS) and the least compatible model. -Comparing to standard memoryy model, it needs about 180 bytes in BASIC segment and 80 bytes in KERNAL segment - at the moment of doing the test, these values are expected to change often. +Comparing to standard memory model, it needs about 180 bytes in BASIC segment and 80 bytes in KERNAL segment - at the moment of doing the test, these values are expected to change often. + +## I/O devices + +### `CONFIG_IEC` + +Adds support for the IEEC bus - for serial printers, disk drives, etc. + +Needs over 1000 bytes in KERNAL segment. If unsure - enable. + +### `CONFIG_IEC_BLANK_SCREEN` + +Causes screen blanking during some IEC operations (currently only JiffyDOS file loading) to increase the data transfer performance. + +### `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_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. ## Multiple SID support @@ -105,7 +129,7 @@ The SID support in the ROM is very limited - it only disables the sound during s Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively. -Each of these options needs 8 bytes in KERNAL segment. +Each of these options needs 3 bytes in KERNAL segment. ### `CONFIG_SID_D4XX` and `CONFIG_SID_D5XX` @@ -125,7 +149,7 @@ Needs 30-250 more space in KERNAL segment (depending on the features enabled for ### `CONFIG_KEYBOARD_C128` -Allows to use additional keys found on the C128 keyboard. NOTE: might be buggy, on VICE emulator I can't get all the keys working. +Allows to use additional keys found on the C128 keyboard. Needs about 130 bytes more space in KERNAL segment. If unsure - disable. @@ -135,6 +159,10 @@ Allows to use CAPS LOCK key on the C128 keyboard, this is independent from `CONF Needs about 50 bytes more space in KERNAL segment. If unsure - disable. +### `CONFIG_KEYBOARD_C65`, `CONFIG_KEYBOARD_C65_CAPS_LOCK` + +Similar, but for C65 keyboard. Please note - the C65 keyboard support is (as of yet) completely untested! + ### `CONFIG_KEY_REPEAT_DEFAULT` Enables key repetition by default during the startup (sets `RPTFLG`). @@ -157,25 +185,27 @@ Needs 13 bytes more space in KERNAL segment. Only disable if you are running out Joystick movement also moves the cursor. -Needs about 65 bytes of ROM space to handle both joysticks. +Needs about 65 bytes of ROM space in KERNAL segment to handle both joysticks. -## Eye candy +### `CONFIG_PROGRAMMABLE_KEYS` -### `CONFIG_COLORS_BRAND` +Allows to assign command to any function key, `RUN` key and `HELP` key (if selected keybaord has one) - just fill-in appropriate `CONFIG_KEYCMD_*` variable(s). Keys not present on the selected keyboard are ignored. -Tries to adjust the color scheme to the selected brand. Some brands might not support this. +Needs 25 bytes more space in KERNAL segment for the code. In addition, each configured key takes 3 bytes + length of the command. -### `CONFIG_BANNER_SIMPLE`, `CONFIG_BANNER_FANCY`, `CONFIG_BANNER_BRAND` +## Screen editor -Select startup banner - either a simple one, or with some colorful elements. `CONFIG_BANNER_BRAND` heavily depends on the selected brand, not all the brands support it. +### `CONFIG_EDIT_STOPQUOTE` -Richer banners need more BASIC segment, varies between brands. +If enabled, STOP key terminates insert/quote mode (like on some _Black Box_ cartridges). -### `CONFIG_BANNER_PAL_NTSC` +Feature needs 12 bytes in KERNAL segment. If unsure - enable. -If enabled, prints video system on startup banner. Eye candy only. +### `CONFIG_EDIT_TABULATORS` -Feature needs some bytes in BASIC (depending on banner type) and about 25 bytes in KERNAL segment. +If enabled, allows use of TAB (or CTRL+>) and SHIFT+TAB (or CTRL+<) to switch between predefined tabulator positions. + +Feature needs 35-45 bytes in KERNAL segment. If unsure - enable. ## Software features @@ -191,12 +221,42 @@ If enabled, a simple DOS wedge is available from the direct mode - supports `@`, `@`, `@$`, `@$`, `@` NOTE: extra features and their syntax can change in the future! @@ -19,6 +22,10 @@ NOTE: extra features and their syntax can change in the future! # Features missing +The following ROM features are currently missing and are not planned due to space considerations: + +* full tape support - VERIFY, SAVE, sequential files; tape is considered a legacy medium, so it's support is going to be limited +* mock 6551 emulation - this only complicates the RS-232 support for original ROMs, probably noone needs it The following ROM features are currently missing: @@ -26,12 +33,46 @@ The following ROM features are currently missing: * BASIC variables * BASIC expression parsing * floating point routines -* tape support +* tape (normal mode) support * RS-232 support -* breaking Kernal routines with RUN/STOP key * NMI handling is incomplete +# Hardware support status + +## Keyboard + +| Driver | Status | Remarks | +| :-----------: | :------: | :------------------------------------------------: | +| C64 | DONE | | +| C128 | DONE | | +| C65 / Mega65 | NOT DONE | code should be complete, but is not tested yet | + +## Tape storage (LOAD only!) + +| Driver | Status | Remarks | +| :-----------: | :------: | :------------------------------------------------: | +| normal | NOT DONE | | +| turbo | PARTIAL | works, to do: use sync to calibrate read speed | + +## IEC bus (disk drives, etc.) + +| Driver | Status | Remarks | +| :-----------: | :------: | :------------------------------------------------: | +| standard | DONE | | +| JiffyDOS | DONE | | +| DolphinDOS | NOT DONE | | +| CIA burst mod | NOT DONE | | + +## RS-232 + +| Driver | Status | Remarks | +| :-----------: | :------: | :------------------------------------------------: | +| UP2400 | NOT DONE | | +| UP9600 | NOT DONE | work in progress, not functional yet | +| ACIA 6551 | NOT DONE | | + + # API status @@ -48,8 +89,6 @@ For the current status of the low memory location implementation andd usage chec ### Official BASIC routines -Note: vectors at `$0300` are not supported yet - for now only the locations below can be used! -
| Entry | Unofficial | Name | Status | Remarks | @@ -84,6 +123,7 @@ Not all of them - only these we want to have implemented. | `$A68E` | RUNC | DONE | | | `$A7AE` | NEWSTT | PARTIAL | redirected to RUN command | | `$AB1E` | STROUT | DONE | | +| `$AD9E` | FRMEVL | NOT DONE | | | `$BDCD` | LINPRT | DONE | temporary implementation | | `$E3BF` | INIT | NOT DONE | | | `$E422` | INITMSG | DONE | | @@ -103,8 +143,8 @@ NOTE: Even the 'DONE' routines won't support features described as missing in on | :-------: | :--------: | :---------- | :------: | :--------------------------------------------------: | | `($028F)` | | `KEYLOG` | DONE | | | `$FF81` | `$FF5B` | `CINT` | DONE | | -| `$FF84` | `$FDA3` | `IOINIT` | PARTIAL | CIA initialization might be incomplete | -| `$FF87` | `$FD50` | `RAMTAS` | PARTIAL | probably shouldn't touch VIC and CIA's | +| `$FF84` | `$FDA3` | `IOINIT` | PARTIAL | CIA initialization incomplete | +| `$FF87` | `$FD50` | `RAMTAS` | DONE | | | `$FF8A` | `$FD15` | `RESTOR` | DONE | | | `$FF8D` | `$FD1A` | `VECTOR` | DONE | | | `$FF90` | | `SETMSG` | DONE | | @@ -126,26 +166,26 @@ NOTE: Even the 'DONE' routines won't support features described as missing in on | `$FFC0` | `$F34A` | `OPEN` | DONE | | | `$FFC3` | `$F291` | `CLOSE` | DONE | | | `$FFC6` | `$F20E` | `CHKIN` | DONE | | -| `$FFC9` | `$F250` | `CKOUT` | PARTIAL | | +| `$FFC9` | `$F250` | `CKOUT` | DONE | | | `$FFCC` | `$F333` | `CLRCHN` | DONE | | -| `$FFCF` | `$F157` | `CHRIN` | PARTIAL | | -| `$FFD2` | `$F1CA` | `CHROUT` | PARTIAL | | -| `$FFD5` | `$F49E` | `LOAD` | PARTIAL | not yet clear what's this entry doing | -| `($0330)` | `$F4A5` | `LOAD` | PARTIAL | no VERIFY support, no STOP key, check $F49E addr | -| `$FFD8` | `$F5DD` | `SAVE` | NOT DONE | | -| `($0332)` | `$F5ED` | `SAVE` | NOT DONE | | +| `$FFCF` | `$F157` | `CHRIN` | PARTIAL | no screen device support | +| `$FFD2` | `$F1CA` | `CHROUT` | DONE | | +| `$FFD5` | `$F49E` | `LOAD` | DONE | | +| `($0330)` | `$F4A5` | `LOAD` | DONE | | +| `$FFD8` | `$F5DD` | `SAVE` | DONE | | +| `($0332)` | `$F5ED` | `SAVE` | DONE | | | `$FFDB` | | `SETTIM` | DONE | | | `$FFDE` | | `RDTIM` | DONE | | | `$FFE1` | `$F6ED` | `STOP` | DONE | | -| `$FFE4` | `$F13E` | `GETIN` | PARTIAL | only keyboard supported | +| `$FFE4` | `$F13E` | `GETIN` | PARTIAL | no screen device support | | `$FFE7` | `$F32F` | `CLALL` | DONE | | | `$FFEA` | | `UDTIM` | DONE | | | `$FFED` | | `SCREEN` | DONE | | | `$FFF0` | `$E50A` | `PLOT` | DONE | | | `$FFF3` | | `IOBASE` | DONE | | | `($FFFA)` | | NMI vec | PARTIAL | | -| `($FFFC)` | `$FCE2` | RESET vec | PARTIAL | | -| `($FFFE)` | | IRQ/BRK vec | PARTIAL | | +| `($FFFC)` | `$FCE2` | RESET vec | PARTIAL | see IOINIT status | +| `($FFFE)` | | IRQ/BRK vec | DONE | |
@@ -162,10 +202,11 @@ Not all of them - only these we want to have implemented. | `$E544` | clear screen | DONE | | | `$E50C` | set cursor position | PARTIAL | | | `$E566` | home cursor | NOT DONE | | -| `$E5A0` | setup VIC II & IO | DONE | | +| `$E5A0` | setup VIC II & I/O | DONE | | | `$E6B6` | advance cursor | NOT DONE | | | `$E701` | previous line | NOT DONE | | | `$E716` | screen CHROUT | NOT DONE | | +| `$E8DA` | color code table | DONE | | | `$E8EA` | scroll line | NOT DONE | | | `$E96C` | insert line on top | NOT DONE | | | `$E9FF` | clear line | NOT DONE | | @@ -176,7 +217,6 @@ Not all of them - only these we want to have implemented. | `$F646` | IEC close | NOT DONE | | | `$FD30` | default vectors | DONE | | | `$FD90` | (unknown) | NOT DONE | | -| `$FD90` | (unknown) | NOT DONE | | | `$FE2D` | memtop set part | DONE | | | `$FE47` | default NMI | PARTIAL | | | `$FE66` | default BRK | DONE | | diff --git a/assembler/KickAss.cfg b/assembler/KickAss.cfg old mode 100755 new mode 100644 index 79e9428c..919ec309 --- a/assembler/KickAss.cfg +++ b/assembler/KickAss.cfg @@ -1,2 +1,3 @@ --showmem --symbolfile +# These are the defaults - not needed for Open ROMs build system +# -showmem +# -symbolfile diff --git a/assembler/KickAss.jar b/assembler/KickAss.jar old mode 100755 new mode 100644 diff --git a/assembler/KickAssembler.pdf b/assembler/KickAssembler.pdf old mode 100755 new mode 100644 diff --git a/assembler/README.TXT b/assembler/README.TXT deleted file mode 100644 index 3bc6fa41..00000000 --- a/assembler/README.TXT +++ /dev/null @@ -1 +0,0 @@ -Put KickAss.jar and KickAss.cfg into this directory. diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index a1e9f2ef..d09f539f 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 index 2d95059d..06e4b304 100644 Binary files a/bin/basic_mega65.rom and b/bin/basic_mega65.rom differ diff --git a/bin/basic_testing.rom b/bin/basic_testing.rom index efbebfcd..008bb835 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 d9cdeaf9..4c147b6c 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 3833498b..749b319e 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 index b4a039f8..58a7a0c7 100644 Binary files a/bin/kernal_mega65.rom and b/bin/kernal_mega65.rom differ diff --git a/bin/kernal_testing.rom b/bin/kernal_testing.rom index 6731edb1..4f8f4734 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 90de039e..2106f3ec 100644 Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ diff --git a/bin/newc65.rom b/bin/newc65.rom new file mode 100644 index 00000000..90f97c65 Binary files /dev/null and b/bin/newc65.rom differ diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s index 8965f1dd..cba2e0d3 100644 --- a/c64/,,config_generic.s +++ b/c64/,,config_generic.s @@ -1,5 +1,6 @@ .const CONFIG_ID = $00 // should be 1 byte, different for each config file! +.encoding "petscii_upper" // // Please read CONFIG.md before modifying this file! @@ -37,6 +38,17 @@ // #define CONFIG_MEMORY_MODEL_60K +// I/O devices + +#define CONFIG_IEC +#define CONFIG_IEC_BLANK_SCREEN +#define CONFIG_IEC_JIFFYDOS +// #define CONFIG_TAPE_NORMAL // please keep disabled for now +#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 @@ -52,14 +64,52 @@ // Keyboard settings // #define CONFIG_LEGACY_SCNKEY -#define CONFIG_KEYBOARD_C128 // incomplete +#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 @@ -67,16 +117,10 @@ // #define CONFIG_BANNER_SIMPLE #define CONFIG_BANNER_FANCY // #define CONFIG_BANNER_BRAND +#define CONFIG_SHOW_FEATURES #define CONFIG_SHOW_PAL_NTSC -// Software features - -#define CONFIG_PANIC_SCREEN -#define CONFIG_DOS_WEDGE -#define CONFIG_BCD_SAFE_INTERRUPTS - - // Debug options // #define CONFIG_DBG_STUBS_BRK diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s index 65169f8d..b2087518 100644 --- a/c64/,,config_mega65.s +++ b/c64/,,config_mega65.s @@ -1,5 +1,6 @@ .const CONFIG_ID = $01 // should be 1 byte, different for each config file! +.encoding "petscii_upper" // // Please read CONFIG.md before modifying this file! @@ -33,19 +34,30 @@ // #define CONFIG_CPU_WDC_65816 -// Memory model configuration +// 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_JIFFYDOS +// #define CONFIG_TAPE_NORMAL // please keep disabled for now +// #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 +.const CONFIG_SID_2ND_ADDRESS = $D440 // #define CONFIG_SID_3RD -.const CONFIG_SID_3RD_ADDRESS = $D440 +.const CONFIG_SID_3RD_ADDRESS = $D480 // #define CONFIG_SID_D4XX // #define CONFIG_SID_D5XX @@ -54,31 +66,63 @@ // Keyboard settings // #define CONFIG_LEGACY_SCNKEY -// #define CONFIG_KEYBOARD_C128 // incomplete +// #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 -// Eye candy +.const CONFIG_KEYCMD_RUN = @"LOAD\"*\"" -#define CONFIG_COLORS_BRAND -// #define CONFIG_BANNER_SIMPLE -// #define CONFIG_BANNER_FANCY -#define CONFIG_BANNER_BRAND -// #define CONFIG_SHOW_PAL_NTSC +.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 // do not enable for now, triggers screen editor bug under XEMU +#define CONFIG_SHOW_FEATURES +// #define CONFIG_SHOW_PAL_NTSC + + // Debug options // #define CONFIG_DBG_STUBS_BRK diff --git a/c64/,,config_testing.s b/c64/,,config_testing.s index 877a5005..19376b5a 100644 --- a/c64/,,config_testing.s +++ b/c64/,,config_testing.s @@ -1,5 +1,6 @@ .const CONFIG_ID = $F0 // should be 1 byte, different for each config file! +.encoding "petscii_upper" // // Please read CONFIG.md before modifying this file! @@ -32,18 +33,29 @@ // #define CONFIG_CPU_WDC_65816 -// Memory model configuration +// 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_JIFFYDOS +// #define CONFIG_TAPE_NORMAL // please keep disabled for now +#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 +#define CONFIG_SID_3RD .const CONFIG_SID_3RD_ADDRESS = $D440 // #define CONFIG_SID_D4XX @@ -53,31 +65,63 @@ // Keyboard settings #define CONFIG_LEGACY_SCNKEY -// #define CONFIG_KEYBOARD_C128 // incomplete +// #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 -// Eye candy +.const CONFIG_KEYCMD_RUN = @"\$5FL" -// #define CONFIG_COLORS_BRAND -// #define CONFIG_BANNER_SIMPLE -#define CONFIG_BANNER_FANCY -// #define CONFIG_BANNER_BRAND -// #define CONFIG_SHOW_PAL_NTSC +.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 diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s index 1eda8501..1856fd44 100644 --- a/c64/,,config_ultimate64.s +++ b/c64/,,config_ultimate64.s @@ -1,5 +1,6 @@ .const CONFIG_ID = $02 // should be 1 byte, different for each config file! +.encoding "petscii_upper" // // Please read CONFIG.md before modifying this file! @@ -31,12 +32,23 @@ // #define CONFIG_CPU_WDC_65816 -// Memory model configuration +// 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_JIFFYDOS +// #define CONFIG_TAPE_NORMAL // please keep disabled for now +#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 @@ -52,31 +64,63 @@ // Keyboard settings // #define CONFIG_LEGACY_SCNKEY -// #define CONFIG_KEYBOARD_C128 // incomplete +// #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 -// Eye candy +.const CONFIG_KEYCMD_RUN = @"\$5FL" -#define CONFIG_COLORS_BRAND -// #define CONFIG_BANNER_SIMPLE -#define CONFIG_BANNER_FANCY -// #define CONFIG_BANNER_BRAND -#define CONFIG_SHOW_PAL_NTSC +.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 diff --git a/c64/aliases/,aliases_config.s b/c64/aliases/,aliases_config.s index ac668e61..99b2d2c9 100644 --- a/c64/aliases/,aliases_config.s +++ b/c64/aliases/,aliases_config.s @@ -3,10 +3,11 @@ // Various configuration dependent aliases/macros/checks // +.encoding "petscii_upper" + // Check that platform configuration is correct - { .var selected = 0; @@ -20,7 +21,6 @@ // Check that motherboard extras configuration is correct - { .var selected = 0; @@ -44,7 +44,6 @@ // Check that brand configuration is correct - { .var selected = 0; @@ -74,7 +73,6 @@ // Check that processor configuration is correct - { .var selected = 0; @@ -97,7 +95,6 @@ // Check that memory model configuration is correct - { .var selected = 0; @@ -112,9 +109,26 @@ } +// Check that I/O configuration is correct +{ +#if CONFIG_IEC_JIFFYDOS && !CONFIG_IEC + .error "CONFIG_IEC_JIFFYDOS requires CONFIG_IEC" +#endif + + .var selected_rs232 = 0; + +#if CONFIG_RS232_UP2400 + .eval selected_rs232++ +#endif +#if CONFIG_RS232_UP9600 + .eval selected_rs232++ +#endif + + .if (selected_rs232 > 1) .error "Please select at most one CONFIG_RS232_* option" +} + // Check that startup banner configuration is correct - { .var selected = 0; @@ -134,8 +148,8 @@ .error "CONFIG_BANNER_BRAND is not supported for your CONFIG_BRAND_*" #endif -#if CONFIG_BANNER_BRAND && CONFIG_BRAND_MEGA_65 && CONFIG_SHOW_PAL_NTSC - .error "MEGA65 brand banner does not support showing PAL/NTSC" +#if CONFIG_MB_MEGA_65 && CONFIG_SHOW_PAL_NTSC + .error "MEGA65 can switch PAL/NTSC during run-time, CONFIG_SHOW_PAL_NTSC makes no sense" #endif } @@ -143,15 +157,70 @@ // Check if keyboard options are correct - +.function CHECK_KEYCMD(keycmd) { -#if CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C128_CAPS_LOCK) - .error "CONFIG_LEGACY_SCNKEY and CONFIG_KEYBOARD_C128* are mutually exclusive" + .if (keycmd.size() > 0) .return 1 + .return 0 +} +{ +#if CONFIG_LEGACY_SCNKEY && CONFIG_RS232_UP9600 + .error "CONFIG_LEGACY_SCNKEY is not compatible with CONFIG_RS232_UP9600" +#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 #if (CONFIG_MB_MEGA_65 || CONFIG_MB_ULTIMATE_64) && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C128_CAPS_LOCK) .error "Selected CONFIG_MB_* is not compatible with CONFIG_KEYBOARD_C128*" #endif +#if CONFIG_MB_ULTIMATE_64 && (CONFIG_KEYBOARD_C65 || CONFIG_KEYBOARD_C65_CAPS_LOCK) + .error "Selected CONFIG_MB_* is not compatible with CONFIG_KEYBOARD_C65*" +#endif + + .var num_pkeys_base = 0 + .var num_pkeys_ext1 = 0 + .var num_pkeys_ext2 = 0 + + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_RUN) + + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F1) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F2) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F3) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F4) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F5) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F6) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F7) + .eval num_pkeys_base += CHECK_KEYCMD(CONFIG_KEYCMD_F8) + + .eval num_pkeys_ext1 += CHECK_KEYCMD(CONFIG_KEYCMD_HELP) + + .eval num_pkeys_ext2 += CHECK_KEYCMD(CONFIG_KEYCMD_F9) + .eval num_pkeys_ext2 += CHECK_KEYCMD(CONFIG_KEYCMD_F10) + .eval num_pkeys_ext2 += CHECK_KEYCMD(CONFIG_KEYCMD_F11) + .eval num_pkeys_ext2 += CHECK_KEYCMD(CONFIG_KEYCMD_F12) + .eval num_pkeys_ext2 += CHECK_KEYCMD(CONFIG_KEYCMD_F13) + .eval num_pkeys_ext2 += CHECK_KEYCMD(CONFIG_KEYCMD_F14) + + .var num_pkeys = num_pkeys_base +#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65) + .eval num_pkeys += num_pkeys_ext1 +#endif +#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65 + .eval num_pkeys += num_pkeys_ext2 +#endif + +#if CONFIG_PROGRAMMABLE_KEYS + .if (num_pkeys == 0) .error "CONFIG_PROGRAMMABLE_KEYS requires at least one defined key" +#endif +} + + + +// Check that features are configured correctly +{ +#if CONFIG_TAPE_WEDGE && !CONFIG_TAPE_TURBO + .error "CONFIG_TAPE_WEDGE requires CONFIG_TAPE_TURBO" +#endif } @@ -170,6 +239,12 @@ #endif +// Handle I/O configuration + +#if CONFIG_RS232_UP2400 || CONFIG_RS232_UP9600 +#define HAS_RS232 +#endif + // Handle configuration of various features @@ -200,3 +275,75 @@ STUB_IMPLEMENTATION_RTS() #endif } + + +// Function for printing out build features + +.var feature_new_line = false + +.function ADD_FEATURE(current_features, new_feature) +{ + .var features_str = current_features + + .if (!feature_new_line && features_str.size() > 0) + { + .eval features_str = features_str + ", " + } + + .if (feature_new_line) + { + .eval feature_new_line = false + .eval features_str = features_str + @"\r" + } + + .return features_str + new_feature +} + +.function BUILD_FEATURES_STR() +{ + .var features_str = "" + +#if CONFIG_TAPE_NORMAL + .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD NORMAL") +#elif CONFIG_TAPE_TURBO + .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD TURBO") +#elif CONFIG_TAPE_NORMAL && CONFIG_TAPE_TURBO + .eval features_str = ADD_FEATURE(features_str, "TAPE LOAD NORMAL TURBO") +#endif + + .eval feature_new_line = true + +#if CONFIG_IEC + .var iec_features_str = "IEC" +#if CONFIG_IEC_DOLPHINDOS + .eval iec_features_str = iec_features_str + " DOLPHIN-DEV" +#endif +#if CONFIG_IEC_JIFFYDOS + .eval iec_features_str = iec_features_str + " JIFFY" +#endif +#if !CONFIG_IEC_DOLPHINDOS && !CONFIG_IEC_JIFFYDOS + .eval iec_features_str = iec_features_str + " NORMAL" +#endif + .eval features_str = ADD_FEATURE(features_str, iec_features_str) +#endif + + .eval feature_new_line = true + +#if CONFIG_RS232_UP2400 + .eval features_str = ADD_FEATURE(features_str, "UP2400") +#endif + +#if CONFIG_RS232_UP2400 + .eval features_str = ADD_FEATURE(features_str, "UP9600") +#endif + +#if CONFIG_KEYBOARD_C128 + .eval features_str = ADD_FEATURE(features_str, "KBD 128") +#endif + +#if CONFIG_KEYBOARD_C65 + .eval features_str = ADD_FEATURE(features_str, "KBD 65") +#endif + + .return features_str +} diff --git a/c64/aliases/,aliases_cpu.s b/c64/aliases/,aliases_cpu.s index 01b980b6..79caf2d8 100644 --- a/c64/aliases/,aliases_cpu.s +++ b/c64/aliases/,aliases_cpu.s @@ -17,6 +17,17 @@ } +// +// Trick to skip a 2-byte instruction +// + + +.pseudocommand skip_2_bytes_trash_nvz +{ + .byte $2C +} + + // // Stack manipulation - some CPUs will leave .A unchanged, some will use it as temporary storage, so consider .A trashed // diff --git a/c64/aliases/,aliases_hardware.s b/c64/aliases/,aliases_hardware.s index 63790da6..e7a7a51c 100644 --- a/c64/aliases/,aliases_hardware.s +++ b/c64/aliases/,aliases_hardware.s @@ -70,6 +70,13 @@ .label VIC_XSCAN = $D02F // C128 only .label VIC_CLKRATE = $D030 // C128 only +#endif + +#if CONFIG_MB_MEGA_65 + + .label VIC_KEY = $D02F + .label VIC_XPOS = $D050 + #endif // SID registers @@ -165,7 +172,7 @@ .const BIT_CIA2_PRA_CLK_IN = $40 // 0 - low (pulled), 1 - high (released) .const BIT_CIA2_PRA_DAT_IN = $80 // 0 - low (pulled), 1 - high (released) -#if CONFIG_MB_MEGA_65 +#if CONFIG_MB_MEGA_65 .const C65_EXTKEYS_PR = $D607 .const C65_EXTKEYS_DDR = $D608 diff --git a/c64/aliases/,aliases_petscii_codes.s b/c64/aliases/,aliases_petscii_codes.s index d62bf4ec..0156cfff 100644 --- a/c64/aliases/,aliases_petscii_codes.s +++ b/c64/aliases/,aliases_petscii_codes.s @@ -16,30 +16,35 @@ .const KEY_FLAG_SHIFT = %00000001 .const KEY_FLAG_VENDOR = %00000010 .const KEY_FLAG_CTRL = %00000100 -.const KEY_FLAG_ALT = %00001000 // C65 / C128 -.const KEY_CAPS_LOCK = %00010000 // C65 / C128 -.const KEY_FLAG_NO_SCRL = %00100000 // C65 / C128, Open ROMs unofficial +#if CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65 +.const KEY_FLAG_ALT = %00001000 +#if CONFIG_KEYBOARD_C128_CAPS_LOCK || CONFIG_KEYBOARD_C65_CAPS_LOCK +.const KEY_CAPS_LOCK = %00010000 +#endif +.const KEY_FLAG_NO_SCRL = %00100000 // Open ROMs unofficial +#endif // Note - the following PETSCII codes are currently unassigned, can be used for further extensions: // -// $01, $04, $06, $0A, $0B, $0C, $0F, $18, $82 +// $01, $02, $04, $06, $0A, $0B, $0C, $0F, $18, $82 .const KEY_NA = $00 // to indicate that no key is presed -// PETSCII codes for our extended screen editor XXX implement these +// PETSCII codes for our extended screen editor -.const KEY_BOTTOM = $02 // CTRL+B - Open ROMs unofficial, DolphinDOS compatible .const KEY_TAB_FW = $8F // CTRL+>, TAB - Open ROMs unofficial, original TAB conflicts with C64 PETSCII .const KEY_TAB_BW = $80 // CTRL+<, SHIFT+TAB - Open ROMs unofficial, original TAB conflicts with C64 PETSCII -// PETSCII codes for certain C128 and C65 functionalities XXX implement these +// PETSCII codes for certain C128 and C65 functionalities -.const KEY_BELL = $07 // C65 / C128, no key -.const KEY_ESC = $1B // C65 / C128 +#if CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65 +.const KEY_BELL = $07 // no key, originally CTRL+G // XXX implement BELL +.const KEY_ESC = $1B +#endif // PETSCII codes for programmable keys @@ -48,22 +53,26 @@ .const KEY_RUN = $83 .const KEY_F1 = $85 -.const KEY_F2 = $86 -.const KEY_F3 = $87 -.const KEY_F4 = $88 -.const KEY_F5 = $89 -.const KEY_F6 = $8A -.const KEY_F7 = $8B +.const KEY_F2 = $89 +.const KEY_F3 = $86 +.const KEY_F4 = $8A +.const KEY_F5 = $87 +.const KEY_F6 = $8B +.const KEY_F7 = $88 .const KEY_F8 = $8C -.const KEY_F9 = $10 // C65 -.const KEY_F10 = $15 // C65 -.const KEY_F11 = $16 // C65 -.const KEY_F12 = $17 // C65 -.const KEY_F13 = $19 // C65 -.const KEY_F14 = $1A // C65 +#if CONFIG_KEYBOARD_C65 +.const KEY_F9 = $10 +.const KEY_F10 = $15 +.const KEY_F11 = $16 +.const KEY_F12 = $17 +.const KEY_F13 = $19 +.const KEY_F14 = $1A +#endif -.const KEY_HELP = $84 // C65, also used for our C128 support +#if CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65 +.const KEY_HELP = $84 // normally C65 only, also used for our C128 support +#endif // PETSCII codes for cursor keys @@ -151,4 +160,5 @@ .const KEY_GT = $3E .const KEY_QUESTION = $3F + // XXX finish this: $4x, $5x, $6x, $7x, $Ax, $Bx, $Cx, $Dx, $Ex, $Fx diff --git a/c64/aliases/,aliases_ram_lowmem.s b/c64/aliases/,aliases_ram_lowmem.s index 905446dc..814aff63 100644 --- a/c64/aliases/,aliases_ram_lowmem.s +++ b/c64/aliases/,aliases_ram_lowmem.s @@ -89,24 +89,32 @@ .label C3PO = $94 // flag - is BSOUR content valid .label BSOUR = $95 // serial bus buffered output byte .label SYNO = $96 // -- NOT IMPLEMENTED -- - .label XSAV = $97 // -- NOT IMPLEMENTED -- + .label XSAV = $97 // temporary register storage for ASCII 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 - .label PRTY = $9B // -- NOT IMPLEMENTED -- + .label PRTY = $9B // tape storage for parity/checksum +#if !CONFIG_TAPE_NORMAL && !CONFIG_TAPE_TURBO .label DPSW = $9C // -- NOT IMPLEMENTED -- +#else + .label COLSTORE = $9C // [!] screen border storage for tape routines +#endif .label MSGFLG = $9D // bit 6 = error messages, bit 7 = control message .label PTR1 = $9E // -- NOT IMPLEMENTED -- .label PTR2 = $9F // -- NOT IMPLEMENTED -- .label TIME = $A0 // $A0-$A2 jiffy clock - .label TSFCNT = $A3 // temporary variable for tape and IEC, [!] our usage probably differs in details +#if !CONFIG_IEC_JIFFYDOS + .label TSFCNT = $A3 // temporary variable for tape and IEC, [!] our usage differs +#else + .label IECPROTO = $A3 // -- WIP -- [!] 0 = normal, 1 = JiffyDOS, >= $80 for unknown +#endif .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 -- #if !CONFIG_LEGACY_SCNKEY .label BITCI = $A8 // -- NOT IMPLEMENTED -- - .label RINONE = $A9 // -- 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 -- #endif @@ -127,13 +135,13 @@ .label SA = $B9 // current secondary address .label FA = $BA // current device number .label FNADDR = $BB // $BB-$BC current file name pointer - .label ROPRTY = $BD // -- NOT IMPLEMENTED -- + .label ROPRTY = $BD // tape / RS-232 temporary storage .label FSBLK = $BE // -- NOT IMPLEMENTED -- .label MYCH = $BF // -- NOT IMPLEMENTED -- - .label CAS1 = $C0 // -- NOT IMPLEMENTED -- + .label CAS1 = $C0 // tape motor interlock .label STAL = $C1 // $C1-$C2 LOAD/SAVE start address .label MEMUSS = $C3 // $C3-$C4 temporary address for tape LOAD/SAVE - .label LSTX = $C5 // last keyy matrix position [!] our usage probably differs in details + .label LSTX = $C5 // last key matrix position [!] our usage probably differs in details .label NDX = $C6 // number of chars in keyboard buffer .label RVS = $C7 // flag, whether to print reversed characters .label INDX = $C8 // end of logical line (column, 0-79) @@ -142,7 +150,7 @@ .label BLNSW = $CC // cursor blink disable flag .label BLNCT = $CD // cursor blink countdown .label GDBLN = $CE // cursor saved character - .label BLNON = $CF // cursor visibilityy flag + .label BLNON = $CF // cursor visibility flag .label CRSW = $D0 // whether to input from screen or keyboard .label PNT = $D1 // $D1-$D2 pointer to the current screen line .label PNTR = $D3 // current screen X position @@ -154,8 +162,8 @@ .label LDTBL = $D9 // $D9-$F2 screen line link table, [!] our usage is different XXX give more details .label USER = $F3 // $F3-$F4 pointer to current color RAM location .label KEYTAB = $F5 // $F5-$F6 pointer to keyboard lookup table - .label RIBUF = $F7 // $F7-$F8 -- NOT IMPLEMENTED -- - .label ROBUF = $F9 // $F9-$FA -- NOT IMPLEMENTED -- + .label RIBUF = $F7 // $F7-$F8 -- WIP -- RS-232 receive buffer pointer + .label ROBUF = $F9 // $F9-$FA -- WIP -- RS-232 send buffer pointer // $FB $FB-$FE -- UNUSED -- free for user software .label BASZPT = $FF // -- NOT IMPLEMENTED -- @@ -198,14 +206,14 @@ .label M51CRT = $293 // -- NOT IMPLEMENTED -- mock 6551 .label M51CDR = $294 // -- NOT IMPLEMENTED -- mock 6551 .label M51AJB = $295 // $295-$296 -- NOT IMPLEMENTED -- mock 6551 - .label RSSTAT = $297 // -- NOT IMPLEMENTED -- mock 6551, RS-232 status + .label RSSTAT = $297 // -- WIP -- (UP9600 only) mock 6551, RS-232 status .label BITNUM = $298 // -- NOT IMPLEMENTED -- .label BAUDOF = $299 // $299-$29A -- NOT IMPLEMENTED -- #endif - .label RIDBE = $29B // -- NOT IMPLEMENTED -- - .label RIDBS = $29C // -- NOT IMPLEMENTED -- - .label RODBS = $29D // -- NOT IMPLEMENTED -- - .label RODBE = $29E // -- NOT IMPLEMENTED -- + .label RIDBE = $29B // -- WIP -- write pointer into RS-232 receive buffer + .label RIDBS = $29C // -- WIP -- read pointer into RS-232 receive buffer + .label RODBS = $29D // -- WIP -- read pointer into RS-232 send buffer + .label RODBE = $29E // -- WIP -- write pointer into RS-232 send buffer .label IRQTMP = $29F // $29F-$2A0 -- NOT IMPLEMENTED -- .label ENABL = $2A1 // -- NOT IMPLEMENTED -- .label TODSNS = $2A2 // -- NOT IMPLEMENTED -- @@ -273,6 +281,9 @@ // $314 $334-$33B -- UNUSED -- free for user software - .label TBUFFR = $33C // $33C-$3FB, -- NOT IMPLEMENTED --, tape buffer + .label TBUFFR = $33C // $33C-$3FB [!] tape buffer, our usage details differ +#if CONFIG_RS232_UP9600 + .label REVTAB = $37C // $37C-$3FB -- WIP -- [!] RS-232 precalculated data +#endif // $3FC $3FC-$3FF -- UNUSED -- free for user software diff --git a/c64/basic/,imports.s b/c64/basic/,imports.s index bc90a4cd..525459f4 100644 --- a/c64/basic/,imports.s +++ b/c64/basic/,imports.s @@ -19,6 +19,10 @@ .label print_return = KERNAL.print_return .label print_space = KERNAL.print_space +#if CONFIG_SHOW_FEATURES +.label print_features = KERNAL.print_features +#endif + #if CONFIG_SHOW_PAL_NTSC .label print_pal_ntsc = KERNAL.print_pal_ntsc #endif diff --git a/c64/basic/ad9e.frmevl.s b/c64/basic/ad9e.frmevl.s new file mode 100644 index 00000000..2b41983e --- /dev/null +++ b/c64/basic/ad9e.frmevl.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +FRMEVL: + STUB_IMPLEMENTATION() diff --git a/c64/basic/ad9e.interop b/c64/basic/ad9e.interop new file mode 100644 index 00000000..96b13dfd --- /dev/null +++ b/c64/basic/ad9e.interop @@ -0,0 +1,3 @@ + +This routine is desribed in Mapping the C64, page 102, and used at least by CCGMS terminal software - see here: +- https://raw.githubusercontent.com/spathiwa/ccgmsterm/master/original/5a.gs diff --git a/c64/basic/basic_main_loop.s b/c64/basic/basic_main_loop.s index 0c93e2a8..55ea6dce 100644 --- a/c64/basic/basic_main_loop.s +++ b/c64/basic/basic_main_loop.s @@ -62,17 +62,25 @@ rsl_l1: lda __tokenise_work1 beq basic_read_next_line -#if CONFIG_DOS_WEDGE + // Check if a wedge should take over + +#if CONFIG_DOS_WEDGE || CONFIG_TAPE_WEDGE + + ldx __tokenise_work1 // here is the size of input // Check if DOS wedge should take over lda BUF - cmp #$40 // '@' - bne !+ - ldx __tokenise_work1 // here is the size of input - jmp wedge_dos -!: -#endif // CONFIG_DOS_WEDGE +#if CONFIG_DOS_WEDGE + cmp #$40 // '@' + beq_far wedge_dos +#endif +#if CONFIG_TAPE_WEDGE + cmp #$1F // left arrow + beq_far wedge_tape +#endif + +#endif // Else, tokenise the line jsr tokenise_line diff --git a/c64/basic/commands/cmd_load.s b/c64/basic/commands/cmd_load.s index 9dfe60f0..20e2a501 100644 --- a/c64/basic/commands/cmd_load.s +++ b/c64/basic/commands/cmd_load.s @@ -69,13 +69,13 @@ got_devicenumber: lda #$00 sta SA jsr injest_comma - bcs got_secondaryaddress + bcs cmd_load_got_secondaryaddress jsr basic_parse_line_number lda LINNUM+1 bne !+ lda LINNUM+0 sta SA - jmp got_secondaryaddress + jmp cmd_load_got_secondaryaddress !: // Second parameter is above 255, this can't be a secondary address // Use it as load address instead @@ -85,7 +85,7 @@ got_devicenumber: ldy LINNUM+1 bne got_loadaddress -got_secondaryaddress: +cmd_load_got_secondaryaddress: // input for tape wedge ldy TXTTAB+1 ldx TXTTAB+0 @@ -97,16 +97,18 @@ got_loadaddress: jsr print_return pla plp - bcc !+ + bcc load_no_error // A = KERNAL error code, which also almost match - // basic ERROR codes, so we can just copy the - // error code to X, decrement, and handle normally + // basic ERROR codes tax dex + bpl !+ + ldx #B_ERR_BREAK +!: jmp do_basic_error -!: +load_no_error: // $YYXX is the last loaded address, so store it stx VARTAB+0 sty VARTAB+1 diff --git a/c64/basic/init/initmsg_real.s b/c64/basic/init/initmsg_real.s index 169a8cd3..5cb951a3 100644 --- a/c64/basic/init/initmsg_real.s +++ b/c64/basic/init/initmsg_real.s @@ -10,27 +10,35 @@ initmsg_real: ldy #>startup_banner jsr STROUT - ldx #$02 - ldy #$02 + ldx #$01 + ldy #$04 jsr plot_set lda #rom_revision_basic_string jsr STROUT - ldx #$04 - ldy #$02 + ldx #$03 + ldy #$04 jsr plot_set -#if CONFIG_SHOW_PAL_NTSC - jsr print_pal_ntsc -#endif - jsr initmsg_bytes_free - ldx #$07 + ldx #$06 ldy #$00 +#if CONFIG_SHOW_PAL_NTSC && CONFIG_SHOW_FEATURES + jsr plot_set + jsr print_features + jmp print_pal_ntsc +#elif CONFIG_SHOW_PAL_NTSC + jsr plot_set + jmp print_pal_ntsc +#elif CONFIG_SHOW_FEATURES + jsr plot_set + jmp print_features +#else jmp plot_set +#endif #elif CONFIG_BANNER_FANCY @@ -38,7 +46,7 @@ initmsg_real: ldy #>rainbow_logo jsr STROUT - ldx #$01 + ldx #$00 ldy #$0A jsr plot_set @@ -46,7 +54,7 @@ initmsg_real: ldy #>startup_banner jsr STROUT - ldx #$03 + ldx #$01 ldy #$0A jsr plot_set @@ -58,19 +66,27 @@ initmsg_real: ldy #>rom_revision_basic_string jsr STROUT - ldx #$05 - ldy #$00 + ldx #$03 + ldy #$0A jsr plot_set -#if CONFIG_SHOW_PAL_NTSC - jsr print_pal_ntsc -#endif - jsr initmsg_bytes_free - ldx #$07 + ldx #$06 ldy #$00 +#if CONFIG_SHOW_PAL_NTSC && CONFIG_SHOW_FEATURES + jsr plot_set + jsr print_features + jmp print_pal_ntsc +#elif CONFIG_SHOW_PAL_NTSC + jsr plot_set + jmp print_pal_ntsc +#elif CONFIG_SHOW_FEATURES + jsr plot_set + jmp print_features +#else jmp plot_set +#endif #elif CONFIG_BANNER_BRAND && CONFIG_BRAND_MEGA_65 @@ -88,8 +104,17 @@ initmsg_real: jsr initmsg_bytes_free +#if CONFIG_SHOW_FEATURES + ldx #$04 + ldy #$00 + jsr plot_set + jsr print_features + jmp print_return +#else ldx #$05 ldy #$00 jmp plot_set +#endif + #endif diff --git a/c64/basic/init/startup_banner.s b/c64/basic/init/startup_banner.s index 0fbc4049..8736df64 100644 --- a/c64/basic/init/startup_banner.s +++ b/c64/basic/init/startup_banner.s @@ -3,6 +3,8 @@ // Startup banner, to be displayed during cold start // +.encoding "petscii_upper" + .macro BANNER_TEXT() { @@ -22,7 +24,7 @@ startup_banner: #if CONFIG_BANNER_SIMPLE - .text " " + .text " " BANNER_TEXT() .byte $00 diff --git a/c64/basic/wedge_dos.s b/c64/basic/wedge_dos.s index 39e55ce9..b7292c5d 100644 --- a/c64/basic/wedge_dos.s +++ b/c64/basic/wedge_dos.s @@ -66,6 +66,7 @@ wedge_dos_command: !: // Retrieve status, print it if not OK jsr JCLALL + jsr print_return jsr wedge_dos_status_get lda BUF+0 cmp #$30 // '0' @@ -92,6 +93,7 @@ wedge_dos_change_drive: jmp do_ILLEGAL_DEVICE_NUMBER_error !: sta FA + jsr print_return jmp basic_end_of_line wedge_dos_status_get: @@ -133,7 +135,9 @@ wedge_dos_x1: rts wedge_dos_status: + jsr wedge_dos_status_get + jsr print_return // FALLTROUGH wedge_dos_status_print: @@ -178,6 +182,9 @@ wedge_dos_directory: jsr JCHRIN bcs wedge_dos_basic_error + // Print new line + jsr print_return + wedge_dos_directory_line: // Load a single line, reuse BASIC input buffer @@ -225,8 +232,6 @@ wedge_dos_directory_display: wedge_dos_clean_exit: jsr JCLALL - // Print new line - jsr print_return jmp basic_main_loop wedge_dos_basic_error: diff --git a/c64/basic/wedge_tape.s b/c64/basic/wedge_tape.s new file mode 100644 index 00000000..4edbe8e8 --- /dev/null +++ b/c64/basic/wedge_tape.s @@ -0,0 +1,34 @@ + +#if CONFIG_TAPE_WEDGE + + +// .X has to contain size of the buffer + +wedge_tape: + + lda #$FF + sta CURLIN+1 // in case of error do not print line number + + cpx #$02 + bne_far do_SYNTAX_error + + lda BUF+1 + cmp #$4C // 'L' + bne_far do_SYNTAX_error + + // Execute 'arrow + L' + + lda #$00 + sta FNLEN + + ldy #$01 + ldx #$07 // turbo tape device + jsr JSETFLS + + ldy TXTTAB+1 + ldx TXTTAB+0 + + jmp cmd_load_got_secondaryaddress + + +#endif // CONFIG_TAPE_WEDGE diff --git a/c64/kernal/stubs/e566.home_cursor.s b/c64/kernal/,stubs/e566.home_cursor.s similarity index 100% rename from c64/kernal/stubs/e566.home_cursor.s rename to c64/kernal/,stubs/e566.home_cursor.s diff --git a/c64/kernal/stubs/e566.interop b/c64/kernal/,stubs/e566.interop similarity index 100% rename from c64/kernal/stubs/e566.interop rename to c64/kernal/,stubs/e566.interop diff --git a/c64/kernal/stubs/e6b6.advance_cursor.s b/c64/kernal/,stubs/e6b6.advance_cursor.s similarity index 100% rename from c64/kernal/stubs/e6b6.advance_cursor.s rename to c64/kernal/,stubs/e6b6.advance_cursor.s diff --git a/c64/kernal/stubs/e6b6.interop b/c64/kernal/,stubs/e6b6.interop similarity index 100% rename from c64/kernal/stubs/e6b6.interop rename to c64/kernal/,stubs/e6b6.interop diff --git a/c64/kernal/stubs/e701.interop b/c64/kernal/,stubs/e701.interop similarity index 100% rename from c64/kernal/stubs/e701.interop rename to c64/kernal/,stubs/e701.interop diff --git a/c64/kernal/stubs/e701.previous_line.s b/c64/kernal/,stubs/e701.previous_line.s similarity index 100% rename from c64/kernal/stubs/e701.previous_line.s rename to c64/kernal/,stubs/e701.previous_line.s diff --git a/c64/kernal/stubs/e716.chrout_screen.s b/c64/kernal/,stubs/e716.chrout_screen.s similarity index 100% rename from c64/kernal/stubs/e716.chrout_screen.s rename to c64/kernal/,stubs/e716.chrout_screen.s diff --git a/c64/kernal/stubs/e716.interop b/c64/kernal/,stubs/e716.interop similarity index 100% rename from c64/kernal/stubs/e716.interop rename to c64/kernal/,stubs/e716.interop diff --git a/c64/kernal/stubs/e8ea.interop b/c64/kernal/,stubs/e8ea.interop similarity index 100% rename from c64/kernal/stubs/e8ea.interop rename to c64/kernal/,stubs/e8ea.interop diff --git a/c64/kernal/stubs/e8ea.scroll_line.s b/c64/kernal/,stubs/e8ea.scroll_line.s similarity index 100% rename from c64/kernal/stubs/e8ea.scroll_line.s rename to c64/kernal/,stubs/e8ea.scroll_line.s diff --git a/c64/kernal/stubs/e96c.insert_line_at_top.s b/c64/kernal/,stubs/e96c.insert_line_at_top.s similarity index 100% rename from c64/kernal/stubs/e96c.insert_line_at_top.s rename to c64/kernal/,stubs/e96c.insert_line_at_top.s diff --git a/c64/kernal/stubs/e96c.interop b/c64/kernal/,stubs/e96c.interop similarity index 100% rename from c64/kernal/stubs/e96c.interop rename to c64/kernal/,stubs/e96c.interop diff --git a/c64/kernal/stubs/e9ff.clear_line.s b/c64/kernal/,stubs/e9ff.clear_line.s similarity index 100% rename from c64/kernal/stubs/e9ff.clear_line.s rename to c64/kernal/,stubs/e9ff.clear_line.s diff --git a/c64/kernal/stubs/e9ff.interop b/c64/kernal/,stubs/e9ff.interop similarity index 100% rename from c64/kernal/stubs/e9ff.interop rename to c64/kernal/,stubs/e9ff.interop diff --git a/c64/kernal/stubs/f646.iec_close.s b/c64/kernal/,stubs/f646.iec_close.s similarity index 100% rename from c64/kernal/stubs/f646.iec_close.s rename to c64/kernal/,stubs/f646.iec_close.s diff --git a/c64/kernal/stubs/f646.interop b/c64/kernal/,stubs/f646.interop similarity index 100% rename from c64/kernal/stubs/f646.interop rename to c64/kernal/,stubs/f646.interop diff --git a/c64/kernal/stubs/fd90.interop b/c64/kernal/,stubs/fd90.interop similarity index 100% rename from c64/kernal/stubs/fd90.interop rename to c64/kernal/,stubs/fd90.interop diff --git a/c64/kernal/stubs/fd90.unknown.s b/c64/kernal/,stubs/fd90.unknown.s similarity index 100% rename from c64/kernal/stubs/fd90.unknown.s rename to c64/kernal/,stubs/fd90.unknown.s diff --git a/c64/kernal/assets/colour_codes.s b/c64/kernal/assets/e8da.colour_codes.s similarity index 100% rename from c64/kernal/assets/colour_codes.s rename to c64/kernal/assets/e8da.colour_codes.s diff --git a/c64/kernal/assets/e8da.interop b/c64/kernal/assets/e8da.interop new file mode 100644 index 00000000..2aa8069b --- /dev/null +++ b/c64/kernal/assets/e8da.interop @@ -0,0 +1,6 @@ + +A color code table, see here: +- https://csdb.dk/forums/index.php?roomid=7&topicid=487 + +CCGMS termina program expects it to be under original location, see here: +- https://raw.githubusercontent.com/spathiwa/ccgmsterm/master/original/5a.gs diff --git a/c64/kernal/assets/kernal_messages.s b/c64/kernal/assets/kernal_messages.s index 0e8b6abe..a14954c1 100644 --- a/c64/kernal/assets/kernal_messages.s +++ b/c64/kernal/assets/kernal_messages.s @@ -3,6 +3,9 @@ // Messages to be prined out by Kernal // +.encoding "petscii_upper" + + // Double underscore prevents labels from being passed to VICE (would confuse monitor) .label __MSG_KERNAL_SEARCHING_FOR = __msg_kernalsearching_for - __msg_kernal_first @@ -12,6 +15,11 @@ .label __MSG_KERNAL_FROM_HEX = __msg_kernalfrom_hex - __msg_kernal_first .label __MSG_KERNAL_TO_HEX = __msg_kernalto_hex - __msg_kernal_first +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO +.label __MSG_KERNAL_PRESS_PLAY = __msg_kernalplay - __msg_kernal_first +.label __MSG_KERNAL_FOUND = __msg_kernalfound - __msg_kernal_first +#endif + #if CONFIG_SHOW_PAL_NTSC .label __MSG_KERNAL_PAL = __msg_kernalpal - __msg_kernal_first .label __MSG_KERNAL_NTSC = __msg_kernalntsc - __msg_kernal_first @@ -22,6 +30,9 @@ .label __MSG_KERNAL_PANIC_ROM_MISMATCH = __msg_kernalpanic_rom_mismatch - __msg_kernal_first #endif +#if CONFIG_SHOW_FEATURES +.label __MSG_KERNAL_FEATURES = __msg_kernalfeatures - __msg_kernal_first +#endif __msg_kernal_first: @@ -42,8 +53,8 @@ __msg_kernalverifying: __msg_kernalsaving: .byte $0D - .text "SAVIN" - .byte $80 + $47 // end of string mark + 'G' + .text "SAVING" + .byte $80 + $20 // end of string mark + space __msg_kernalfrom_hex: .text " FROM " @@ -53,15 +64,30 @@ __msg_kernalto_hex: .text " TO " .byte $80 + $24 // end of string mark + '$' +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + +__msg_kernalplay: + .byte $0D + .text "PRESS PLAY ON TAPE" + .byte $80 + $0D // end of string mark + return + +__msg_kernalfound: + .text "FOUND" + .byte $80 + $20 // end of string mark + space + +#endif + #if CONFIG_SHOW_PAL_NTSC __msg_kernalpal: - .text "PAL," - .byte $80 + $20 // end of string mark + space + .text "PAL" + .byte $0D + .byte $80 + $0D // end of string mark + return __msg_kernalntsc: - .text "NTSC," - .byte $80 + $20 // end of string mark + space + .text "NTSC" + .byte $0D + .byte $80 + $0D // end of string mark + return #endif // CONFIG_SHOW_PAL_NTSC @@ -76,3 +102,11 @@ __msg_kernalpanic_rom_mismatch: .byte $80 + $48 // end of string mark + 'H' #endif // CONFIG_PANIC_SCREEN + +#if CONFIG_SHOW_FEATURES + +__msg_kernalfeatures: + .text BUILD_FEATURES_STR() + .byte $80 + $0D // end of string mark + return + +#endif // CONFIG_SHOW_FEATURES diff --git a/c64/kernal/chkinout_real.s b/c64/kernal/chkinout_real.s deleted file mode 100644 index 18bc6bc7..00000000 --- a/c64/kernal/chkinout_real.s +++ /dev/null @@ -1,141 +0,0 @@ - -// -// Official Kernal routines, described in: -// -// - [RG64] C64 Programmer's Reference Guide - page 275 (CHKIN) / 276 (CKOUT) -// - [CM64] Compute's Mapping the Commodore 64 - page 229 -// -// CPU registers that has to be preserved (see [RG64]): .Y, possibly .A (XXX - see [CM64], page 213) -// - - -// CHKIN implementation - -chkin_real: - - // Store Y for preservation - phy_trash_a - - // Reset status - jsr kernalstatus_reset - - // First retrieve the FAT/LAT/SAT table index (and check if file is open) - - txa - jsr find_fls - bcs chkinout_file_not_open - - // Now we have table index in Y - first filter out unsuitable devices - - lda FAT,Y - cmp #$01 - beq chkinout_device_not_present // tape not implemented - cmp #$02 - beq chkinout_device_not_present // RS-232 not implemented - - // Fail if the file is open for writing (secondary address 1) - - lda LAT, Y - cmp #$01 - beq chkinout_file_not_input - - // For IEC devices, send TALK + TKSA first - lda FAT,Y - jsr iec_check_devnum - bcs chkin_set_device - - jsr TALK - bcs chkinout_device_not_present // don't set DFLTN in case of failure - - lda LAT, Y - jsr TKSA - bcs chkinout_device_not_present - -chkin_set_device: - lda FAT,Y - sta DFLTN - clc // for success - // FALLTROUGH - -// Common part for booth CHKIN and CKOUT -// XXX add CPU-dependent optimizations here - -chkinout_end: - tax - pla - tay - txa - rts - -chkinout_file_not_open: - pla - tay - jmp kernalerror_FILE_NOT_OPEN - -chkinout_device_not_present: - pla - tay - jsr kernalstatus_DEVICE_NOT_FOUND - jmp kernalerror_DEVICE_NOT_FOUND - -chkinout_file_not_input: - pla - tay - jmp kernalerror_FILE_NOT_INPUT - -chkinout_file_not_output: - pla - tay - jmp kernalerror_FILE_NOT_OUTPUT - -// CKOUT implementation - -ckout_real: - - // Store Y for preservation - tya - pha - - // Reset status - jsr kernalstatus_reset - - // First retrieve the FAT/LAT/SAT table index (and check if file is open) - - txa - jsr find_fls - bcs chkinout_file_not_open - - // Now we have table index in Y - first filter out unsuitable devices - - lda FAT,Y - cmp #$01 - beq chkinout_device_not_present // tape not implemented - cmp #$02 - beq chkinout_device_not_present // RS-232 not implemented - - cmp #$00 - beq chkinout_file_not_output // cannot output to keyboard - XXX check real ROM behaviour - - // Fail if the file is open for reading (secondary address 0) - - lda LAT, Y - beq chkinout_file_not_output - - // For IEC devices, send LISTEN + SECOND first - lda FAT,Y - jsr iec_check_devnum - bcs chkout_set_device - - jsr LISTEN - bcs chkinout_device_not_present // don't set DFLTO in case of failure - - lda LAT, Y - jsr SECOND - bcs chkinout_device_not_present - -chkout_set_device: - lda FAT,Y - sta DFLTO - clc // for success - - jmp chkinout_end diff --git a/c64/kernal/close_load.s b/c64/kernal/close_load.s deleted file mode 100644 index efb0b013..00000000 --- a/c64/kernal/close_load.s +++ /dev/null @@ -1,23 +0,0 @@ - - -// Common ppart of CLOSE and LOAD routines - -close_load: - - tax - - // Command drive to stop talking and to close the file - jsr UNTLK - - txa - jsr LISTEN - - lda #$E0 // CLOSE command - sta TBTCNT - jsr iec_tx_command - jsr iec_tx_command_finalize - - // Tell drive to unlisten - jsr UNLSN - - rts diff --git a/c64/kernal/errors.s b/c64/kernal/errors.s index 70f9847e..73e6c552 100644 --- a/c64/kernal/errors.s +++ b/c64/kernal/errors.s @@ -63,17 +63,19 @@ kernalstatus_reset: sta IOSTATUS rts -kernalstatus_TIMEOUT_WRITE: // XXX detect this! - lda IOSTATUS - ora #K_STS_TIMEOUT_WRITE - sta IOSTATUS - rts +// The following two statuses are currentl not implemented - and most likely not really needed -kernalstatus_TIMEOUT_READ: // XXX detect this! - lda IOSTATUS - ora #K_STS_TIMEOUT_READ - sta IOSTATUS - rts +// kernalstatus_TIMEOUT_WRITE: +// lda IOSTATUS +// ora #K_STS_TIMEOUT_WRITE +// sta IOSTATUS +// rts + +// kernalstatus_TIMEOUT_READ: +// lda IOSTATUS +// ora #K_STS_TIMEOUT_READ +// sta IOSTATUS +// rts kernalstatus_EOI: lda IOSTATUS diff --git a/c64/kernal/f157.chrin.jmp.s b/c64/kernal/f157.chrin.jmp.s deleted file mode 100644 index b1b7c234..00000000 --- a/c64/kernal/f157.chrin.jmp.s +++ /dev/null @@ -1,6 +0,0 @@ - -// Our implementation is longer than the original one, -// placing it here would cause a collision with CHROUT - -CHRIN: - jmp chrin_real diff --git a/c64/kernal/f20e.chkin.jmp.s b/c64/kernal/f20e.chkin.jmp.s deleted file mode 100644 index ba38979d..00000000 --- a/c64/kernal/f20e.chkin.jmp.s +++ /dev/null @@ -1,6 +0,0 @@ - -// In our implementation CHKIN and CKOUT are closely tied, -// placing it here would cause a collision - -CHKIN: - jmp chkin_real diff --git a/c64/kernal/f250.ckout.jmp.s b/c64/kernal/f250.ckout.jmp.s deleted file mode 100644 index 18cfbffc..00000000 --- a/c64/kernal/f250.ckout.jmp.s +++ /dev/null @@ -1,6 +0,0 @@ - -// In our implementation CHKIN and CKOUT are closely tied, -// placing it here would cause a collision - -CKOUT: - jmp ckout_real diff --git a/c64/kernal/f291.close.s b/c64/kernal/f291.close.s deleted file mode 100644 index ca60794b..00000000 --- a/c64/kernal/f291.close.s +++ /dev/null @@ -1,64 +0,0 @@ - -// -// Official Kernal routine, described in: -// -// - [RG64] C64 Programmer's Reference Guide - page 281/282 -// - [CM64] Compute's Mapping the Commodore 64 - page 229/230 -// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command) -// -// CPU registers that has to be preserved (see [RG64]): none -// - -CLOSE: - - // XXX this needs more testing (opening 10 files at once, closing in various orders, etc) once the code is more mature - - // Find the LAT / SAT / FAT entry which LAT corresponds to A - - jsr find_fls - bcs close_error_not_found // XXX can we report error in IOSTATUS here? - - // We have the entry index in Y - check whether this is IEC device - lda FAT, y - jsr iec_check_devnum - bcs close_remove_from_table - - // IEC device - - jsr iec_tx_flush // make sure no byte is awaiting - lda SAT, y // get secondary address - cmp #$60 - bne !+ - // workaround for using CLOSE on reading executable - XXX is this a proper way? - jsr close_load - jmp close_remove_from_table -!: - ora $E0 // CLOSE command - sta TBTCNT - jsr iec_tx_command - bcs close_remove_from_table - jsr iec_tx_command_finalize - -close_remove_from_table: - // Remove channel from the table - iny - cpy #$0A - bpl !+ - lda LAT, y - sta LAT-1, y - lda FAT, y - sta FAT-1, y - lda SAT, y - sta SAT-1, y - jmp close_remove_from_table -!: - // Decrement the list size variable - dec LDTND - - clc // report success - not sure if original CLOSE does this, but it's nevertheless a good practice - rts - -close_error_not_found: - - sec // report success - not sure if original CLOSE does this, but it's nevertheless a good practice - rts diff --git a/c64/kernal/f333.clrchn.jmp.s b/c64/kernal/f333.clrchn.jmp.s deleted file mode 100644 index 7c56fe28..00000000 --- a/c64/kernal/f333.clrchn.jmp.s +++ /dev/null @@ -1,6 +0,0 @@ - -// Our implementation is longer than the original one, -// placing it here would cause a collision with OPEN - -CLRCHN: - jmp clrchn_real diff --git a/c64/kernal/f49e.load_int.s b/c64/kernal/f49e.load_int.s deleted file mode 100644 index 837d896c..00000000 --- a/c64/kernal/f49e.load_int.s +++ /dev/null @@ -1,13 +0,0 @@ - -// -// XXX Note: something unusual was done with LOAD routine - although the vector at $330 points to $F4A5, -// the Kernal jump table points to $F49E (see also Mapping the C64, page 76). By experimenting -// I have already discovered that $F4A5 performs indirect jump via ($0330) vector, but it must -// be doing a little bit more - not sure yet, what. Something similar is done with SAVE. -// -// This has to be clarified. -// - -LOAD_INT: - jmp (ILOAD) - diff --git a/c64/kernal/f4a5.load.s b/c64/kernal/f4a5.load.s deleted file mode 100644 index 76307dc6..00000000 --- a/c64/kernal/f4a5.load.s +++ /dev/null @@ -1,144 +0,0 @@ -// -// Official Kernal routine, described in: -// -// - [RG64] C64 Programmer's Reference Guide - page 286 -// - [CM64] Compute's Mapping the Commodore 64 - page 231 -// - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf -// -// CPU registers that has to be preserved (see [RG64]): none -// - - - // Expects that SETLFS and SETNAM are called before hand. - // $YYXX = load address. - // (ignored if SETLFS channel = 1, i.e., like ,8,1) - // If A=1 then VERIFY instead of LOAD. - // On exit, $YYXX is the highest address into which data - // will have been placed. - - // XXX honor MSGFLG bit 6 - // XXX add VERIFY support - -LOAD: - - // Are we loading or verifying? - sta VERCKK - - // Store start address of LOAD - stx STAL+0 - sty STAL+1 - - // Reset status - jsr kernalstatus_reset - -#if CONFIG_MEMORY_MODEL_60K - // We need our helpers to get to filenames under ROMs or IO area - jsr install_ram_routines -#endif - - // Check whether we support the requested device - lda FA - and #$FC - bne !+ - jmp lvs_illegal_device_number // device number below 4, not an IEC device -!: - // Device numbers above 30 are also illegal (see https://www.pagetable.com/?p=1031), - // as the protocol combines device number with command code int one byte, - // above 30 it is no longer possible (UNLISTEN and UNTALK codes prevent using - // number 31), yet original ROMs show ILLEGAL DEVICE NUMBER error only - // for devices 0-3; in our implementation LISTEN / TALK will cause device - // not present detected for numbers above 30 - - // Display SEARCHING FOR + filename - jsr lvs_display_searching_for - - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - // p13, 16; also p16 tells us this routine doesn't mess with the file table - // in the C64, only in the drive. - - // Call device to LISTEN (p16) - lda FA - jsr LISTEN - bcc !+ - jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine -!: - // Open channel 0 (reserved for file reading) - lda #$00 - jsr iec_cmd_open - bcc !+ - jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine -!: - // Send file name - jsr lvs_send_file_name - bcc !+ - jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine -!: - // Now command device to talk (p16) - lda FA - jsr TALK - bcc !+ - jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine -!: - lda #$60 // open channel / data (p3) , required according to p13 - sta TBTCNT - jsr iec_tx_command - bcc !+ - jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine -!: - // We are currently talker, so do the IEC turn around so that we - // are the listener (p16) - jsr iec_turnaround_to_listen - bcc !+ - jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine -!: - // Get load address and store it if secondary address is zero - jsr iec_rx_byte - bcc !+ - jmp kernalerror_FILE_NOT_FOUND // XXX deduplicate with other jumps in this routine -!: - ldx SA - beq !+ - sta STAL+0 -!: - jsr iec_rx_byte - bcc !+ - jmp kernalerror_FILE_NOT_FOUND // XXX deduplicate with other jumps in this routine -!: - ldx SA - beq !+ - sta STAL+1 -!: - // Display start address - jsr lvs_display_loading_verifying - -load_loop: - // We are now ready to receive bytes - jsr iec_rx_byte - bcc !+ - jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine -!: - // Handle the byte (store in memory / verify) - jsr lvs_handle_byte_load_verify - bcc !+ - jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine -!: - // Advance pointer to data - jsr lvs_advance_pointer - bcc !+ - jmp lvs_wrap_around_error -!: - // Check for EOI - if so, this was the last byte - lda IOSTATUS - and #K_STS_EOI - beq load_loop - - // Display end address - jsr lvs_display_done - - // Close file on drive - - lda FA - jsr close_load - - // Return last address - jmp lvs_return_last_address diff --git a/c64/kernal/f5dd.save_int.s b/c64/kernal/f5dd.save_int.s deleted file mode 100644 index 7ef54a41..00000000 --- a/c64/kernal/f5dd.save_int.s +++ /dev/null @@ -1,12 +0,0 @@ - -// -// XXX Note: something unusual was done with LOAD routine - although the vector at $330 points to $F4A5, -// the Kernal jump table points to $F49E (see also Mapping the C64, page 76). By experimenting -// I have already discovered that $F4A5 performs indirect jump via ($0330) vector, but it must -// be doing a little bit more - not sure yet, what. Something similar is done with SAVE. -// -// This has to be clarified. -// - -SAVE_INT: - jmp (ISAVE) diff --git a/c64/kernal/iec/acptr.s b/c64/kernal/iec/acptr.s index b7ee27ce..e5e818e7 100644 --- a/c64/kernal/iec/acptr.s +++ b/c64/kernal/iec/acptr.s @@ -10,5 +10,21 @@ ACPTR: - jsr kernalstatus_reset + + lda IOSTATUS + beq !+ + + lda #$0D // tested on real ROMs + clc + rts +!: + +#if CONFIG_IEC +#if CONFIG_IEC_JIFFYDOS + jmp iec_rx_dispatch +#else // no turbo supported jmp iec_rx_byte +#endif +#else + jmp kernalerror_ILLEGAL_DEVICE_NUMBER +#endif diff --git a/c64/kernal/iec/chkin_iec.s b/c64/kernal/iec/chkin_iec.s new file mode 100644 index 00000000..b86dee9c --- /dev/null +++ b/c64/kernal/iec/chkin_iec.s @@ -0,0 +1,31 @@ + +// +// IEC part of the CHKIN routine +// + + +#if CONFIG_IEC + + +chkin_iec: + + // Fail if the file is open for writing (secondary address 1) + + lda LAT, Y + cmp #$01 + beq_far chkin_file_not_input + + // Send TALK + TKSA first + lda FAT,Y + + jsr TALK + bcs_far chkinout_device_not_present + + lda LAT, Y + ora #$60 + jsr TKSA + bcs_far chkinout_device_not_present + + jmp chkin_set_device + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/chrin_iec.s b/c64/kernal/iec/chrin_iec.s new file mode 100644 index 00000000..93ad7afc --- /dev/null +++ b/c64/kernal/iec/chrin_iec.s @@ -0,0 +1,10 @@ + +// +// IEC part of the CHRIN routine +// + + +chrin_iec: + + // XXX is this really all? + jmp JACPTR diff --git a/c64/kernal/iec/chrout_iec.s b/c64/kernal/iec/chrout_iec.s new file mode 100644 index 00000000..38924b76 --- /dev/null +++ b/c64/kernal/iec/chrout_iec.s @@ -0,0 +1,12 @@ + +// +// IEC part of the CHROUT routine +// + + +chrout_iec: + + lda SCHAR + jsr JCIOUT + bcc_far chrout_done_success + jmp chrout_done_fail diff --git a/c64/kernal/ciout.s b/c64/kernal/iec/ciout.s similarity index 82% rename from c64/kernal/ciout.s rename to c64/kernal/iec/ciout.s index 3d84170c..4c6137bd 100644 --- a/c64/kernal/ciout.s +++ b/c64/kernal/iec/ciout.s @@ -11,6 +11,8 @@ CIOUT: +#if CONFIG_IEC + pha lda C3PO bne ciout_send_byte @@ -31,7 +33,17 @@ ciout_store_in_buffer: ciout_send_byte: clc // don't send with EOI +#if CONFIG_IEC_JIFFYDOS + jsr iec_tx_dispatch +#else // no turbo supported jsr iec_tx_byte +#endif inc C3PO // iec_tx_byte sets it to 0, but we still have something to send jmp ciout_store_in_buffer +#else + + sec // indicate failure + rts + +#endif diff --git a/c64/kernal/iec/ckout_iec.s b/c64/kernal/iec/ckout_iec.s new file mode 100644 index 00000000..662f4840 --- /dev/null +++ b/c64/kernal/iec/ckout_iec.s @@ -0,0 +1,31 @@ + +// +// IEC part of the CKOUT routine +// + + +#if CONFIG_IEC + + +ckout_iec: + + // Fail if the file is open for reading (secondary address 0) + + lda LAT, Y + beq_far ckout_file_not_output + + // Send LISTEN + SECOND first + lda FAT,Y + + jsr LISTEN + bcs_far chkinout_device_not_present + + lda LAT, Y + ora #$60 + jsr SECOND + bcs_far chkinout_device_not_present + + jmp ckout_set_device + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/close_iec.s b/c64/kernal/iec/close_iec.s new file mode 100644 index 00000000..0cdc2801 --- /dev/null +++ b/c64/kernal/iec/close_iec.s @@ -0,0 +1,35 @@ + +// +// IEC part of the CLOSE routine +// + + +#if CONFIG_IEC + + +// .Y contains LAT/FAT/SAT table index, it should stay this way + +close_iec: + + jsr iec_tx_flush // make sure no byte is awaiting + lda SAT, y // get secondary address + cmp #$60 + bne !+ + + // workaround for using CLOSE on reading executable - XXX is this a proper way? + jsr iec_close_load + jmp close_remove_from_table + +!: + ora $E0 // CLOSE command + sta TBTCNT + jsr iec_tx_command + bcs close_iec_end + jsr iec_tx_command_finalize + +close_iec_end: + + jmp close_remove_from_table + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/clrchn_iec.s b/c64/kernal/iec/clrchn_iec.s new file mode 100644 index 00000000..84993a0c --- /dev/null +++ b/c64/kernal/iec/clrchn_iec.s @@ -0,0 +1,30 @@ + +// +// IEC part of the CLRCHN routine +// + + +#if CONFIG_IEC + + +clrchn_iec: + + // Check input device + lda DFLTN + jsr iec_check_devnum_oc + bcs !+ + + // It was IEC device - send UNTALK first + jsr UNTLK +!: + // Check output device + lda DFLTO + jsr iec_check_devnum_oc + + // If it was IEC device - send UNLSN first + bcc_far UNLSN + + rts + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_check_devnum.s b/c64/kernal/iec/iec_check_devnum.s index 0071392b..e6ac9c08 100644 --- a/c64/kernal/iec/iec_check_devnum.s +++ b/c64/kernal/iec/iec_check_devnum.s @@ -5,18 +5,29 @@ // Preserves .A, .X and .Y // -iec_check_devnum: - // 0, 1, 2, or 3 are illegal - reserved for non-IEC devices on Commodore - cmp #$04 - bcs !+ + +#if CONFIG_IEC + +iec_check_devnum_lvs: // for load/verify/save + + cmp #$08 // below 8 are illegal for load/save + bcc iec_check_devnum_failed + // FALLTROUGH -iec_check_devnum_failed: - sec // indicate non-IEC device - rts -!: + +iec_check_devnum_oc: // for open/close + + cmp #$04 // below 4 are illegal, reserved for non-IEC devices on Commodore + bcc iec_check_devnum_failed + // 31 and above are illegal too, due to IEC command encoding scheme, // see https://www.pagetable.com/?p=1031 - cmp #$1F - bcs iec_check_devnum_failed - // Carry is clear here - indicates IEC device + cmp #$1F // sets carry for 31 or above rts + +iec_check_devnum_failed: + + sec // indicate non-IEC device + rts + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_close_load.s b/c64/kernal/iec/iec_close_load.s new file mode 100644 index 00000000..5cc8e76a --- /dev/null +++ b/c64/kernal/iec/iec_close_load.s @@ -0,0 +1,31 @@ + +// +// Common part of CLOSE and LOAD/SAVE routines for IEC +// + + +#if CONFIG_IEC + + +iec_close_load: + + tax + + // Command drive to stop talking before closing the file + jsr UNTLK + + txa + jsr LISTEN + + lda #$E0 // CLOSE command + sta TBTCNT + jsr iec_tx_command + jsr iec_tx_command_finalize + + // Tell drive to unlisten + jsr UNLSN + + rts + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_cmd_close.s b/c64/kernal/iec/iec_cmd_close.s index 114cf0e4..126cb04e 100644 --- a/c64/kernal/iec/iec_cmd_close.s +++ b/c64/kernal/iec/iec_cmd_close.s @@ -5,6 +5,10 @@ // - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc // + +#if CONFIG_IEC + + iec_cmd_close: jsr iec_check_channel_openclose @@ -14,3 +18,6 @@ iec_cmd_close: ora #$E0 jmp common_open_close_unlsn_second + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_cmd_open.s b/c64/kernal/iec/iec_cmd_open.s index 5cc86ccb..48fceb28 100644 --- a/c64/kernal/iec/iec_cmd_open.s +++ b/c64/kernal/iec/iec_cmd_open.s @@ -6,6 +6,9 @@ // +#if CONFIG_IEC + + iec_cmd_open: // similar to TKSA, but without turnaround jsr iec_check_channel_openclose @@ -40,3 +43,6 @@ iec_check_channel_openclose: !: clc // mark suitable channel number rts + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_pull_atn_clk_release_data.s b/c64/kernal/iec/iec_pull_atn_clk_release_data.s deleted file mode 100644 index 62da6f12..00000000 --- a/c64/kernal/iec/iec_pull_atn_clk_release_data.s +++ /dev/null @@ -1,15 +0,0 @@ - -iec_pull_atn_clk_release_data: - - // Pulled CLK = DATA considered invalid; for extra robustness on non-emulated - // hardware give some lines few more cycles to stabilize; see page 10 of - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - - lda CIA2_PRA - ora #BIT_CIA2_PRA_ATN_OUT // pull - sta CIA2_PRA - ora #BIT_CIA2_PRA_CLK_OUT // pull - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_DAT_OUT // release - sta CIA2_PRA - rts diff --git a/c64/kernal/iec/iec_pull_clk_release_data.s b/c64/kernal/iec/iec_pull_clk_release_data.s deleted file mode 100644 index 2b1a58f8..00000000 --- a/c64/kernal/iec/iec_pull_clk_release_data.s +++ /dev/null @@ -1,13 +0,0 @@ - -iec_pull_clk_release_data: - - // Pulled CLK = DATA considered invalid; for extra robustness on non-emulated - // hardware give some lines few more cycles to stabilize; see page 10 of - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - - lda CIA2_PRA - ora #BIT_CIA2_PRA_CLK_OUT // pull - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_DAT_OUT // release - sta CIA2_PRA - rts diff --git a/c64/kernal/iec/iec_pull_clk_release_data_oneshot.s b/c64/kernal/iec/iec_pull_clk_release_data_oneshot.s deleted file mode 100644 index b2a80988..00000000 --- a/c64/kernal/iec/iec_pull_clk_release_data_oneshot.s +++ /dev/null @@ -1,8 +0,0 @@ - -iec_pull_clk_release_data_oneshot: - - lda CIA2_PRA - ora #BIT_CIA2_PRA_CLK_OUT // pull - and #$FF - BIT_CIA2_PRA_DAT_OUT // release - sta CIA2_PRA - rts diff --git a/c64/kernal/iec/iec_pull_data_release_atn_clk.s b/c64/kernal/iec/iec_pull_data_release_atn_clk.s deleted file mode 100644 index f7c71da4..00000000 --- a/c64/kernal/iec/iec_pull_data_release_atn_clk.s +++ /dev/null @@ -1,15 +0,0 @@ - -iec_pull_data_release_atn_clk: - - // Released CLK = DATA considered valid; for extra robustness on non-emulated - // hardware give some lines few more cycles to stabilize; see page 10 of - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - - lda CIA2_PRA - ora #BIT_CIA2_PRA_DAT_OUT // pull - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_CLK_OUT // release - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_ATN_OUT // release - sta CIA2_PRA - rts diff --git a/c64/kernal/iec/iec_pull_release.s b/c64/kernal/iec/iec_pull_release.s new file mode 100644 index 00000000..8be0e851 --- /dev/null +++ b/c64/kernal/iec/iec_pull_release.s @@ -0,0 +1,85 @@ + +// +// Helper IEC routines to pull/release certain lines +// +// Order of operation is set for extra robustness, on non-emulated hardware +// lines might need few cycles to stabilize (released CLK = DATA considered valid), +// see page 10 of http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf +// + + + +#if CONFIG_IEC + + +iec_pull_atn_clk_release_data: + + lda CIA2_PRA + ora #BIT_CIA2_PRA_ATN_OUT // pull + sta CIA2_PRA + + // FALLTROUGH + +iec_pull_clk_release_data: + + lda CIA2_PRA + ora #BIT_CIA2_PRA_CLK_OUT // pull + sta CIA2_PRA +!: + and #$FF - BIT_CIA2_PRA_DAT_OUT // release + bne iec_pull_release_end // branch always + +iec_pull_clk_release_data_oneshot: + + lda CIA2_PRA + ora #BIT_CIA2_PRA_CLK_OUT // pull + bne !- // branch always + +iec_release_atn_clk_data: + + lda CIA2_PRA + and #$FF - BIT_CIA2_PRA_ATN_OUT // release + sta CIA2_PRA + + // FALLTROUGH + +iec_release_clk_data: + + lda CIA2_PRA + and #$FF - BIT_CIA2_PRA_DAT_OUT // release + sta CIA2_PRA + and #$FF - BIT_CIA2_PRA_CLK_OUT // release + jmp iec_pull_release_end + +iec_release_clk_pull_data: + + lda CIA2_PRA + ora #BIT_CIA2_PRA_DAT_OUT // pull + sta CIA2_PRA + and #$FF - BIT_CIA2_PRA_CLK_OUT // release + bne iec_pull_release_end // branch always + +iec_pull_data_release_atn_clk: + + lda CIA2_PRA + ora #BIT_CIA2_PRA_DAT_OUT // pull + sta CIA2_PRA + and #$FF - BIT_CIA2_PRA_CLK_OUT // release + sta CIA2_PRA + + // FALLTROUGH + +iec_release_atn: + + lda CIA2_PRA + and #$FF - BIT_CIA2_PRA_ATN_OUT // release + + // FALLTROUGH + +iec_pull_release_end: + + sta CIA2_PRA + rts + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_release_atn.s b/c64/kernal/iec/iec_release_atn.s deleted file mode 100644 index d7493aa0..00000000 --- a/c64/kernal/iec/iec_release_atn.s +++ /dev/null @@ -1,8 +0,0 @@ - -iec_release_atn: - - lda CIA2_PRA - and #$FF - BIT_CIA2_PRA_ATN_OUT // release - sta CIA2_PRA - rts - diff --git a/c64/kernal/iec/iec_release_atn_clk_data.s b/c64/kernal/iec/iec_release_atn_clk_data.s deleted file mode 100644 index 07f5c4da..00000000 --- a/c64/kernal/iec/iec_release_atn_clk_data.s +++ /dev/null @@ -1,16 +0,0 @@ - -iec_release_atn_clk_data: - - // Released CLK = DATA considered valid; for extra robustness on non-emulated - // hardware give some lines few more cycles to stabilize; see page 10 of - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - - lda CIA2_PRA - and #$FF - BIT_CIA2_PRA_ATN_OUT // release - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_DAT_OUT // release - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_CLK_OUT // release - sta CIA2_PRA - rts - diff --git a/c64/kernal/iec/iec_release_clk_data.s b/c64/kernal/iec/iec_release_clk_data.s deleted file mode 100644 index 83af42aa..00000000 --- a/c64/kernal/iec/iec_release_clk_data.s +++ /dev/null @@ -1,13 +0,0 @@ - -iec_release_clk_data: - - // Released CLK = DATA considered valid; for extra robustness on non-emulated - // hardware give some lines few more cycles to stabilize; see page 10 of - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - - lda CIA2_PRA - and #$FF - BIT_CIA2_PRA_DAT_OUT // release - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_CLK_OUT // release - sta CIA2_PRA - rts diff --git a/c64/kernal/iec/iec_release_clk_pull_data.s b/c64/kernal/iec/iec_release_clk_pull_data.s deleted file mode 100644 index 359c02f3..00000000 --- a/c64/kernal/iec/iec_release_clk_pull_data.s +++ /dev/null @@ -1,13 +0,0 @@ - -iec_release_clk_pull_data: - - // Released CLK = DATA considered valid; for extra robustness on non-emulated - // hardware give some lines few more cycles to stabilize; see page 10 of - // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf - - lda CIA2_PRA - ora #BIT_CIA2_PRA_DAT_OUT // pull - sta CIA2_PRA - and #$FF - BIT_CIA2_PRA_CLK_OUT // release - sta CIA2_PRA - rts diff --git a/c64/kernal/iec/iec_return.s b/c64/kernal/iec/iec_return.s index de3f8b01..b73a8d1f 100644 --- a/c64/kernal/iec/iec_return.s +++ b/c64/kernal/iec/iec_return.s @@ -8,6 +8,10 @@ // take care about .A and IOSTATUS // + +#if CONFIG_IEC + + iec_return_success: // BSOUR is certainly not valid anymore @@ -32,3 +36,6 @@ iec_return_DEVICE_NOT_FOUND: plx_trash_a // Report error jmp kernalerror_DEVICE_NOT_FOUND + + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_rx_byte.s b/c64/kernal/iec/iec_rx_byte.s index 2f859cf7..5297a4ae 100644 --- a/c64/kernal/iec/iec_rx_byte.s +++ b/c64/kernal/iec/iec_rx_byte.s @@ -4,6 +4,10 @@ // // Preserves .X and .Y registers + +#if CONFIG_IEC + + iec_rx_byte: // Store .X and .Y on the stack - preserve them @@ -107,16 +111,8 @@ iec_rx_clk_wait2: // Timeout jsr kernalstatus_EOI pla - - // Restore registers - pla - tay - pla - tax - - sec // XXX confirm that sec is really a way to report timeout here - cli - rts + + jmp iec_rx_end !: // More bits? dex @@ -128,18 +124,23 @@ iec_rx_clk_wait2: // the next byte. (p11). jsr iec_release_clk_pull_data - // Retreive the received byte + // Retrieve the received byte pla // Restore registers sta TBTCNT // $A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html - pla - tay - pla - tax + + // FALLTROUGH + +iec_rx_end: + + ply_trash_a + plx_trash_a lda TBTCNT clc cli rts + +#endif // CONFIG_IEC diff --git a/c64/kernal/iec/iec_send_file_name.s b/c64/kernal/iec/iec_send_file_name.s new file mode 100644 index 00000000..7530f7a0 --- /dev/null +++ b/c64/kernal/iec/iec_send_file_name.s @@ -0,0 +1,44 @@ + +// +// Sends file (stream) name to IEC device +// + + +#if CONFIG_IEC + + +iec_send_file_name: + ldy #0 + +iec_send_file_name_loop: + cpy FNLEN + beq iec_send_file_name_done + +#if CONFIG_MEMORY_MODEL_60K + ldx #$033C - sta TAPE1+1 - - // set screen address to $0400 - // https://www.c64-wiki.com/wiki/Screen_RAM - // Since we are setting $D018, we also make sure we are using the - // ROM character set (C64 Programmer's Reference Guide p322) - lda #$14 - sta VIC_YMCSB - - // Make sure we have the correct VIC-II memory bank for the screen to really be at $0400 - // and not $4400, $8400 or $C400 - // https://www.c64-wiki.com/wiki/VIC_bank#Selecting_VIC_banks - lda CIA2_DDRA - ora #$03 - sta CIA2_DDRA - lda CIA2_PRA - ora #$03 - sta CIA2_PRA + ldx #<$033C + stx TAPE1+0 + ldx #>$033C + stx TAPE1+1 // Set screen address pointer ("Compute's Mapping the 64" p238) // This is obvious boiler plate containing no creative input, but to avoid @@ -62,30 +43,41 @@ ramtas_real: ldx #>$0400 stx HIBASE - // Work out RAM size and put in MEMSTR and MEMSIZK - // "Compute's Mapping the 64", p54 - // http://unusedino.de/ec64/technical/project64/mapping_c64.html + // Set BASIC start text pointer + // (remember, that low memory is 0 initialized at this moment) + ldx #>$0800 stx MEMSTR+1 - ldx #$00 - stx MEMSTR+0 - stx MEMSIZK+0 + + // Work out RAM size and put in MEMSIZK // Try to modify $8000, if it fails then RAM ends at $7FFF, else $9FFF + ldx $8000 inx stx $8000 cpx $8000 - bne ramtas_32K_RAM + bne ramtas_32k + + // FALLTROUGH + +ramtas_40k: + + // 40K RAM - restore memory content, set MEMSIZK + + ldy #$A0 +!: + sty MEMSIZK+1 + + // Always restore memory, cartridge might have RAM under ROM + dex stx $8000 - ldx #$A0 - stx MEMSIZK+1 - bne !+ // always non-zero, saves one byte -ramtas_32K_RAM: - dex - stx $8000 // case there is RAM under the ROM - ldx #$80 - stx MEMSIZK+1 -!: rts + +ramtas_32k: + + // 32K RAM - restore memory content, set MEMSIZK + + ldy #$80 + bne !- // branch always diff --git a/c64/kernal/init/fda3.ioinit.s b/c64/kernal/init/fda3.ioinit.s index 0337ec11..59fa824d 100644 --- a/c64/kernal/init/fda3.ioinit.s +++ b/c64/kernal/init/fda3.ioinit.s @@ -11,38 +11,71 @@ IOINIT: - // Set $00/$01 port mode and value + // + // First initialize the CPU port, to make sure we have correct memory map + // + // We want BASIC and KERNAL ROMs mapped, and datasette motor off // (https://www.c64-wiki.com/wiki/Zeropage) // Work around for VICE bug: Writing $00 before $01 results in rubbish in $01 // after. https://sourceforge.net/p/vice-emu/bugs/1057/ - lda #$27 - ldx #$2F - sta CPU_R6510 - stx CPU_D6510 - // Silence the SID chips, depending on the configuration + ldx #$27 + stx CPU_R6510 + ldx #$EF + stx CPU_D6510 // [CM64] page 4 + + // + // Now prevent the CIAs from generating interrupts, who knows what damage they can do + // + + // Disable IRQ generation for both CIAs - see [CM64], page 149 + + ldx #$7F + stx CIA1_ICR // $DC0D + stx CIA2_ICR // $DD0D + + // See discussion here: + // https://www.lemon64.com/forum/viewtopic.php?t=41744&sid=e294c254db2ba671cde643f100aae341 + // It seems that initializing this register to $7F is the best idea - UDTIM key scanning + // also leaves this at $7F + + stx CIA1_PRA // $DC00 + + // + // Now silence the SID chip(s), depending on the configuration - we want them silent ASAP + // + + // First the standard chip (skip if it is covered by whole $D4XX range) + + lda #$00 #if !CONFIG_SID_D4XX - lda SID_SIGVOL - and #$F0 sta SID_SIGVOL #endif // !CONFIG_SID_D4XX + // Silence manually configured 2nd and 3rd SIDs + +#if CONFIG_SID_2ND + sta SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS +#endif // CONFIG_SID_2ND + +#if CONFIG_SID_3RD + sta SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS +#endif // CONFIG_SID_3RD + + // Silence whole D4XX and D5XX ranges (if configured) + #if CONFIG_SID_D4XX || CONFIG_SID_D5XX + ldy #$00 !: #if CONFIG_SID_D4XX - lda SID_SIGVOL, Y - and #$F0 - sta SID_SIGVOL, Y + sta SID_SIGVOL + $000, Y #endif // CONFIG_SID_D4XX #if CONFIG_SID_D5XX - // SIDs under $D5xx - lda SID_SIGVOL + $100, Y - and #$F0 sta SID_SIGVOL + $100, Y #endif // CONFIG_SID_D4XX @@ -51,54 +84,68 @@ IOINIT: adc #$20 tay bne !- + #endif // CONFIG_SID_D4XX || CONFIG_SID_D5XX -#if CONFIG_SID_2ND - lda SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS - and #$F0 - sta SID_SIGVOL - __SID_BASE + CONFIG_SID_2ND_ADDRESS -#endif // CONFIG_SID_2ND + // + // Now continue the CIAs initialization + // -#if CONFIG_SID_3RD - lda SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS - and #$F0 - sta SID_SIGVOL - __SID_BASE + CONFIG_SID_3RD_ADDRESS -#endif // CONFIG_SID_3RD - - // Initialize CIAs - - // XXX: calibrate TOD for both CIA's, see here: https://codebase64.org/doku.php?id=base:efficient_tod_initialisation - - // Enable CIA1 IRQ and ~50Hz timer (https://csdb.dk/forums/?roomid=11&topicid=69037) - - // First disable IRQ generation for both CIA's - lda #$7F - sta CIA2_ICR - sta CIA1_ICR - - // Enable timer interrupt - lda #$81 - sta CIA1_ICR - - // Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts) - lda #$11 - sta CIA1_CRA - lda CIA1_ICR - - // Setup the CIA1 for reading the keyboard - 'POKE 56322, 0' on original ROMs proves this - // is done during initialization, not during the interrupt + // For CIA #1 we need port A as output and port B as input to scan the keyboard ldx #$FF - stx CIA1_DDRA // output - inx // $00 - stx CIA1_DDRB // input + stx CIA1_DDRA // $DC02 + inx + stx CIA1_DDRB // $DC03 + stx CIA2_DDRB // $DD03 // XXX this port is used for RS-232, value here is most likely wrong! - // Value checked on original ROM - stx CIA2_DDRA +#if CONFIG_KEYBOARD_C65 || CONFIG_KEYBOARD_C65_CAPS_LOCK - // Set DDR on CIA2 for IEC bus, VIC-II banking + lda #$02 + sta C65_EXTKEYS_DDR // output for most keys, input for CAPS LOCK bit + +#endif + + // Set DDR on CIA2 for IEC bus, VIC-II banking (see [CM64], $DDOO description on page 193) lda #$3F - sta CIA2_DDRA + sta CIA2_DDRA // $DD02 + + // XXX detect TOD clock, see https://codebase64.org/doku.php?id=base:efficient_tod_initialisation + + // XXX how to initialize these timers??? + // stx CIA1_CRB // $DC0F + // stx CIA2_CRA // $DD0E + // stx CIA2_CRB // $DD0F + + // Set VIC-II bank - at least the 'Operacja Proboszcz' game needs this within IOINIT + // Checked on original ROMs, that it sets bit #2 (RS-232 output) high + + ldx #%00000111 // XXX adapt this to IEC idle state, JMP at the end won't be needed + stx CIA2_PRA // $DD00 + + // + + ldy #<16421 + ldx #>16421 + + sty CIA1_TIMALO // $DC04 + stx CIA1_TIMAHI // $DC05 + + // Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts) + ldx #$11 + stx CIA1_CRA // $DC0E + + // Enable timer interrupt + ldx #$81 + stx CIA1_ICR // $DC0D + +#if CONFIG_IEC // Set IEC bus to its initial idle state jmp iec_set_idle + +#else + + rts + +#endif diff --git a/c64/kernal/fffc.interop b/c64/kernal/init/fffc.interop similarity index 100% rename from c64/kernal/fffc.interop rename to c64/kernal/init/fffc.interop diff --git a/c64/kernal/fffc.vector_reset.s b/c64/kernal/init/fffc.vector_reset.s similarity index 100% rename from c64/kernal/fffc.vector_reset.s rename to c64/kernal/init/fffc.vector_reset.s diff --git a/c64/kernal/init/setup_pal_ntsc.s b/c64/kernal/init/setup_pal_ntsc.s index 0b5ae619..99668527 100644 --- a/c64/kernal/init/setup_pal_ntsc.s +++ b/c64/kernal/init/setup_pal_ntsc.s @@ -32,7 +32,7 @@ setup_pal: // ldx #>16380 // PAL C64 (https://codebase64.org/doku.php?id=base:cpu_clocking), - // is clocked at 0.985248 MHz, so that 1/60s is 16421 CPU cycles + // is clocked at 0.985248 MHz, so that 1/60s is 16421 ($4025) CPU cycles ldy #<16421 ldx #>16421 @@ -43,8 +43,8 @@ setup_pal: setup_pal_ntsc_end: - sty CIA1_TIMALO - stx CIA1_TIMAHI + sty CIA1_TIMALO // $DC04 + stx CIA1_TIMAHI // $DC05 sta TVSFLG @@ -55,7 +55,7 @@ setup_ntsc: // Set timer interval to ~1/60th of a second // NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking), - // is clocked at 1.022727 MHz, so that 1/60s is 17045 CPU cycles + // is clocked at 1.022727 MHz, so that 1/60s is 17045 ($4295) CPU cycles ldy #<17045 ldx #>17045 diff --git a/c64/kernal/interrupts/ea31.default_irq_handler.s b/c64/kernal/interrupts/ea31.default_irq_handler.s index 304fa343..be964c9f 100644 --- a/c64/kernal/interrupts/ea31.default_irq_handler.s +++ b/c64/kernal/interrupts/ea31.default_irq_handler.s @@ -1,10 +1,44 @@ default_irq_handler: +#if CONFIG_RS232_UP9600 + + jsr rs232_count_channels + cpx #$00 + beq !+ + jsr up9600_irq +!: + +#endif // CONFIG_RS232_UP9600 + + jsr cursor_blink jsr JSCNKEY jsr JUDTIM // update jiffy clock + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + // Turn tape motor on/off depending on the button state + // For CAS1 (tape motor interlock) variable description, see Mapping the C64, page 7 + + lda CPU_R6510 + and #$10 + beq !+ // branch if tape button pressed + + jsr tape_motor_off + lda #$00 + sta CAS1 + beq default_irq_handler_end_tape // branch always +!: + lda CAS1 + bne default_irq_handler_end_tape + jsr tape_motor_on + +default_irq_handler_end_tape: + +#endif // CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + // Acknowledge CIA interrupt and return jmp clear_cia1_interrupt_flag_and_return_from_interrupt - diff --git a/c64/kernal/interrupts/fe47.default_nmi_handler.s b/c64/kernal/interrupts/fe47.default_nmi_handler.s index 1fa8acc1..9f877bb5 100644 --- a/c64/kernal/interrupts/fe47.default_nmi_handler.s +++ b/c64/kernal/interrupts/fe47.default_nmi_handler.s @@ -17,9 +17,10 @@ default_nmi_handler: bne !+ jmp (ICART_WARM_START) !: - // According to C64 Wiki, if STOP key is pressed, the routine assumes warm start request + // XXX is it right? how to check that IRQ was caused by RESTORE? + jsr JSTOP bcs !+ jmp return_from_interrupt // no STOP pressed diff --git a/c64/kernal/fffa.interop b/c64/kernal/interrupts/fffa.interop similarity index 100% rename from c64/kernal/fffa.interop rename to c64/kernal/interrupts/fffa.interop diff --git a/c64/kernal/fffa.vector_nmi.s b/c64/kernal/interrupts/fffa.vector_nmi.s similarity index 100% rename from c64/kernal/fffa.vector_nmi.s rename to c64/kernal/interrupts/fffa.vector_nmi.s diff --git a/c64/kernal/fffe.interop b/c64/kernal/interrupts/fffe.interop similarity index 100% rename from c64/kernal/fffe.interop rename to c64/kernal/interrupts/fffe.interop diff --git a/c64/kernal/fffe.vector_irq.s b/c64/kernal/interrupts/fffe.vector_irq.s similarity index 100% rename from c64/kernal/fffe.vector_irq.s rename to c64/kernal/interrupts/fffe.vector_irq.s diff --git a/c64/kernal/interrupts/udtim.s b/c64/kernal/interrupts/udtim.s deleted file mode 100644 index 769ab0e4..00000000 --- a/c64/kernal/interrupts/udtim.s +++ /dev/null @@ -1,73 +0,0 @@ - -// -// Official Kernal routine, described in: -// -// - [RG64] C64 Programmer's Reference Guide - page 303 -// - [CM64] Compute's Mapping the Commodore 64 - pages 27, 232 -// -// CPU registers that has to be preserved (see [RG64]): .Y -// - -UDTIM: - - // Update jiffy clock. The whole day is $4F1A00 jiffies (24 hours * 60 minutes * 60 seconds * 60 jiffies), - // after this time we have to reset the clock. - - inc TIME+0 - bne udtim_update_stkey // done with clock - inc TIME+1 - bne udtim_clock_rollover - inc TIME+2 - - // FALLTROUGH - -udtim_update_stkey: // entry to be used when interrupts are disabled - - // According to [CM64], page 27, another action we have to perform is to copy - // the last row of keyboard to RAM, so that various routines can detect the STOP - // key press. But something as simple as this would have created warm restart - // with M+N+SPACE+RESTORE due to ghosting - so the original ROM has to provide - // some protection here. I do not know what the mechanism there exactly does, - // but I hope the mechanism below will be compatible enough. - - lda #$80 - sta CIA1_PRA // select all the rows except the last one -#if CONFIG_KEYBOARD_C128 - ldx #$00 - stx VIC_XSCAN // connect all the extra C128 keys -#endif - - lda CIA1_PRB // read the keys - eor #$FF - sta STKEY // store reversed state - to filter out anything vulnerable to ghosting - -#if CONFIG_KEYBOARD_C128 - dex // puts $FF - stx VIC_XSCAN // disconnect the extra C128 keys -#endif - lda #$7F - sta CIA1_PRA // select the last row (bit to 0) - - lda CIA1_PRB // read the row - ora STKEY // filter out what might be the reason of ghosting - sta STKEY - - // Leave the CIA configured this way. It would be far better to disconnect - // the keyboard at this point, but certain software (mainly intros) is - // unable to, for example, read the space bar status. - - rts - -udtim_clock_rollover: - - // At this point TIME+0 contains 0 - lda TIME+1 - cmp #$1A - bne udtim_update_stkey // done with clock - lda TIME+2 - cmp #$4F - bne udtim_update_stkey // done with clock - lda #$00 - sta TIME+2 - sta TIME+1 - beq udtim_update_stkey // done with clock - will always jump diff --git a/c64/kernal/iostack/chkinout.s b/c64/kernal/iostack/chkinout.s new file mode 100644 index 00000000..c8d3bda8 --- /dev/null +++ b/c64/kernal/iostack/chkinout.s @@ -0,0 +1,18 @@ + +// +// Common part of CHKIN and CKOUT +// + + +chkinout_device_not_present: + + ply_trash_a + pla + jsr kernalstatus_DEVICE_NOT_FOUND + jmp kernalerror_DEVICE_NOT_FOUND + +chkinout_file_not_open: + + ply_trash_a + pla + jmp kernalerror_FILE_NOT_OPEN diff --git a/c64/kernal/f13e.getin.s b/c64/kernal/iostack/f13e.getin.s similarity index 55% rename from c64/kernal/f13e.getin.s rename to c64/kernal/iostack/f13e.getin.s index be8e3faa..02d68bc3 100644 --- a/c64/kernal/f13e.getin.s +++ b/c64/kernal/iostack/f13e.getin.s @@ -5,12 +5,9 @@ // - [RG64] C64 Programmer's Reference Guide - page 283 // - [CM64] Compute's Mapping the Commodore 64 - page 227/228 // -// CPU registers that has to be preserved (see [RG64]): .X, .Y +// CPU registers that has to be preserved (see [RG64]): for RS-232: .X, .Y // GETIN: - - // XXX this should be a dispatcher for several different devices! - - jmp read_kb_buf + jmp getin_real diff --git a/c64/kernal/f13e.interop b/c64/kernal/iostack/f13e.interop similarity index 100% rename from c64/kernal/f13e.interop rename to c64/kernal/iostack/f13e.interop diff --git a/c64/kernal/iostack/f157.chrin.s b/c64/kernal/iostack/f157.chrin.s new file mode 100644 index 00000000..f4deafb3 --- /dev/null +++ b/c64/kernal/iostack/f157.chrin.s @@ -0,0 +1,48 @@ + +// +// Official Kernal routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 277/278 +// - [CM64] Compute's Mapping the Commodore 64 - page 228 +// +// CPU registers that has to be preserved (see [RG64]): .Y +// + +// Reads a byte of input, unless from keyboard. +// If from keyboard, then it gets a whole line of input, and returns the first char. +// Repeated calls after that read out the successive bytes of the line of input. + + +CHRIN: + + // Determine the device number + lda DFLTN + + // Try $00 - keyboard + beq_far chrin_keyboard + + // XXX Try $03 - screen + // cmp #$03 + // beq_far chrin_screen + +#if HAS_RS232 + + // Try $02 - RS-232 + cmp #$02 + beq_far chrin_rs232 + +#endif // HAS_RS232 + +chrin_getin: // jump entry for GETIN + +#if CONFIG_IEC + + // Try IEC devices + jsr iec_check_devnum_oc + bcc_far chrin_iec + +#endif // CONFIG_IEC + + // Not a supported device + + jmp lvs_device_not_found_error diff --git a/c64/kernal/f157.interop b/c64/kernal/iostack/f157.interop similarity index 100% rename from c64/kernal/f157.interop rename to c64/kernal/iostack/f157.interop diff --git a/c64/kernal/f1ca.chrout.s b/c64/kernal/iostack/f1ca.chrout.s similarity index 80% rename from c64/kernal/f1ca.chrout.s rename to c64/kernal/iostack/f1ca.chrout.s index 6e51ea2b..5c123847 100644 --- a/c64/kernal/f1ca.chrout.s +++ b/c64/kernal/iostack/f1ca.chrout.s @@ -6,6 +6,7 @@ // - [CM64] Compute's Mapping the Commodore 64 - page 228 // // CPU registers that has to be preserved (see [RG64]): .Y +// Additionally we have to preserve .X for out CHRIN and implementation // CHROUT: @@ -26,17 +27,17 @@ CHROUT: lda DFLTO cmp #$03 // screen - bne !+ - jmp chrout_screen -!: - jsr iec_check_devnum - bcs chrout_done_unknown_device // not a supported device + beq_far chrout_screen -chrout_iec: +#if HAS_RS232 + cmp #$02 + beq_far chrout_rs232 +#endif - lda SCHAR - jsr JCIOUT - bcc chrout_done_success +#if CONFIG_IEC + jsr iec_check_devnum_oc + bcc_far chrout_iec +#endif // FALLTROUGH diff --git a/c64/kernal/f1ca.interop b/c64/kernal/iostack/f1ca.interop similarity index 100% rename from c64/kernal/f1ca.interop rename to c64/kernal/iostack/f1ca.interop diff --git a/c64/kernal/iostack/f20e.chkin.s b/c64/kernal/iostack/f20e.chkin.s new file mode 100644 index 00000000..bd86226c --- /dev/null +++ b/c64/kernal/iostack/f20e.chkin.s @@ -0,0 +1,69 @@ + +// +// Official Kernal routines, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 275 +// - [CM64] Compute's Mapping the Commodore 64 - page 229 +// +// CPU registers that has to be preserved (see [RG64]): .Y, .A (see [CM64], page 213) +// + + +CHKIN: + + // Store registers for preservation + pha + phy_trash_a + + // Reset status + jsr kernalstatus_reset + + // First retrieve the FAT/LAT/SAT table index (and check if file is open) + + txa + jsr find_fls + bcs_far chkinout_file_not_open + + // Now we have table index in Y + + lda FAT,Y + + // Handle all the devices + + beq chkin_set_device // 0 - keyboard + + // Tape not supported here + +#if HAS_RS232 + + cmp #$02 + beq_far chkin_rs232 + +#endif // HAS_RS232 + +#if CONFIG_IEC + + jsr iec_check_devnum_oc + bcc_far chkin_iec + +#endif // CONFIG_IEC + + cmp #$03 // screen - only legal one left + bne_far chkinout_device_not_present + +chkin_set_device: + lda FAT,Y + sta DFLTN + + // FALLTROUGH + +chkinout_end: + ply_trash_a + pla + clc // indicate success + rts + +chkin_file_not_input: + ply_trash_a + pla + jmp kernalerror_FILE_NOT_INPUT diff --git a/c64/kernal/f20e.interop b/c64/kernal/iostack/f20e.interop similarity index 100% rename from c64/kernal/f20e.interop rename to c64/kernal/iostack/f20e.interop diff --git a/c64/kernal/iostack/f250.ckout.s b/c64/kernal/iostack/f250.ckout.s new file mode 100644 index 00000000..49a4d6a7 --- /dev/null +++ b/c64/kernal/iostack/f250.ckout.s @@ -0,0 +1,76 @@ + +// +// Official Kernal routines, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 276 +// - [CM64] Compute's Mapping the Commodore 64 - page 229 +// +// CPU registers that has to be preserved (see [RG64]): .Y, .A (see [CM64], page 213) +// + + +CKOUT: + + // Store registers for preservation + pha + phy_trash_a + + // Reset status + jsr kernalstatus_reset + + // First retrieve the FAT/LAT/SAT table index (and check if file is open) + + txa + jsr find_fls + bcs_far chkinout_file_not_open + + // Now we have table index in Y + + lda FAT,Y + + // Handle all the devices + + beq ckout_file_not_output // 0 - keyboard + + // Tape not supported here + +#if HAS_RS232 + + cmp #$02 + beq_far ckout_rs232 + +#endif // HAS_RS232 + +#if CONFIG_IEC + + jsr iec_check_devnum_oc + bcc_far ckout_iec + +#endif // CONFIG_IEC + + cmp #$03 // screen - only legal one left + bne_far chkinout_device_not_present + +ckout_set_device: + lda FAT,Y + sta DFLTO + jmp chkinout_end + +ckout_file_not_output: + ply_trash_a + pla + jmp kernalerror_FILE_NOT_OUTPUT + + + + + + + + + + + + + + diff --git a/c64/kernal/f250.interop b/c64/kernal/iostack/f250.interop similarity index 100% rename from c64/kernal/f250.interop rename to c64/kernal/iostack/f250.interop diff --git a/c64/kernal/iostack/f291.close.s b/c64/kernal/iostack/f291.close.s new file mode 100644 index 00000000..c4930447 --- /dev/null +++ b/c64/kernal/iostack/f291.close.s @@ -0,0 +1,57 @@ + +// +// Official Kernal routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 281/282 +// - [CM64] Compute's Mapping the Commodore 64 - page 229/230 +// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command) +// +// CPU registers that has to be preserved (see [RG64]): none +// + +CLOSE: + + // Find the LAT / SAT / FAT entry which LAT corresponds to A + + jsr find_fls + bcs close_end // XXX can we report error in IOSTATUS here? + + // We have the entry index in .Y + + lda FAT, y + + // Perform device-specific actions + +#if HAS_RS232 + cmp #$02 + beq_far close_rs232 +#endif + +#if CONFIG_IEC + jsr iec_check_devnum_oc + bcc_far close_iec +#endif + + // FALLTROUGH + +close_remove_from_table: + + // Remove channel from the table + iny + cpy #$0A + bpl !+ + lda LAT, y + sta LAT-1, y + lda FAT, y + sta FAT-1, y + lda SAT, y + sta SAT-1, y + jmp close_remove_from_table +!: + // Decrement the list size variable + dec LDTND + + clc // report success - not sure if original CLOSE does this, but it's nevertheless a good practice + +close_end: + rts diff --git a/c64/kernal/f291.interop b/c64/kernal/iostack/f291.interop similarity index 100% rename from c64/kernal/f291.interop rename to c64/kernal/iostack/f291.interop diff --git a/c64/kernal/clrchn_real.s b/c64/kernal/iostack/f333.clrchn.s similarity index 60% rename from c64/kernal/clrchn_real.s rename to c64/kernal/iostack/f333.clrchn.s index 6c97cc4d..ab94909f 100644 --- a/c64/kernal/clrchn_real.s +++ b/c64/kernal/iostack/f333.clrchn.s @@ -9,26 +9,22 @@ // -clrchn_real: +CLRCHN: + +#if CONFIG_IEC + jsr clrchn_iec +#else + nop // just to prevent double label +#endif + + // FALLTROUGH - // Handle IEC input device - lda DFLTN - jsr iec_check_devnum - bcs !+ - // Previous device was IEC one - send UNTALK first - jsr UNTLK -!: - // Restore output device to default - lda DFLTO - jsr iec_check_devnum - bcs !+ - // Handle IEC output device - jsr UNLSN -!: clrchn_reset: // entry needed by setup_vicii + // Set input device number to keyboard lda #$00 sta DFLTN + // Set output device number to screen lda #$03 sta DFLTO diff --git a/c64/kernal/f333.interop b/c64/kernal/iostack/f333.interop similarity index 100% rename from c64/kernal/f333.interop rename to c64/kernal/iostack/f333.interop diff --git a/c64/kernal/f34a.interop b/c64/kernal/iostack/f34a.interop similarity index 100% rename from c64/kernal/f34a.interop rename to c64/kernal/iostack/f34a.interop diff --git a/c64/kernal/f34a.open.s b/c64/kernal/iostack/f34a.open.s similarity index 64% rename from c64/kernal/f34a.open.s rename to c64/kernal/iostack/f34a.open.s index 02ce3ac9..3dc0e134 100644 --- a/c64/kernal/f34a.open.s +++ b/c64/kernal/iostack/f34a.open.s @@ -23,6 +23,7 @@ OPEN: cmp LA bne open_not_yet_open jmp kernalerror_FILE_ALREADY_OPEN + open_not_yet_open: cpy #$00 jmp !- @@ -53,40 +54,25 @@ open_has_space: iny sty LDTND - // Check for command to send - lda FNLEN - beq open_done_success - - // Check for IEC device lda FA - jsr iec_check_devnum - bcc open_iec +#if HAS_RS232 + + cmp #$02 + beq_far open_rs232 + +#endif + +#if CONFIG_IEC + + jsr iec_check_devnum_oc + bcc_far open_iec + +#endif + // FALLTROUGH + open_done_success: clc rts - -open_iec: - - // We have a command to send to IEC device - jsr LISTEN - bcc !+ - jmp kernalerror_DEVICE_NOT_FOUND -!: - lda SA - jsr iec_cmd_open - bcc !+ - jmp kernalerror_DEVICE_NOT_FOUND -!: - -#if CONFIG_MEMORY_MODEL_60K - // We need our helpers to get to filenames under ROMs or IO area - jsr install_ram_routines -#endif - - // Send command ('file name') - jsr lvs_send_file_name - - jmp open_done_success diff --git a/c64/kernal/f49e.interop b/c64/kernal/iostack/f49e.interop similarity index 100% rename from c64/kernal/f49e.interop rename to c64/kernal/iostack/f49e.interop diff --git a/c64/kernal/iostack/f49e.load_prep.s b/c64/kernal/iostack/f49e.load_prep.s new file mode 100644 index 00000000..cc045026 --- /dev/null +++ b/c64/kernal/iostack/f49e.load_prep.s @@ -0,0 +1,23 @@ + +// +// LOAD preparation routine +// + +// +// Input (according to http://sta.c64.org/cbm64krnfunc.html) +// .A - 0 for load, non-0 for verify +// .X and .Y - load address (if secondary address is 0) +// + +// +// Note: Although the vector at $330 points to $F4A5, the Kernal jump table points to $F49E +// (see also Mapping the C64, page 76). By experimenting I have discovered that $F49E performs +// indirect jump via ($0330) vector, after setting MEMUSS. +// + + +LOAD_PREP: + + sty MEMUSS+1 + stx MEMUSS+0 + jmp (ILOAD) diff --git a/c64/kernal/f4a5.interop b/c64/kernal/iostack/f4a5.interop similarity index 100% rename from c64/kernal/f4a5.interop rename to c64/kernal/iostack/f4a5.interop diff --git a/c64/kernal/iostack/f4a5.load.s b/c64/kernal/iostack/f4a5.load.s new file mode 100644 index 00000000..2f173766 --- /dev/null +++ b/c64/kernal/iostack/f4a5.load.s @@ -0,0 +1,57 @@ +// +// Official Kernal routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 286 +// - [CM64] Compute's Mapping the Commodore 64 - page 231 +// - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf +// +// CPU registers that has to be preserved (see [RG64]): none +// + + + // Expects that SETLFS and SETNAM are called before hand. + // $YYXX = load address. + // (ignored if SETLFS channel = 1, i.e., like ,8,1) + // If A=1 then VERIFY instead of LOAD. + // On exit, $YYXX is the highest address into which data + // will have been placed. + + +LOAD: + + // Are we loading or verifying? + sta VERCKK + + // Store start address of LOAD + lda MEMUSS+0 + sta STAL+0 + lda MEMUSS+1 + sty STAL+1 + + // Reset status + jsr kernalstatus_reset + +#if CONFIG_MEMORY_MODEL_60K + // We need our helpers to get to filenames under ROMs or IO area + jsr install_ram_routines +#endif + + // Check whether we support the requested device + lda FA + +#if CONFIG_TAPE_NORMAL + cmp #$01 + beq_far load_tape_normal +#endif + +#if CONFIG_TAPE_TURBO + cmp #$07 + beq_far load_tape_turbo +#endif + +#if CONFIG_IEC + jsr iec_check_devnum_lvs + bcc_far load_iec +#endif + + jmp lvs_illegal_device_number diff --git a/c64/kernal/f5dd.interop b/c64/kernal/iostack/f5dd.interop similarity index 100% rename from c64/kernal/f5dd.interop rename to c64/kernal/iostack/f5dd.interop diff --git a/c64/kernal/iostack/f5dd.save_prep.s b/c64/kernal/iostack/f5dd.save_prep.s new file mode 100644 index 00000000..d7cf3f86 --- /dev/null +++ b/c64/kernal/iostack/f5dd.save_prep.s @@ -0,0 +1,29 @@ + +// +// SAVE preparation routine +// + +// +// Input (according to http://sta.c64.org/cbm64krnfunc.html) +// .A - address of zero page register holding start address of memory area to save +// .X and .Y - end address of memory area plus 1 +// + +// +// Note: Experimenting can easily confirm that SAVE preparation routine does similar +// actions as LOAD preparation routine. +// + +SAVE_PREP: + + sty EAL+1 + stx EAL+0 + + tax + + lda $01, x + sta STAL+1 + lda $00, x + sta STAL+0 + + jmp (ISAVE) diff --git a/c64/kernal/f5ed.interop b/c64/kernal/iostack/f5ed.interop similarity index 100% rename from c64/kernal/f5ed.interop rename to c64/kernal/iostack/f5ed.interop diff --git a/c64/kernal/f5ed.save.s b/c64/kernal/iostack/f5ed.save.s similarity index 50% rename from c64/kernal/f5ed.save.s rename to c64/kernal/iostack/f5ed.save.s index 79ea33d6..d8d053bf 100644 --- a/c64/kernal/f5ed.save.s +++ b/c64/kernal/iostack/f5ed.save.s @@ -10,4 +10,21 @@ // SAVE: - STUB_IMPLEMENTATION() + + // Reset status + jsr kernalstatus_reset + +#if CONFIG_MEMORY_MODEL_60K + // We need our helpers to get to filenames under ROMs or IO area + jsr install_ram_routines +#endif + + // Check whether we support the requested device + lda FA + +#if CONFIG_IEC + jsr iec_check_devnum_lvs + bcc_far save_iec +#endif + + jmp lvs_illegal_device_number diff --git a/c64/kernal/f6ed.interop b/c64/kernal/iostack/f6ed.interop similarity index 100% rename from c64/kernal/f6ed.interop rename to c64/kernal/iostack/f6ed.interop diff --git a/c64/kernal/iostack/findfls.s b/c64/kernal/iostack/findfls.s index 874fad51..9da38026 100644 --- a/c64/kernal/iostack/findfls.s +++ b/c64/kernal/iostack/findfls.s @@ -7,7 +7,6 @@ find_fls: ldy LDTND - beq find_fls_not_found // table empty !: dey bmi find_fls_not_found // no more entries diff --git a/c64/kernal/iostack/getin_real.s b/c64/kernal/iostack/getin_real.s new file mode 100644 index 00000000..681e2a17 --- /dev/null +++ b/c64/kernal/iostack/getin_real.s @@ -0,0 +1,28 @@ + +// +// Official Kernal routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 283 +// - [CM64] Compute's Mapping the Commodore 64 - page 227/228 +// +// CPU registers that has to be preserved (see [RG64]): for RS-232: .X, .Y +// + + +getin_real: + + // Determine the device number + lda DFLTN + + // Try $00 - keyboard + beq_far getin_keyboard + +#if HAS_RS232 + + // Try $02 - RS-232 + cmp #$02 + beq_far getin_rs232 + +#endif // HAS_RS232 + + jmp chrin_getin diff --git a/c64/kernal/iostack/lvs_helpers.s b/c64/kernal/iostack/load_save_common.s similarity index 58% rename from c64/kernal/iostack/lvs_helpers.s rename to c64/kernal/iostack/load_save_common.s index 948de153..8f43b96b 100644 --- a/c64/kernal/iostack/lvs_helpers.s +++ b/c64/kernal/iostack/load_save_common.s @@ -1,80 +1,122 @@ // -// Helper functions for various LOAD/VERIVY/SAVE routine variants (IEC / U64 / etc.) +// Helper functions for various LOAD/VERIFY/SAVE routine variants (IEC / U64 / etc.) // -lvs_send_file_name: - ldy #0 -lvs_send_file_name_loop: - cpy FNLEN - beq lvs_send_file_name_done - -#if CONFIG_MEMORY_MODEL_60K - ldx # 0) + { + .byte CODE + } +} + +.macro PROGRAMMABLE_KEY_STRING(STR) +{ + .if (STR.size() > 0) + { + .text STR + .byte $00 + } +} + +.macro PROGRAMMABLE_KEY_OFFSET(STR, LABEL) +{ + .if (STR.size() > 0) + { + .byte LABEL - programmable_keys_strings + } +} + + +programmable_keys_codes: + + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_RUN, KEY_RUN) + + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F1, KEY_F1) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F2, KEY_F2) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F3, KEY_F3) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F4, KEY_F4) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F5, KEY_F5) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F6, KEY_F6) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F7, KEY_F7) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F8, KEY_F8) + +#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_HELP, KEY_HELP) +#endif + +#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65 + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F9, KEY_F9) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F10, KEY_F10) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F11, KEY_F11) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F12, KEY_F12) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F13, KEY_F13) + PROGRAMMABLE_KEY_CODE(CONFIG_KEYCMD_F14, KEY_F14) +#endif + +__programmable_keys_codes_end: + + +programmable_keys_strings: + +__str_offset_RUN: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_RUN) + +__str_offset_F1: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F1) +__str_offset_F2: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F2) +__str_offset_F3: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F3) +__str_offset_F4: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F4) +__str_offset_F5: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F5) +__str_offset_F6: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F6) +__str_offset_F7: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F7) +__str_offset_F8: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F8) + +#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65) +__str_offset_HELP: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_HELP) +#endif + +#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65 +__str_offset_F9: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F9) +__str_offset_F10: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F10) +__str_offset_F11: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F11) +__str_offset_F12: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F12) +__str_offset_F13: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F13) +__str_offset_F14: PROGRAMMABLE_KEY_STRING(CONFIG_KEYCMD_F14) +#endif + +__programmable_keys_strings_end: +{ + .var offset = __programmable_keys_strings_end - programmable_keys_strings + .if (offset >= 255) .error "Programmable keys took too much space" +} + + +programmable_keys_offsets: + + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_RUN, __str_offset_RUN) + + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F1, __str_offset_F1) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F2, __str_offset_F2) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F3, __str_offset_F3) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F4, __str_offset_F4) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F5, __str_offset_F5) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F6, __str_offset_F6) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F7, __str_offset_F7) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F8, __str_offset_F8) + +#if !CONFIG_LEGACY_SCNKEY && (CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_HELP, __str_offset_HELP) +#endif + +#if !CONFIG_LEGACY_SCNKEY && CONFIG_KEYBOARD_C65 + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F9, __str_offset_F9) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F10, __str_offset_F10) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F11, __str_offset_F11) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F12, __str_offset_F12) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F13, __str_offset_F13) + PROGRAMMABLE_KEY_OFFSET(CONFIG_KEYCMD_F14, __str_offset_F14) +#endif + + +#endif // CONFIG_PROGRAMMABLE_KEYS diff --git a/c64/kernal/keyboard/scnkey.s b/c64/kernal/keyboard/scnkey.s index b1ed3a5f..0aadfd93 100644 --- a/c64/kernal/keyboard/scnkey.s +++ b/c64/kernal/keyboard/scnkey.s @@ -30,6 +30,34 @@ SCNKEY: +#if CONFIG_KEYBOARD_C65 && CONFIG_MB_MEGA_65 + + // Idea by Paul Gardner-Stephen + + lda VIC_XPOS // check raster X position + cmp VIC_XPOS // if it changes, we are on a MEGA65 with VIC-IV registers already visible + bne scnkey_viciv_mode + + // We are on machine that is not in VIC-IV IO mode, so try enabling it (harmless on C64/C65) + // If we are on a C65 (or MEGA65 with C65 VIC-III IO mode selected), the above test would + // have failed, but we could already be in C65 IO mode. In that case, this will disable C65 IO + // mode when done. This is not ideal, but as MEGA65s start C65 mode with VIC-IV IO mode + // selected anyway, it should not be a big problem in practice. + + lda #$A5 + sta VIC_KEY + lda #$96 + sta VIC_KEY + + jsr scnkey_viciv_mode + + sta VIC_KEY + rts + +scnkey_viciv_mode: + +#endif + // Prepare for SHFLAG update lda SHFLAG @@ -76,6 +104,23 @@ SCNKEY: stx VIC_XSCAN // disconnect C128 keys if no C128 keyboard is supported #endif +#endif + +#if CONFIG_KEYBOARD_C65_CAPS_LOCK + + lda C65_EXTKEYS_PR + and #$01 + bne !+ // branch if no CAPS LOCK + + lda #KEY_CAPS_LOCK + sta SHFLAG +!: + +#if !CONFIG_KEYBOARD_C65 + ldx #$FF + stx C65_EXTKEYS_PR // disconnect C128 keys if no C128 keyboard is supported +#endif + #endif ldy #(__kb_matrix_bucky_confmask_end - kb_matrix_bucky_confmask - 1) @@ -85,6 +130,10 @@ scnkey_bucky_loop: #if CONFIG_KEYBOARD_C128 lda kb_matrix_bucky_confmask_c128, y sta VIC_XSCAN +#endif +#if CONFIG_KEYBOARD_C65 + lda kb_matrix_bucky_confmask_c65, y + sta C65_EXTKEYS_PR #endif lda kb_matrix_bucky_testmask, y and CIA1_PRB @@ -123,6 +172,9 @@ scnkey_bucky_loop: stx CIA1_PRA // connect all the rows #if CONFIG_KEYBOARD_C128 stx VIC_XSCAN +#endif +#if CONFIG_KEYBOARD_C65 + stx C65_EXTKEYS_PR #endif dex // puts $FF cpx CIA1_PRB @@ -153,6 +205,9 @@ scnkey_bucky_loop: ldy #$FF // offset in key matrix table, $FF for not found yet #if CONFIG_KEYBOARD_C128 jsr scnkey_128 +#endif +#if CONFIG_KEYBOARD_C65 + jsr scnkey_65 #endif ldx #$07 scnkey_matrix_loop: @@ -280,38 +335,46 @@ scnkey_output_key: // Retrieve the PETSCII code -#if CONFIG_KEYBOARD_C128 +#if CONFIG_KEYBOARD_C128 || CONFIG_KEYBOARD_C65 cpy #$40 bcc !+ +#if CONFIG_KEYBOARD_C128 lda kb_matrix_128 - $41, y // retrieve key code from C128 extended matrix +#elif CONFIG_KEYBOARD_C65 + + // Select key matrix (normal or shifted) for extended C65 keys + + lda SHFLAG + and #%00000111 // KEY_FLAG_SHIFT + KEY_FLAG_VENDOR + KEY_FLAG_CTRL + beq scnkey_output_65_no_shift + cmp #KEY_FLAG_SHIFT + // XXX how to behave on VENDOR/CTRL key? Harmonize this with claasic keys behavior + bne scnkey_no_keys // no scanning for this bucky key combination + + lda kb_matrix_65_shifted - $41, y + jmp scnkey_got_petscii + +scnkey_output_65_no_shift: + + lda kb_matrix_65 - $41, y + +#endif jmp scnkey_got_petscii !: lda (KEYTAB), y // retrieve key code from standard matrix - // XXX this will be needed for extended screen editor +#endif // CONFIG_KEYBOARD_C128 or CONFIG_KEYBOARD_C65 - // cmp KEY_TAB_FW // special handling for SHIFT+TAB - // bne scnkey_got_petscii // XXX or to scnkey_handle_caps_lock - // lda SHFLAG // special handling for SHIFT+TAB - // and #KEY_FLAG_SHIFT - // bne !+ - // lda KEY_TAB_FW - // bne scnkey_got_petscii // branch alWAYS - // !: - // lda KEY_TAB_BW // bne scnkey_got_petscii if CAPS LOCK is handled - -#endif // CONFIG_KEYBOARD_C128_CAPS_LOCK - -#if CONFIG_KEYBOARD_C128_CAPS_LOCK +#if CONFIG_KEYBOARD_C128_CAPS_LOCK || CONFIG_KEYBOARD_C65_CAPS_LOCK // Check if we need special handling for a CAPS LOCK key // This is shorter than a separate set of tables scnkey_handle_caps_lock: -#if !CONFIG_KEYBOARD_C128 +#if !CONFIG_KEYBOARD_C128 && !CONFIG_KEYBOARD_C65 lda (KEYTAB), y #endif tax @@ -332,9 +395,9 @@ scnkey_handle_caps_lock: !: txa -#endif // CONFIG_KEYBOARD_C128_CAPS_LOCK +#endif // CONFIG_KEYBOARD_C128_CAPS_LOCK or CONFIG_KEYBOARD_C65_CAPS_LOCK -#if !CONFIG_KEYBOARD_C128 && !CONFIG_KEYBOARD_C128_CAPS_LOCK +#if !CONFIG_KEYBOARD_C128 && !CONFIG_KEYBOARD_C128_CAPS_LOCK && !CONFIG_KEYBOARD_C65 && !CONFIG_KEYBOARD_C65_CAPS_LOCK lda (KEYTAB), y @@ -344,6 +407,22 @@ scnkey_handle_caps_lock: scnkey_got_petscii: +#if CONFIG_KEYBOARD_C128 && CONFIG_EDIT_TABULATORS + + // Special handling for SHIFT+TAB; it is easier than creating new matrix + + tax + cmp #KEY_TAB_FW + bne !+ + lda SHFLAG + and #KEY_FLAG_SHIFT + beq !+ + ldx #KEY_TAB_BW +!: + txa + +#endif // CONFIG_KEYBOARD_C128 and CONFIG_EDIT_TABULATORS + beq scnkey_no_keys // branch if we have no PETSCII code for this key ldy NDX sta KEYD, y diff --git a/c64/kernal/keyboard/scnkey_128.s b/c64/kernal/keyboard/scnkey_128.s index 7fc8ddf5..dbbeecdf 100644 --- a/c64/kernal/keyboard/scnkey_128.s +++ b/c64/kernal/keyboard/scnkey_128.s @@ -48,15 +48,11 @@ scnkey_matrix_128_loop_next: dex bpl scnkey_matrix_128_loop - // Scanning the C128 keyboard part complete - check if we got a key - - cpy #$FF - beq scnkey_128_done - - // Continue with C64 keyboard scanning + // Scanning the C128 keyboard part complete scnkey_128_done: + stx VIC_XSCAN // $FF, disconnects C128 keys rts diff --git a/c64/kernal/keyboard/scnkey_65.s b/c64/kernal/keyboard/scnkey_65.s new file mode 100644 index 00000000..5d3f5b58 --- /dev/null +++ b/c64/kernal/keyboard/scnkey_65.s @@ -0,0 +1,65 @@ + +// +// Keyboard scanning routine extension for C65 keyboards +// +// - [CM128] Compute's Mapping the Commodore 128 - pages 212 (SHFLAG) +// - https://github.com/MEGA65/c65-specifications/blob/master/c65manualupdated.txt (matrix) +// + + +#if CONFIG_KEYBOARD_C65 && !CONFIG_LEGACY_SCNKEY + + +// Inlining this within SCNKEY would both overcomplicate the implementation +// and disrupt a lot of branches (they would cross the 127 bytes distance limit) + +// .Y is now $FF - try to put there a key code from extended keyboard + +scnkey_65: + + sty CIA1_PRA // disconnect classic keys + + lda #$00 + sta C65_EXTKEYS_PR // connect C65 keys + + lda #%00000101 // filter out bucky keys: ALT, NO_SCRL + ora CIA1_PRB + + cmp #$FF + beq scnkey_65_done // skip if no key pressed from this row + + // At least one key is pressed - decode it + ldy #$07 +scnkey_matrix_65_loop: + cmp kb_matrix_row_keys, y + bne !+ // not this particular key + tya // now .A contains key offset within a row + clc + adc kb_matrix_row_offsets, x // now .A contains key offset from the matrix start + adc #$41 // now .A contains offset after the standard matrix + tay + jmp scnkey_65_done +!: + dey + bpl scnkey_matrix_65_loop + + // FALLTROUGH, multiple keys must have been pressed + +scnkey_65_no_keys: + + pla // get rid of return address from the stack + pla + + jmp scnkey_no_keys // pass controll to original routine + + +scnkey_65_done: + + ldx #$FF + stx C65_EXTKEYS_PR // connect C65 keys + + rts + + + +#endif // CONFIG_KEYBOARD_C65 and no CONFIG_LEGACY_SCNKEY diff --git a/c64/kernal/keyboard/udtim_keyboard.s b/c64/kernal/keyboard/udtim_keyboard.s new file mode 100644 index 00000000..d35f86f6 --- /dev/null +++ b/c64/kernal/keyboard/udtim_keyboard.s @@ -0,0 +1,50 @@ + +// +// Keyboard part of the UDTIM routine, has to preserve .Y +// + + +udtim_keyboard: + + // According to [CM64], page 27, the action we have to perform is to copy + // the last row of keyboard to RAM, so that various routines can detect the STOP + // key press. But something as simple as this would have created warm restart + // with M+N+SPACE+RESTORE due to ghosting - so the original ROM has to provide + // some protection here. I do not know what the mechanism there exactly does, + // but I hope the mechanism below will be compatible enough. + + lda #$80 + sta CIA1_PRA // select all the rows except the last one +#if CONFIG_KEYBOARD_C128 + ldx #$00 + stx VIC_XSCAN // connect all the extra C128 keys +#endif +#if CONFIG_KEYBOARD_C65 + ldx #$00 + stx C65_EXTKEYS_PR // connect all the extra C65 keys +#endif + + lda CIA1_PRB // read the keys + eor #$FF + sta STKEY // store reversed state - to filter out anything vulnerable to ghosting + +#if CONFIG_KEYBOARD_C128 + dex // puts $FF + stx VIC_XSCAN // disconnect the extra C128 keys +#endif +#if CONFIG_KEYBOARD_C65 + dex // puts $FF + stx C65_EXTKEYS_PR // disconnect the extra C65 keys +#endif + lda #$7F + sta CIA1_PRA // select the last row (bit to 0) + + lda CIA1_PRB // read the row + ora STKEY // filter out what might be the reason of ghosting + sta STKEY + + // Leave the CIA configured this way. It would be far better to disconnect + // the keyboard at this point, but certain software (mainly intros) is + // unable to, for example, read the space bar status. + + rts diff --git a/c64/kernal/fd15.interop b/c64/kernal/memory/fd15.interop similarity index 100% rename from c64/kernal/fd15.interop rename to c64/kernal/memory/fd15.interop diff --git a/c64/kernal/fd15.restor.s b/c64/kernal/memory/fd15.restor.s similarity index 100% rename from c64/kernal/fd15.restor.s rename to c64/kernal/memory/fd15.restor.s diff --git a/c64/kernal/fe25.interop b/c64/kernal/memory/fe25.interop similarity index 100% rename from c64/kernal/fe25.interop rename to c64/kernal/memory/fe25.interop diff --git a/c64/kernal/fe25.memtop.s b/c64/kernal/memory/fe25.memtop.s similarity index 100% rename from c64/kernal/fe25.memtop.s rename to c64/kernal/memory/fe25.memtop.s diff --git a/c64/kernal/membot.s b/c64/kernal/memory/membot.s similarity index 100% rename from c64/kernal/membot.s rename to c64/kernal/memory/membot.s diff --git a/c64/kernal/under_rom_routines.s b/c64/kernal/memory/under_rom_routines.s similarity index 100% rename from c64/kernal/under_rom_routines.s rename to c64/kernal/memory/under_rom_routines.s diff --git a/c64/kernal/vector_real.s b/c64/kernal/memory/vector_real.s similarity index 78% rename from c64/kernal/vector_real.s rename to c64/kernal/memory/vector_real.s index b3540f9c..5b3e4eff 100644 --- a/c64/kernal/vector_real.s +++ b/c64/kernal/memory/vector_real.s @@ -1,4 +1,5 @@ + vector_real: // Use MEMUSS as temporary storage location - checked on real C64 that this is the @@ -8,11 +9,11 @@ vector_real: // According to 'Compute's Mapping the Commodore 64' page 237, // the CBM implementation does not disable IRQs - yet, the // 'C64 Programmers Reference Guide' does not contain such - // warning and does not mention any preparations needed, so... - // better safe than sorry, disable the IRQ for the duration - // of vector manipulation - php - cli + // warning and does not mention any preparations needed. + + // Initial idea was to do php, cli, ..., plp to make the routine safer, + // but it seems it might cause problem with initialization on XEMU emulator + // XXX find out, why // Prepare the user data pointer - strange order to reduce risk // of potential similarity to the original routine @@ -38,6 +39,4 @@ vector_end_loop: dey bpl vector_restore - // Restore status register (IRQ) before return - plp rts diff --git a/c64/kernal/print/print_features.s b/c64/kernal/print/print_features.s new file mode 100644 index 00000000..8c958a53 --- /dev/null +++ b/c64/kernal/print/print_features.s @@ -0,0 +1,14 @@ + +// +// Print configured features on startup banner +// + +#if CONFIG_SHOW_FEATURES + +print_features: + + ldx #__MSG_KERNAL_FEATURES +!: + jmp print_kernal_message + +#endif // CONFIG_SHOW_FEATURES diff --git a/c64/kernal/ff80.interop b/c64/kernal/rom_revision/ff80.interop similarity index 100% rename from c64/kernal/ff80.interop rename to c64/kernal/rom_revision/ff80.interop diff --git a/c64/kernal/ff80.kernal_revision.s b/c64/kernal/rom_revision/ff80.kernal_revision.s similarity index 100% rename from c64/kernal/ff80.kernal_revision.s rename to c64/kernal/rom_revision/ff80.kernal_revision.s diff --git a/c64/kernal/rs232/chkin_rs232_up2400.s b/c64/kernal/rs232/chkin_rs232_up2400.s new file mode 100644 index 00000000..0fb045b5 --- /dev/null +++ b/c64/kernal/rs232/chkin_rs232_up2400.s @@ -0,0 +1,14 @@ + +// +// RS-232 part of the CHKIN routine +// + + +#if CONFIG_RS232_UP2400 + + +chkin_rs232: + STUB_IMPLEMENTATION() // XXX provide implementation for both UP2400 and UP9600 + + +#endif // CONFIG_RS232_UP2400 diff --git a/c64/kernal/rs232/chkin_rs232_up9600.s b/c64/kernal/rs232/chkin_rs232_up9600.s new file mode 100644 index 00000000..40d4e2ac --- /dev/null +++ b/c64/kernal/rs232/chkin_rs232_up9600.s @@ -0,0 +1,48 @@ + +// +// RS-232 part of the CHKIN routine +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +// XXX get rid of the ENABLE/DISABLE mechanism + + +chkin_rs232: + + pha + lda XXX_UPFLAG + bne !+ + pla + jmp $F20E // XXX + +!: + pla + jsr $F30F // XXX + beq !+ + jmp $F701 // XXX + +!: + jsr $F31F // XXX + lda FA + cmp #$02 + beq !+ + cmp #$04 + bcc chkin_rs232_nochkin + jsr XXX_DISABLE + jmp chkin_rs232_nochkin +!: + sta $99 + jsr XXX_ENABLE + clc + rts + +chkin_rs232_nochkin + jmp $F219 // XXX + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/chrin_rs232_up2400.s b/c64/kernal/rs232/chrin_rs232_up2400.s new file mode 100644 index 00000000..252cf2db --- /dev/null +++ b/c64/kernal/rs232/chrin_rs232_up2400.s @@ -0,0 +1,14 @@ + +// +// RS-232 part of the CHRIN routine +// + + +#if CONFIG_RS232_UP2400 + + +chrin_rs232: + STUB_IMPLEMENTATION() // XXX provide implementation for both UP2400 and UP9600 + + +#endif // CONFIG_RS232_UP2400 diff --git a/c64/kernal/rs232/chrin_rs232_up9600.s b/c64/kernal/rs232/chrin_rs232_up9600.s new file mode 100644 index 00000000..0945111d --- /dev/null +++ b/c64/kernal/rs232/chrin_rs232_up9600.s @@ -0,0 +1,43 @@ + +// +// RS-232 part of the CHRIN routine +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +chrin_rs232: + + phy_trash_a + phx_trash_a + + lda #$00 + sta XXX_SAVBYTE + sta RSSTAT + jsr up9600_rsin + bcc !+ + plx_trash_a + ply_trash_a + + lda #$08 // XXX don't we have some routine for this? + sta RSSTAT + lda #$00 + clc + rts +!: + sta XXX_SAVBYTE + +XXX_DOGET4: + + plx_trash_a + ply_trash_a + + lda XXX_SAVBYTE + clc + rts + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/chrout_rs232.s b/c64/kernal/rs232/chrout_rs232.s new file mode 100644 index 00000000..9c3af02f --- /dev/null +++ b/c64/kernal/rs232/chrout_rs232.s @@ -0,0 +1,14 @@ + +// +// RS-232 part of the CHROUT routine +// + + +#if HAS_RS232 + + +chrout_rs232: + STUB_IMPLEMENTATION() // XXX provide implementation for both UP2400 and UP9600 + + +#endif // HAS_RS232 diff --git a/c64/kernal/rs232/ckout_rs232_up2400.s b/c64/kernal/rs232/ckout_rs232_up2400.s new file mode 100644 index 00000000..7cec81d6 --- /dev/null +++ b/c64/kernal/rs232/ckout_rs232_up2400.s @@ -0,0 +1,14 @@ + +// +// RS-232 part of the CKOUT routine +// + + +#if CONFIG_RS232_UP2400 + + +ckout_rs232: + STUB_IMPLEMENTATION() // XXX provide implementation for both UP2400 and UP9600 + + +#endif // CONFIG_RS232_UP2400 diff --git a/c64/kernal/rs232/ckout_rs232_up9600.s b/c64/kernal/rs232/ckout_rs232_up9600.s new file mode 100644 index 00000000..e2877512 --- /dev/null +++ b/c64/kernal/rs232/ckout_rs232_up9600.s @@ -0,0 +1,23 @@ + +// +// RS-232 part of the CKOUT routine +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +ckout_rs232: + + // XXX adapt this + + lda #$02 + sta DFLTO + jsr ENABLE + clc + rts + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/close_rs232.s b/c64/kernal/rs232/close_rs232.s new file mode 100644 index 00000000..52d4bf84 --- /dev/null +++ b/c64/kernal/rs232/close_rs232.s @@ -0,0 +1,42 @@ + +// +// RS-232 part of the CLOSE routine +// + + +#if HAS_RS232 + + +#if CONFIG_MEMORY_MODEL_60K + .error "CONFIG_MEMORY_MODEL_60K is not compatible with RS-232 memory allocation code" +#endif + + +close_rs232: + + // First check how many RS-232 channels are currently allocated. + // If more than one, skip deallocation (other channels still uses the buffer). + + jsr rs232_count_channels + cpx #$02 // set Carry if more than one is open + bcs close_rs232_end + + // Deallocate buffer + + inc MEMSIZK+1 + inc MEMSIZK+1 + + // XXX is this needed? check with original ROM what it actually does + + lda #$00 + sta ROBUF+0 + sta ROBUF+1 + sta RIBUF+0 + sta RIBUF+1 + +close_rs232_end: + + jmp close_remove_from_table + + +#endif // HAS_RS232 diff --git a/c64/kernal/rs232/getin_rs232.s b/c64/kernal/rs232/getin_rs232.s new file mode 100644 index 00000000..17215ead --- /dev/null +++ b/c64/kernal/rs232/getin_rs232.s @@ -0,0 +1,14 @@ + +// +// RS-232 part of the GETIN routine +// + + +#if HAS_RS232 + + +getin_rs232: + STUB_IMPLEMENTATION() // XXX provide implementation for both UP2400 and UP9600 + + +#endif // HAS_RS232 diff --git a/c64/kernal/rs232/open_rs232.s b/c64/kernal/rs232/open_rs232.s new file mode 100644 index 00000000..f4b1c0a0 --- /dev/null +++ b/c64/kernal/rs232/open_rs232.s @@ -0,0 +1,60 @@ + +// +// RS-232 part of the OPEN routine +// + + +#if HAS_RS232 + + +#if CONFIG_MEMORY_MODEL_60K + .error "CONFIG_MEMORY_MODEL_60K is not compatible with RS-232 memory allocation code" +#endif + + +open_rs232: + + // First check how many RS-232 channels are currently allocated. + // If more than one, skip allocation (already allocated). + + jsr rs232_count_channels + cpx #$02 // set Carry if more than one is open + bcs open_rs232_end + + // Allocate buffers - first RIBUF, afterwards ROBUF + // (checked addresses on original ROMs) + + lda MEMSIZK+0 + sta ROBUF+0 + sta RIBUF+0 + + dec MEMSIZK+1 + lda MEMSIZK+1 + sta RIBUF+1 + + dec MEMSIZK+1 + lda MEMSIZK+1 + sta ROBUF+1 + + // Initialize buffer indexes + + lda #$00 + sta RIDBE + sta RIDBS + sta RODBS + sta RODBE + + +#if CONFIG_RS232_UP9600 + + jmp up9600_enable + +#endif // CONFIG_RS232_UP9600 + + +open_rs232_end: + + jmp open_done_success + + +#endif // HAS_RS232 diff --git a/c64/kernal/rs232/rs232_count_channels.s b/c64/kernal/rs232/rs232_count_channels.s new file mode 100644 index 00000000..7e032781 --- /dev/null +++ b/c64/kernal/rs232/rs232_count_channels.s @@ -0,0 +1,26 @@ + +// +// Sets .X to number of open RS-232 channels +// + + +#if HAS_RS232 + + +rs232_count_channels: + + ldx #$00 + ldy LDTND +!: + dey + bmi close_rs232_search_done + lda FAT, y + cmp #$02 + bne !- + inx + bpl !- // branch always + + rts + + +#endif diff --git a/c64/kernal/rs232/up9600_disable.s b/c64/kernal/rs232/up9600_disable.s new file mode 100644 index 00000000..80ec3cc4 --- /dev/null +++ b/c64/kernal/rs232/up9600_disable.s @@ -0,0 +1,44 @@ + +// +// Disable UP9600 interface +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_disable: // XXX adapt + + // XXX restore interrupt vectors and IRQ timer + + sei + lda CIA2_PRB // $DD01; DISABLE RTS + and #$FD + sta CIA2_PRB // $DD01 + lda #$7F + sta CIA2_ICR // $DD0D ; DISABLE ALL CIA INTERRUPTS + sta CIA1_ICR // $DC0D + lda #$41; QUICK (AND DIRTY) HACK TO SWITCH BACK + sta CIA1_TIMAHI // $DC05 ; TO THE DEFAULT CIA1 CONFIGURATION + lda #$81 + sta CIA1_ICR // $DC0D ; ENABLE TIMER1 (THIS IS DEFAULT) + lda #ORIGIRQ + sta IRQVECT+1 + lda #ORIGNMI + sta NMIVECT+1 + cli + pla + tay + pla + tax + pla + + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_enable.s b/c64/kernal/rs232/up9600_enable.s new file mode 100644 index 00000000..f282588c --- /dev/null +++ b/c64/kernal/rs232/up9600_enable.s @@ -0,0 +1,133 @@ + +// +// Enable UP9600 interface support +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_enable: // XXX adapt + + sei + + + + lda IRQVECT + cmp #ORIGIRQ + bne INSTERR; IRQ-VECTOR ALREADY CHANGED + lda NMIVECT + cmp #ORIGNMI + bne INSTERR; NMI-VECTOR ALREADY CHANGED + ldy #0 + sty RODBE + sty RODBS + sty RIDBE + sty RIDBS + ; PROBE FOR RS232 INTERFACE + cli + lda #$7F + sta CIA2_ICR // $DD0D ; DISABLE ALL NMIS + lda #$80 + sta CIA2_DDRB // $DD03 ; PB7 USED AS OUTPUT + sta $DD0E; STOP TIMERA + sta CIA2_CRB // $DD0F ; STOP TIMERB + bit CIA2_ICR // $DD0D ; CLEAR PENDING INTERRUPTS + ldx #8 +INSTALL2 + stx CIA2_PRB // $DD01; TOGGLE TXD + sta CIA2_PRB // $DD01; AND LOOK IF IT TRIGGERS AN + dex; SHIFT-REGISTER INTERRUPT + bne INSTALL2 + lda CIA2_ICR // $DD0D ; CHECK FOR BIT3 (SDR-FLAG) + and #8 + beq INSTERR; NO INTERFACE DETECTED + ; GENERATE LOOKUP TABLE + ldx #0 +INSTALL3 + stx OUTSTAT; OUTSTAT USED AS TEMPORARY VARIABLE + ldy #8 +INSTALL4 + asl OUTSTAT + ror + dey + bne INSTALL4 + sta REVTAB,X + inx + bpl INSTALL3 + + + + + + sei + // XXX set NEWIRQ as IRQ vector + // XXX set NMIDOBIT as NMI vector + + ldx TVSFLG; PAL OR NTSC VERSION PRINT + lda ILOTAB,X; (KEYSCAN INTERRUPT ONCE EVERY 1/64 SECOND) + sta CIA1_TIMBLO // $DC06 ; (SORRY THIS WILL BREAK CODE, THAT USES + lda IHITAB,X; THE TI$ - VARIABLE) + sta CIA1_TIMBHI // $DC07 ; START VALUE FOR TIMER B (OF CIA1) + txa + asl + eor #$33; ** TIME CONSTANT FOR SENDER ** + ldx #0; 51 OR 55 DEPENDING ON PAL/NTSC VERSION + sta CIA1_TIMALO // $DC04 ; START VALUE FOR TIMERA (OF CIA1) + stx CIA1_TIMAHI // $DC05 ; (TIME IS AROUND 1/(2*BAUDRATE) ) + asl; ** TIME CONSTANT FOR RECEIVER ** + ora #1; 103 OR 111 DEPENDING ON PAL/NTSC VERSION + sta CIA2_TIMBLO // $DD06 ; START VALUE FOR TIMERB (OF CIA2) + stx CIA2_TIMBHI // $DD07 ; (TIME IS AROUND 1/BAUDRATE ) + lda #$41; START TIMERA OF CIA1, SP1 USED AS OUTPUT + sta CIA1_CRA // $DC0E ; GENERATES THE SENDER'S BIT CLOCK + lda #1 + sta OUTSTAT + sta CIA1_ICR // $DC0D ; DISABLE TIMERA (CIA1) INTERRUPT + sta CIA1_CRB // $DC0F ; START TIMERB OF CIA1 (GENERATES KEYSCAN IRQ) + lda #$92; STOP TIMERB OF CIA2 (ENABLE SIGNAL AT PB7) + sta CIA2_CRB // $DD0F + lda #$98 + bit CIA2_ICR // $DD0D ; CLEAR PENDING NMIS + sta CIA2_ICR // $DD0D ; ENABLE NMI (SDR AND FLAG) (CIA2) + lda #$8A + sta CIA1_ICR // $DC0D ; ENABLE IRQ (TIMERB AND SDR) (CIA1) + lda #$FF + sta CIA2_PRB // $DD01; PB0-7 DEFAULT TO 1 + sta CIA1_SDR // $DC0C ; SP1 DEFAULTS TO 1 + sec + lda RIDBE + sbc RIDBS + cmp #200 + bcc ENABLE2;; DON'T ENABLE RTS IF REC-BUFFER IS FULL + lda #2;; ENABLE RTS + sta CIA2_DDRB // $DD03 ;; (THE RTS LINE IS THE ONLY OUTPUT) +ENABLE2 + cli + pla + tay + pla + tax + pla + rts + + + + +INSTERR + cli + sec + rts + + + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_ihitab.s b/c64/kernal/rs232/up9600_ihitab.s new file mode 100644 index 00000000..05310e40 --- /dev/null +++ b/c64/kernal/rs232/up9600_ihitab.s @@ -0,0 +1,18 @@ + +// +// Timer values for PAL/NTSC - high bytes +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_ihitab: + + .byte $42 + .byte $40 + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_ilotab.s b/c64/kernal/rs232/up9600_ilotab.s new file mode 100644 index 00000000..bede02ea --- /dev/null +++ b/c64/kernal/rs232/up9600_ilotab.s @@ -0,0 +1,18 @@ + +// +// Timer values for PAL/NTSC - low bytes +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_ilotab: + + .byte $95 + .byte $25 + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_irq.s b/c64/kernal/rs232/up9600_irq.s new file mode 100644 index 00000000..a5a99e0e --- /dev/null +++ b/c64/kernal/rs232/up9600_irq.s @@ -0,0 +1,40 @@ + +// +// RS-232 IRQ handler part +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_irq: + + lda CIA1_ICR // $DC0D + + lsr + lsr // move bit 1 (timer B flag) into Carry + and #$02 // test SDR (shift register) status + + beq up9600_irq_continue + + ldx RINONE + beq !+ // skip if not waiting for empty SDR + dex + stx RINONE +!: + bcc up9600_irq_end + +up9600_irq_continue: + + rts + +up9600_irq_end: + + pla + pla + jmp return_from_interrupt + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_nmi.s b/c64/kernal/rs232/up9600_nmi.s new file mode 100644 index 00000000..fea3652d --- /dev/null +++ b/c64/kernal/rs232/up9600_nmi.s @@ -0,0 +1,66 @@ + +// +// RS-232 NMI handler part +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_nmi: + // XXX integrate with NMI handler + + pha + bit CIA2_ICR // $DD0D; check if CIA caused the interrupt + bpl NMIDOBI2; NO STARTBIT RECEIVED, THEN SKIP + lda #$13 + sta CIA2_CRB // $DD0F; START TIMER B (FORCED RELOAD, SIGNAL AT PB7) + sta CIA2_ICR // $DD0D; DISABLE TIMER AND FLAG INTERRUPTS + lda #NMIBYTRY + sta NMIVECT+1 +NMIDOBI2 + pla; IGNORE, IF NMI WAS TRIGGERED BY RESTORE-KEY + rti + ; +NMIBYTRY + pha + bit CIA2_ICR // $DD0D; CHECK BIT 7 (SDR FULL PRINT) + bpl NMIDOBI2; SDR NOT FULL, THEN SKIP (EG. RESTORE-KEY) + lda #$92 + sta CIA2_CRB // $DD0F; STOP TIMER B (KEEP SIGNALLING AT PB7!) + sta CIA2_ICR // $DD0D; ENABLE FLAG (AND TIMER) INTERRUPTS + lda #NMIDOBIT + sta NMIVECT+1 + phx_trash_a + phy_trash_a + lda CIA2_SDR // $DD0C; READ SDR (BIT0=DATABIT7,...,BIT7=DATABIT0) + cmp #128; MOVE BIT7 INTO CARRY-FLAG + and #127 + tax + lda REVTAB,X; READ DATABITS 1-7 FROM LOOKUP TABLE + adc #0; ADD DATABIT0 + ldy RIDBE; AND WRITE IT INTO THE RECEIVE BUFFER + sta (RIBUF),Y + iny + sty RIDBE + sec;;START BUFFER FULL CHK + tya + sbc RIDBS + cmp #200 + bcc NMIBYTR2 + lda CIA2_PRB // $DD01;; MORE THAN 200 BYTES IN THE RECEIVE BUFFER + and #$FD;; THEN DISABLE RTS + sta CIA2_PRB // $DD01 +NMIBYTR2 + ply_trash_a + plx_trash_a + pla + rti + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_rsin.s b/c64/kernal/rs232/up9600_rsin.s new file mode 100644 index 00000000..39009f0c --- /dev/null +++ b/c64/kernal/rs232/up9600_rsin.s @@ -0,0 +1,43 @@ + +// +// Get byte from serial interface +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_rsin: + + ldy RIDBS + cpy RIDBE + beq up9600_rsin_end; // skip (empty buffer, return with carry set) + + lda (RIBUF),Y + iny + sty RIDBS + pha // begin buffer emptying chk + tya + sec + sbc RIDBE + cmp #206 // 256-50 + bcc !+ + lda #$02 + ora CIA2_PR // $DD01 + sta CIA2_PR // enable RTS + clc + + // FALLTROUGH + +!: + pla + + // FALLTROUGH + +up9600_rsin_end: + + rts + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/rs232/up9600_rsout.s b/c64/kernal/rs232/up9600_rsout.s new file mode 100644 index 00000000..fd4e607d --- /dev/null +++ b/c64/kernal/rs232/up9600_rsout.s @@ -0,0 +1,56 @@ + +// +// Put byte to serial interface +// + +// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations + + +#if CONFIG_RS232_UP9600 + + +up9600_rsout: + + pha + sta $9E // XXX synchronize with aliases + cmp #$80 + and #$7F + stx $A8 // XXX synchronize with aliases + sty $A7 // XXX synchronize with aliases + tax + jsr up9600_rsout_time + + lda REVTAB, x + adc #$00 + lsr + sei + sta CIA1_SDR // $DC0C + lda #$02 + STA XXX_OUTSTAT + ror + ora #$7F + sta CIA1_SDR // $DC0C + cli + ldx $A8 // XXX synchronize with aliases + ldy $A7 // XXX synchronize with aliases + pla + rts + +up9600_rsout_time: + + cli + lda #$FD + sta TIME+2 // XXX check if this is the lowest byte + +rs232_rsout_wait: + + lda XXX_OUTSTAT + beq !+ + bit TIME+2 + bmi up9600_rsout_wait + +!: + jmp $F490 // XXX + + +#endif // CONFIG_RS232_UP9600 diff --git a/c64/kernal/screen/chrout_screen_clr.s b/c64/kernal/screen/chrout_screen_clr.s new file mode 100644 index 00000000..ab9469dd --- /dev/null +++ b/c64/kernal/screen/chrout_screen_clr.s @@ -0,0 +1,9 @@ + +// +// CLR key handling within CHROUT +// + +chrout_screen_CLR: + + jsr clear_screen + jmp chrout_screen_done diff --git a/c64/kernal/screen/chrout_screen_control.s b/c64/kernal/screen/chrout_screen_control.s index ff4f5706..83686dde 100644 --- a/c64/kernal/screen/chrout_screen_control.s +++ b/c64/kernal/screen/chrout_screen_control.s @@ -7,176 +7,55 @@ chrout_screen_control: txa - // Order here is not random - // 1. First handle the ones that do not depend on quoote mode - // 2. Handle remaining control codes starting from the most commonly used - // in situations when speed might matter, we want to be - // as snappy as possible +chrout_try_jumptable: -chrout_try_RETURN: + ldx #(__chrout_screen_jumptable_codes_end - chrout_screen_jumptable_codes - 1) - cmp #$0D - bne !+ +chrout_try_jumptable_loop: - // RETURN clears quote and insert modes, it also clears reverse flag - lda #$00 - sta QTSW - sta INSRT - sta RVS - jmp chrout_screen_advance_to_next_line -!: -chrout_try_DEL: - - cmp #$14 - bne !+ - jmp chrout_screen_del -!: -chrout_try_quote: + cpx #(__chrout_screen_jumptable_quote_guard - chrout_screen_jumptable_codes - 1) + bne chrout_try_jumptable_loop_noquote + // Is this insert/quote mode? + tay lda QTSW ora INSRT beq !+ + tya jmp chrout_screen_quote !: - txa + tya -chrout_try_CRSR_UP: + // FALLTROUGH - cmp #$91 +chrout_try_jumptable_loop_noquote: + + cmp chrout_screen_jumptable_codes, x bne !+ - lda PNTR - sec - sbc #40 - sta PNTR - jmp chrout_screen_calc_lptr_done + // Found, perform a jump to subroutine + lda chrout_screen_jumptable_hi, x + pha + lda chrout_screen_jumptable_lo, x + pha + rts !: -chrout_try_CRSR_DOWN: + dex + bpl chrout_try_jumptable_loop - cmp #$11 - bne !+ - - lda PNTR - clc - adc #40 - sta PNTR - // We need to advance the pointer manually, as normalising - // now will break things. The pointer update is required - // so that we can tell if we really are on the bottom phys - // screen line or not - jsr screen_scroll_up_if_on_last_line - jmp chrout_screen_calc_lptr_done -!: -chrout_try_CRSR_LEFT: - - cmp #$9D - bne !+ - - lda TBLX - ora PNTR - beq crsr_l1 // recalculating pointer is not really necessary, but this is a very rare case nevertheless - dec PNTR -crsr_l1: - jmp chrout_screen_calc_lptr_done -!: -chrout_try_CRSR_RIGHT: - - cmp #$1D - bne !+ - - inc PNTR - jmp chrout_screen_calc_lptr_done -!: -chrout_try_RVS_ON: - - cmp #$12 - bne !+ - - lda #$80 - bne rvs_l1 -!: -chrout_try_RVS_OFF: - - cmp #$92 - bne !+ - - lda #$00 -rvs_l1: - sta RVS - jmp chrout_screen_done -!: -chrout_try_MODE_GFX: - - cmp #$8E - bne !+ - - lda VIC_YMCSB - and #$02 // to upper case -mode_l1: - sta VIC_YMCSB - jmp chrout_screen_done -!: -chrout_try_MODE_TXT: - - cmp #$0E - bne !+ - - lda VIC_YMCSB - ora #$02 // to lower case - bne mode_l1 // branch always -!: chrout_try_COLOR: ldx #$0F -colour_check_loop: + +chrout_try_color_loop: + cmp colour_codes,x bne !+ stx COLOR jmp chrout_screen_done !: dex - bpl colour_check_loop - -chrout_try_SHIFT_ENABLE: - - cmp #$09 - bne !+ - - lda #$00 // enable SHIFT+VENDOR combination - sta MODE + bpl chrout_try_color_loop + // Unknown code, or key not requiring any handling jmp chrout_screen_done -!: -chrout_try_SHIFT_DISABLE: - - cmp #$08 - bne !+ - - lda #$80 // disable SHIFT+VENDOR combination - sta MODE - - jmp chrout_screen_done -!: -chrout_try_HOME: - - cmp #$13 - bne !+ - - jsr cursor_home - jmp chrout_screen_done -!: -chrout_try_CLR: - - cmp #$93 - bne !+ - - jsr clear_screen -clr_l1: - jmp chrout_screen_done -!: -chrout_try_INS: - - cmp #$94 - bne clr_l1 // unknown code or key does not need handling - - jmp chrout_screen_ins diff --git a/c64/kernal/screen/chrout_screen_crsr.s b/c64/kernal/screen/chrout_screen_crsr.s new file mode 100644 index 00000000..ed174568 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_crsr.s @@ -0,0 +1,43 @@ + +// +// Cursor keys handling within CHROUT +// + + +chrout_screen_CRSR_UP: + + lda PNTR + sec + sbc #40 + sta PNTR + jmp chrout_screen_calc_lptr_done + + +chrout_screen_CRSR_DOWN: + + lda PNTR + clc + adc #40 + sta PNTR + // We need to advance the pointer manually, as normalising + // now will break things. The pointer update is required + // so that we can tell if we really are on the bottom phys + // screen line or not + jsr screen_scroll_up_if_on_last_line + jmp chrout_screen_calc_lptr_done + + +chrout_screen_CRSR_LEFT: + + lda TBLX + ora PNTR + beq !+ // top-left corner, recalculating pointer is not necessary, but this is a very rare case nevertheless + dec PNTR +!: + jmp chrout_screen_calc_lptr_done + + +chrout_screen_CRSR_RIGHT: + + inc PNTR + jmp chrout_screen_calc_lptr_done diff --git a/c64/kernal/screen/chrout_screen_del.s b/c64/kernal/screen/chrout_screen_del.s index 135f4777..88a403b2 100644 --- a/c64/kernal/screen/chrout_screen_del.s +++ b/c64/kernal/screen/chrout_screen_del.s @@ -3,7 +3,7 @@ // CHROUT routine - screen support, DEL key handling // -chrout_screen_del: +chrout_screen_DEL: // In insert mode it embeds control character ldx INSRT diff --git a/c64/kernal/screen/chrout_screen_gfxtxt.s b/c64/kernal/screen/chrout_screen_gfxtxt.s new file mode 100644 index 00000000..e523e03b --- /dev/null +++ b/c64/kernal/screen/chrout_screen_gfxtxt.s @@ -0,0 +1,19 @@ + +// +// GFX/TXT mode switch handling within CHROUT +// + + +chrout_screen_GFX: + + lda VIC_YMCSB + and #$02 // to upper case +!: + sta VIC_YMCSB + jmp chrout_screen_done + +chrout_screen_TXT: + + lda VIC_YMCSB + ora #$02 // to lower case + bne !- // branch always diff --git a/c64/kernal/screen/chrout_screen_home.s b/c64/kernal/screen/chrout_screen_home.s new file mode 100644 index 00000000..77976bd0 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_home.s @@ -0,0 +1,10 @@ + +// +// HOME key handling within CHROUT +// + + +chrout_screen_HOME: + + jsr cursor_home + jmp chrout_screen_done diff --git a/c64/kernal/screen/chrout_screen_ins.s b/c64/kernal/screen/chrout_screen_ins.s index 8e0e7f63..3082012a 100644 --- a/c64/kernal/screen/chrout_screen_ins.s +++ b/c64/kernal/screen/chrout_screen_ins.s @@ -3,7 +3,7 @@ // CHROUT routine - screen support, INS key handling // -chrout_screen_ins: +chrout_screen_INS: // Insert (shift-DELETE) diff --git a/c64/kernal/screen/chrout_screen_jumptable_codes.s b/c64/kernal/screen/chrout_screen_jumptable_codes.s new file mode 100644 index 00000000..448c3f96 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_jumptable_codes.s @@ -0,0 +1,87 @@ + +// +// Jumptable for screen control coldes support. To improve performance, should be sorted +// starting from the least probable routine. +// + + +chrout_screen_jumptable_codes: + + .byte KEY_CLR + .byte KEY_HOME + .byte KEY_SHIFT_OFF + .byte KEY_SHIFT_ON + .byte KEY_TXT + .byte KEY_GFX + .byte KEY_RVS_OFF + .byte KEY_RVS_ON + .byte KEY_CRSR_RIGHT + .byte KEY_CRSR_LEFT + .byte KEY_CRSR_DOWN + .byte KEY_CRSR_UP + +__chrout_screen_jumptable_quote_guard: + +#if CONFIG_EDIT_STOPQUOTE + .byte KEY_STOP +#endif +#if CONFIG_EDIT_TABULATORS + .byte KEY_TAB_BW + .byte KEY_TAB_FW +#endif + .byte KEY_INS + .byte KEY_DEL + .byte KEY_RETURN + +__chrout_screen_jumptable_codes_end: + + +chrout_screen_jumptable_lo: + + .byte <(chrout_screen_CLR - 1) + .byte <(chrout_screen_HOME - 1) + .byte <(chrout_screen_SHIFT_OFF - 1) + .byte <(chrout_screen_SHIFT_ON - 1) + .byte <(chrout_screen_TXT - 1) + .byte <(chrout_screen_GFX - 1) + .byte <(chrout_screen_RVS_OFF - 1) + .byte <(chrout_screen_RVS_ON - 1) + .byte <(chrout_screen_CRSR_RIGHT - 1) + .byte <(chrout_screen_CRSR_LEFT - 1) + .byte <(chrout_screen_CRSR_DOWN - 1) + .byte <(chrout_screen_CRSR_UP - 1) +#if CONFIG_EDIT_STOPQUOTE + .byte <(chrout_screen_STOP - 1) +#endif +#if CONFIG_EDIT_TABULATORS + .byte <(chrout_screen_TAB_BW - 1) + .byte <(chrout_screen_TAB_FW - 1) +#endif + .byte <(chrout_screen_INS - 1) + .byte <(chrout_screen_DEL - 1) + .byte <(chrout_screen_RETURN - 1) + +chrout_screen_jumptable_hi: + + .byte >(chrout_screen_CLR - 1) + .byte >(chrout_screen_HOME - 1) + .byte >(chrout_screen_SHIFT_OFF - 1) + .byte >(chrout_screen_SHIFT_ON - 1) + .byte >(chrout_screen_TXT - 1) + .byte >(chrout_screen_GFX - 1) + .byte >(chrout_screen_RVS_OFF - 1) + .byte >(chrout_screen_RVS_ON - 1) + .byte >(chrout_screen_CRSR_RIGHT - 1) + .byte >(chrout_screen_CRSR_LEFT - 1) + .byte >(chrout_screen_CRSR_DOWN - 1) + .byte >(chrout_screen_CRSR_UP - 1) +#if CONFIG_EDIT_STOPQUOTE + .byte >(chrout_screen_STOP - 1) +#endif +#if CONFIG_EDIT_TABULATORS + .byte >(chrout_screen_TAB_BW - 1) + .byte >(chrout_screen_TAB_FW - 1) +#endif + .byte >(chrout_screen_INS - 1) + .byte >(chrout_screen_DEL - 1) + .byte >(chrout_screen_RETURN - 1) diff --git a/c64/kernal/screen/chrout_screen_return.s b/c64/kernal/screen/chrout_screen_return.s new file mode 100644 index 00000000..521c5323 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_return.s @@ -0,0 +1,14 @@ + +// +// RETURN key handling within CHROUT +// + + +chrout_screen_RETURN: + + // RETURN clears quote and insert modes, it also clears reverse flag + lda #$00 + sta QTSW + sta INSRT + sta RVS + jmp chrout_screen_advance_to_next_line diff --git a/c64/kernal/screen/chrout_screen_rvs.s b/c64/kernal/screen/chrout_screen_rvs.s new file mode 100644 index 00000000..b1f68b76 --- /dev/null +++ b/c64/kernal/screen/chrout_screen_rvs.s @@ -0,0 +1,17 @@ + +// +// RVS ON/OFF handling within CHROUT +// + + +chrout_screen_RVS_ON: + + lda #$80 + bne !+ // branch always + +chrout_screen_RVS_OFF: + + lda #$00 +!: + sta RVS + jmp chrout_screen_done diff --git a/c64/kernal/screen/chrout_screen_shift_onoff.s b/c64/kernal/screen/chrout_screen_shift_onoff.s new file mode 100644 index 00000000..8f16587d --- /dev/null +++ b/c64/kernal/screen/chrout_screen_shift_onoff.s @@ -0,0 +1,16 @@ + +// +// SHIFT ON/OFF handling within CHROUT +// + +chrout_screen_SHIFT_ON: + + lda #$00 // enable SHIFT+VENDOR combination +!: + sta MODE + jmp chrout_screen_done + +chrout_screen_SHIFT_OFF: + + lda #$80 // disable SHIFT+VENDOR combination + bne !- // branch always diff --git a/c64/kernal/screen/chrout_screen_stop.s b/c64/kernal/screen/chrout_screen_stop.s new file mode 100644 index 00000000..179c217f --- /dev/null +++ b/c64/kernal/screen/chrout_screen_stop.s @@ -0,0 +1,18 @@ + +// +// STOP key handling within CHROUT +// + + +#if CONFIG_EDIT_STOPQUOTE + + +chrout_screen_STOP: + + lda #$00 + sta QTSW + sta INSRT + jmp chrout_screen_done + + +#endif diff --git a/c64/kernal/screen/chrout_screen_tab.s b/c64/kernal/screen/chrout_screen_tab.s new file mode 100644 index 00000000..ac48295c --- /dev/null +++ b/c64/kernal/screen/chrout_screen_tab.s @@ -0,0 +1,33 @@ + +// +// Tabulation keys handling within CHROUT +// + + +#if CONFIG_EDIT_TABULATORS + + +chrout_screen_TAB_FW: + + lda PNTR + ora #%00000111 + sta PNTR + inc PNTR + jmp chrout_screen_calc_lptr_done + + +chrout_screen_TAB_BW: + + lda TBLX + ora PNTR + beq !+ // top-left corner, recalculating pointer is not necessary, but this is a very rare case nevertheless + + dec PNTR + lda PNTR + and #%11111000 + sta PNTR +!: + jmp chrout_screen_calc_lptr_done + + +#endif // CONFIG_EDIT_TABULATORS diff --git a/c64/kernal/screen/screen_grow_logical_line.s b/c64/kernal/screen/screen_grow_logical_line.s index d2995b3c..b90f36de 100644 --- a/c64/kernal/screen/screen_grow_logical_line.s +++ b/c64/kernal/screen/screen_grow_logical_line.s @@ -36,7 +36,13 @@ count_rows_loop: cpx #0 beq no_copy_down bmi no_copy_down - + + // Preserve EAL + lda EAL+0 + pha + lda EAL+1 + pha + // 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 @@ -105,6 +111,12 @@ cl_inner: dex bne copy_line_down_loop + // Restore EAL + pla + sta EAL+1 + pla + sta EAL+0 + no_copy_down: jsr screen_calculate_line_pointer diff --git a/c64/kernal/screen/screen_off.s b/c64/kernal/screen/screen_off.s new file mode 100644 index 00000000..c8f811d8 --- /dev/null +++ b/c64/kernal/screen/screen_off.s @@ -0,0 +1,28 @@ + +// +// Helper routine to blank screen +// + + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO || (CONFIG_IEC_JIFFYDOS && !CONFIG_MEMORY_MODEL_60K) + + +screen_off: + + lda VIC_SCROLY + and #($FF - $10) + sta VIC_SCROLY + + // To be sure there are no badlines we have to wait till the next screen, + // as the bit is checked by VIC-II at the start of the frame only +!: + lda VIC_SCROLY // wait for higher part of screen + bpl !- +!: + lda VIC_SCROLY // wait for lower part of the screen + bmi !- + + rts + + +#endif diff --git a/c64/kernal/screen/screen_on.s b/c64/kernal/screen/screen_on.s new file mode 100644 index 00000000..4742321b --- /dev/null +++ b/c64/kernal/screen/screen_on.s @@ -0,0 +1,18 @@ + +// +// Helper routine to show screen +// + + +#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO + + +screen_on: + + lda VIC_SCROLY + ora #$10 + sta VIC_SCROLY + + rts + +#endif diff --git a/c64/kernal/screen/screen_scroll_up_if_on_last_line.s b/c64/kernal/screen/screen_scroll_up_if_on_last_line.s index 8f8281b9..1ad713cc 100644 --- a/c64/kernal/screen/screen_scroll_up_if_on_last_line.s +++ b/c64/kernal/screen/screen_scroll_up_if_on_last_line.s @@ -28,6 +28,13 @@ is_last_line: // FALLTHROUGH scroll_screen_up: + + // Preserve EAL + lda EAL+0 + pha + lda EAL+1 + pha + // Now scroll the whole screen up either one or two lines // based on whether the first screen line is linked or not. @@ -88,6 +95,12 @@ scroll_copy_loop2: dex bne scroll_copy_loop2 + // Restore EAL + pla + sta EAL+1 + pla + sta EAL+0 + // Fill in scrolled up area ldx SAL+0 scroll_copy_loop3: diff --git a/c64/kernal/tape/load_tape_normal.s b/c64/kernal/tape/load_tape_normal.s new file mode 100644 index 00000000..e9e69370 --- /dev/null +++ b/c64/kernal/tape/load_tape_normal.s @@ -0,0 +1,36 @@ + +// +// Tape (normal) part of the LOAD routine +// + + +// 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 + +// 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,M) = 0 bit +// (M,S) = 1 bit +// (L,M) = new-data marker +// (L,S) = end-of-data marker + + +#if CONFIG_TAPE_NORMAL + + +load_tape_normal: + STUB_IMPLEMENTATION() + + +#endif diff --git a/c64/kernal/tape/load_tape_turbo.s b/c64/kernal/tape/load_tape_turbo.s new file mode 100644 index 00000000..a676d6d5 --- /dev/null +++ b/c64/kernal/tape/load_tape_turbo.s @@ -0,0 +1,185 @@ + +// +// Tape (turbo) part of the LOAD routine +// + +// Based on routine by enthusi/Onslaught, found here: +// - https://codebase64.pokefinder.org/doku.php?id=base:turbotape_loader_source + + +// XXX use calibration bits to improve reading + + +#if CONFIG_TAPE_TURBO + + +load_tape_turbo: + + jsr tape_ditch_verify // only LOAD is supported, no VERIFY + + lda #$00 + sta CIA2_TIMAHI // $DD05 + lda #$FE // timer threshold for TurboTape + sta CIA2_TIMALO // $DD04 + + jsr tape_clean_sid + jsr tape_ask_play + + // FALLTROUGH + +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) + // 2 bytes - start address + // 2 bytes - end address + 1 + // 1 byte - if $0B (tape timing) contained at the time of saving + // 16 bytes - filename, padded with 0x20 + + jsr tape_turbo_sync_header + ldy #$10 + + // FALLTROUGH + +load_tape_turbo_header_loop: // this strange loop puts metadata after file name + + jsr tape_turbo_get_byte + sta (TAPE1), y + iny + cpy #$15 + bne !+ + ldy #$00 +!: + cpy #$10 + bne load_tape_turbo_header_loop + + jsr tape_clean_sid + jsr tape_handle_header + bcs load_tape_turbo_header // if name does not match, look for other header + + // FALLTROUGH + +load_tape_turbo_payload: + + // Initial checksum value + + lda #$00 + sta PRTY + + // Read file payload + + jsr tape_turbo_sync_payload + + // FALLTROUGH + +load_tape_turbo_loop: + + jsr tape_turbo_get_byte + sta (MEMUSS),y + + eor PRTY // handle checksum + sta PRTY + + // Advance MEMUSS (see Mapping the C64, page 36) + jsr lvs_advance_MEMUSS_check_EAL + bne load_tape_turbo_loop + + // Get the checksum + jsr tape_turbo_get_byte + tax + + // Silence audio + jsr tape_clean_sid + + // Verify the checksum + cpx PRTY + 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 new file mode 100644 index 00000000..9a630bb0 --- /dev/null +++ b/c64/kernal/tape/tape_common.s @@ -0,0 +1,341 @@ + +// +// Common routines for tape support +// + + +#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 +// + +tape_break_error: + + pla + pla + cli + 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 +// + +tape_ask_play: + + sei // timing is critical for tape loading + + // First check whether the button is already pressed + + lda CPU_R6510 + and #$10 + beq tape_wait_play_done + + // Display message + + ldx #__MSG_KERNAL_PRESS_PLAY + jsr print_kernal_message + + // FALLTROUGH + +tape_wait_play_loop: + + jsr udtim_keyboard + jsr STOP + bcs tape_break_error + + lda CPU_R6510 + and #$10 // check for pressed button + bne tape_wait_play_loop + +tape_wait_play_done: + + // Prepare for reading + + lda #$01 + sta CAS1 // set the interlock + + jsr print_return + jmp tape_screen_off_motor_on + + +// +// Handle file header - display it, decide whether load the file or not, etc. +// + +tape_handle_header: + + jsr tape_screen_on_motor_off + + // Print FOUND + file name + + ldx #__MSG_KERNAL_FOUND + jsr print_kernal_message + + ldy #$00 +!: + lda (TAPE1), y + jsr JCHROUT + iny + cpy #$10 + bne !- + + // Header, wait for user decision + + jsr tape_header_get_decision + bcs tape_break_error + + // Check if file name matches + + jsr tape_match_filename + bcs tape_handle_header_skip + + // Setup STAL and EAL + + ldy #$10 + lda (TAPE1), y + sta STAL+0 + + iny + lda (TAPE1), y + sta STAL+1 + + iny + lda (TAPE1), y + sta EAL+0 + + iny + lda (TAPE1), y + sta EAL+1 + + // Handle the secondary address, 0 means loading to location from MEMUSS + + lda SA + bne !+ + + // EAL = EAL - STAL + + sec + lda EAL+0 + sbc STAL+0 + sta EAL+0 + lda EAL+1 + sbc STAL+1 + sta EAL+1 + + // STAL = MEMUSS + + lda MEMUSS+0 + sta STAL+0 + lda MEMUSS+1 + sta STAL+1 + + // EAL = EAL + STAL + + clc + lda EAL+0 + adc STAL+0 + sta EAL+0 + lda EAL+1 + adc STAL+1 + sta EAL+1 +!: + // Setup MEMUSS (see Mapping the C64, page 36) + + jsr lvs_setup_MEMUSS + + // Print LOADING and start address + + jsr lvs_display_loading_verifying + +tape_handle_header_displayed: + + // Load the file + + jsr tape_screen_off_motor_on + + // FALLTROUGH + +tape_return_ok: + + clc + rts + +tape_handle_header_skip: + + // Skip this file + + jsr print_return + jsr tape_screen_off_motor_on + + // FALLTROUGH + +tape_return_not_ok: + + sec + rts + + +// +// Check whether file name matches the pattern +// + +tape_match_filename: + + lda FNLEN + beq tape_return_ok // no pattern to match + + ldy #$00 + +tape_match_loop: + + lda #$20 // default byte, for padding + cpy FNLEN + bcs !+ // end of pattern + lda (FNADDR), y // byte from pattern +!: + cmp #KEY_ASTERISK + beq tape_return_ok + + cmp (TAPE1), y + bne tape_return_not_ok + + iny + cpy #$10 + bne tape_match_loop + + clc + rts + + +// +// Get user decision whether to load the file or not +// + +tape_header_get_decision: + + ldy #$00 +!: + jsr udtim_keyboard + lda STKEY + bpl tape_header_wait_stop // STOP pressed + and #$10 + beq tape_header_wait_space // space pressed + + ldx #$80 + jsr wait_x_bars // sets .X to 0 + dex + jsr wait_x_bars + + dey + bne !- + + // FALLTROUGH - timeout + +tape_header_wait_space: + + clc + rts + +tape_header_wait_stop: + + sec + rts + + +// +// Report that file loading succeeded (or not) +// + +tape_load_success: + + jsr tape_screen_on_motor_off + jsr lvs_display_done + + cli + jmp lvs_return_last_address + +tape_load_error: + + jsr tape_screen_on_motor_off + + cli + jmp lvs_load_verify_error + + +#endif diff --git a/c64/kernal/rdtim.s b/c64/kernal/time/rdtim.s similarity index 100% rename from c64/kernal/rdtim.s rename to c64/kernal/time/rdtim.s diff --git a/c64/kernal/settim.s b/c64/kernal/time/settim.s similarity index 100% rename from c64/kernal/settim.s rename to c64/kernal/time/settim.s diff --git a/c64/kernal/time/udtim.s b/c64/kernal/time/udtim.s new file mode 100644 index 00000000..65dc6aaf --- /dev/null +++ b/c64/kernal/time/udtim.s @@ -0,0 +1,41 @@ + +// +// Official Kernal routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 303 +// - [CM64] Compute's Mapping the Commodore 64 - pages 27, 232 +// +// CPU registers that has to be preserved (see [RG64]): .Y +// + +UDTIM: + + // Update jiffy clock. The whole day is $4F1A00 jiffies + // (24 hours * 60 minutes * 60 seconds * 60 jiffies), + // after this time we have to reset the clock. + + inc TIME+0 + bne udtim_time_done // done with clock + inc TIME+1 + bne udtim_clock_rollover + inc TIME+2 + + // FALLTROUGH + +udtim_time_done: + + jmp udtim_keyboard + +udtim_clock_rollover: + + // At this point TIME+0 contains 0 + lda TIME+1 + cmp #$1A + bne udtim_time_done // done with clock + lda TIME+2 + cmp #$4F + bne udtim_time_done // done with clock + lda #$00 + sta TIME+2 + sta TIME+1 + beq udtim_time_done // done with clock - will always jump diff --git a/doc/Protocol-JiffyDOS.md b/doc/Protocol-JiffyDOS.md new file mode 100644 index 00000000..f3773ad7 --- /dev/null +++ b/doc/Protocol-JiffyDOS.md @@ -0,0 +1,69 @@ + +# JiffyDOS fast protocol description + +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. + +## Documents, samples + +- [1] JiffySoft128 description - see https://sites.google.com/site/h2obsession/CBM/C128/JiffySoft128 +- [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 + +## 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 + +## Timing information + +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 + +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. + +## Protocol detection + +Protocol detection happens when the IEC bus controller sends a command (under ATN) - first 7 bits of the commnad code is sent normally, detection is performed before sending the last bit: +- after releasing DATA, controller delays releasing the CLK +- if within about 400 usec (probably less time is needed, I took the value from a comment in the SD2IEC source code) the device pulls DATA line, it talks the JiffyDOS protocol +- in such case the controller waits till DATA is released again and continues the command transmission + +## 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. + +## Turnover + +Turnover (both to listener and to back to talker) is performed as usual. + +## Sending a byte + +Receiver releases DATA line once it is ready to receive a byte. When the bus controller is ready too (after possible 'badline synchronization' - this wasn't tested, but artificial delay might be needed when maintaining synchronization by screen blanking) it releases the CLK on his side. + +What happens now has to be carefully synchronized between bus controller and receiver, there is not much margin in terms of CPU cycles - see the source code and [2] for details. Basically, we are sending 2 bits a time (using CLK and DATA lines), without any sort of confirmation, and the only synchronization is done via instruction timing: + +- bits 4 (CLK out) and 5 (DATA out) +- bits 6 (CLK out) and 7 (DATA out) +- 2x two bits of the encoded low nibble + +Encoding the low nibble is done via lookup table, reverse engineered by observing the IEC logs from the original JiffyDOS ROMs in action. Unfortunately, IEC registers of the C64 and 1541 do not have the same layout - some bits are reversed and the bit layout is different (see [3]). Thus every single fast IEC protocol has to perform some kind of encoding/decoding; when sending byte using the JiffyDOS protocol the drive handles the high nibble and the controller - the lower one. + +Afterwards the controller either pulls the CLK quickly, or signals EOI by delaying this action. In our implementation the acceptable timing was adjusted by experimentation (pre-existing delay subroutine was used to reduce code size, also note that NTSC machines have slightly higher CPU frequency) - but it's important not to wait too long, 1541 JiffyDOS ROM can handle it, but SD2IEC implementation can not! + +## Receiving a byte + +Device ready to send a byte signals it by releasing CLK, bus controller performs the 'badline synchronization' (note: if screen blanking method was choosen, artificial delay has to be inserted, otherwise communication with 1541 fails; also note the slightly faster CPU frequency on NTSC machines!). Controller releases the DATA line to signal it is ready to accept bits. + +Again, what happens now has to be carefully synchronized between bus controller and receiver, see [2]. Bits are received in the order shown below (using CLK and DATA lines), without any sort of confirmation, and the only synchronization is done via instruction timing: + +- bits 0 (CLK in) and 1 (DATA in) +- bits 2 (CLK in) and 3 (DATA in) +- bits 4 (CLK in) and 5 (DATA in) +- bits 6 (CLK in) and 7 (DATA in) + +No decoding is necessary (we just need to put received bits on proper positions by bit shifting and EOR manipulation to cancel the effect of non-IEC bits of the CIA register). I had to insert some delays (again - watch out for PAL/NTSC clock difference!) to make the protocol work. + +At the end the controller fetches the CLK/DATA bits and pulls DATA. If CLK is set at certain point, it means EOI (I'm not 100% sure about that, but such an implementation seems to work correctly). diff --git a/src/build_segment.cc b/src/build_segment.cc index 97614123..a55a1b96 100644 --- a/src/build_segment.cc +++ b/src/build_segment.cc @@ -109,6 +109,10 @@ public: std::map fixedRoutines; // routines with location already fixed std::map gaps; // gaps by address std::vector floatingRoutines; // routines not allocated to any address yet; always keep them sorted! + + int statSize; + int statFree; + int statWasted; }; class Solver @@ -620,6 +624,12 @@ BinningProblem::BinningProblem(int loAddress, int hiAddress) // Create one large gap (initial) to represent the assembly gaps[loAddress] = hiAddress - loAddress + 1; + + // Initial value of statistics + + statSize = gaps[loAddress]; + statFree = gaps[loAddress]; + statWasted = 0; } bool BinningProblem::isSolved() const @@ -657,6 +667,7 @@ void BinningProblem::addToProblem(SourceFile *routine) // Put the routine into the gap, possibly removing it or splitting into two fixedRoutines[routine->startAddr] = routine; + statFree -= routine->codeLength; // Calculate possible new gap after the routine @@ -702,7 +713,8 @@ void BinningProblem::fillGap(DualStream &logOutput, int gapAddress, const std::l routine->fileName << spacing << "size: " << routine->codeLength << "\n"; fixedRoutines[targetAddr] = routine; - offset += routine->codeLength; + offset += routine->codeLength; + statFree -= routine->codeLength; if (offset > gaps[gapAddress]) ERROR(std::string("internal error line ") + std::to_string(__LINE__)); @@ -718,6 +730,8 @@ 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 { @@ -759,6 +773,7 @@ void BinningProblem::performObviousSteps(DualStream &logOutput) gaps[gapAddress] -= routineSize; int targetAddr = gapAddress + gaps[gapAddress]; fixedRoutines[targetAddr] = floatingRoutines.back(); + statFree -= routineSize; logOutput << "forced reducing gap $" << std::hex << gapAddress << std::dec << " to size " << gaps[gapAddress] << "\n"; @@ -792,6 +807,7 @@ void BinningProblem::removeUselessGaps(DualStream &logOutput) if (gap.second < minUsefulSize) { logOutput << "dropping gap: $" << std::hex << gap.first << std::dec << " (size: " << gap.second << ")" << "\n"; + statWasted += gap.second; gaps.erase(gap.first); repeat = true; break; @@ -847,6 +863,11 @@ void Solver::run() if (problem.isSolved()) { logOutput << "\n" << "all the routines sucessfully placed" << "\n\n"; + + 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"; } // Close the log file diff --git a/src/release.cc b/src/release.cc index af3144e9..38d00872 100644 --- a/src/release.cc +++ b/src/release.cc @@ -20,9 +20,10 @@ typedef struct { std::string romTypeName; size_t fileSize; - size_t signatureOffset; // offset to 'OR' string - bool requireIdBASIC; - bool requireIdKERNAL; + size_t signatureOffset1; // offset to 'OR' string + size_t signatureOffset2; // offset to 'OR' string + size_t idBasicOffset; // offset to BASIC identification string + size_t idKernalOffset; // offset to KERNAL identification byte } ROMTypeDescriptionEntry; @@ -30,22 +31,33 @@ const std::vector ROM_DEFINITIONS = { { "BASIC", - 8192, // file size - 0x1F52, // signature offset - true, // whether to require BASIC ID - false // whether to require KERNAL ID + 8192, // file size + 0x1F52, // signature offset 1 + 0, // signature offset 2 + 0x0004, // BASIC ID offset + 0 // KERNAL ID offset }, { "KERNAL", - 8192, // file size - 0x04B9, // signature offset - false, // whether to require BASIC ID - false // whether to require KERNAL ID + 8192, // file size + 0x04B9, // signature offset 1 + 0, // signature offset 2 + 0, // BASIC ID offset + 0x1F80 // KERNAL ID offset + }, + + { + "MEGA65", + 128 * 1024, // file size + 0xBF52, // signature offset 1 + 0xE4B9, // signature offset 2 + 0xA004, // BASIC ID offset + 0xFF80 // KERNAL ID offset }, }; -const uint16_t MAX_FILE_SIZE = 8192; +const uint32_t MAX_FILE_SIZE = 128 * 1024; const std::vector STR_MEGABAS = { 0x4D, 0x45, 0x47, 0x41, 0x42, 0x41, 0x53, 0x32 }; const std::vector STR_OR = { 0x4F, 0x52 }; @@ -365,33 +377,49 @@ void ROMFile::recognizeSrcFile() { // Recognize source file type - for (auto &SPEC : ROM_DEFINITIONS) + auto checkSignature = [this](size_t signatureOffset) -> bool { - if (srcFileContent.size() != SPEC.fileSize) continue; - - if (SPEC.requireIdBASIC && memcmp(&srcFileContent[0x0004], STR_MEGABAS.data(), STR_MEGABAS.size()) != 0) + if (signatureOffset == 0) { - continue; + return true; } - if (SPEC.requireIdKERNAL && srcFileContent[0x1F80] != 0xF0) + if (memcmp(&srcFileContent[signatureOffset], STR_OR.data(), STR_OR.size()) != 0) { - continue; + return false; } - if (memcmp(&srcFileContent[SPEC.signatureOffset], STR_OR.data(), STR_OR.size()) != 0) - { - continue; - } - - auto snapshotStrOffset = SPEC.signatureOffset + STR_OR.size() + 1; + auto snapshotStrOffset = signatureOffset + STR_OR.size() + 1; if (memcmp(&srcFileContent[snapshotStrOffset], STR_SNAPSHOT.data(), STR_SNAPSHOT.size()) != 0) { - continue; + return false; } auto zeroByteoffset = snapshotStrOffset + 0x10; if (srcFileContent[zeroByteoffset] != 0) + { + return false; + } + + return true; + }; + + for (auto &SPEC : ROM_DEFINITIONS) + { + if (srcFileContent.size() != SPEC.fileSize) continue; + + if ((SPEC.idBasicOffset != 0) && + memcmp(&srcFileContent[SPEC.idBasicOffset], STR_MEGABAS.data(), STR_MEGABAS.size()) != 0) + { + continue; + } + + if ((SPEC.idKernalOffset != 0) && srcFileContent[SPEC.idKernalOffset] != 0xF0) + { + continue; + } + + if (!checkSignature(SPEC.signatureOffset1) || !checkSignature(SPEC.signatureOffset2)) { continue; } @@ -411,19 +439,26 @@ void ROMFile::dropUnmatchingDst() { // Drop unmatching destination file data - if (!dstFileContent.empty() && descPtr->requireIdBASIC && - memcmp(&dstFileContent[0x0004], STR_MEGABAS.data(), STR_MEGABAS.size()) != 0) + if (!dstFileContent.empty() && (descPtr->idBasicOffset != 0) && + memcmp(&dstFileContent[descPtr->idBasicOffset], STR_MEGABAS.data(), STR_MEGABAS.size()) != 0) { dstFileContent.clear(); } - if (!dstFileContent.empty() && descPtr->requireIdKERNAL && dstFileContent[0x1F80] != 0xF0) + if (!dstFileContent.empty() && (descPtr->idKernalOffset != 0) && + dstFileContent[descPtr->idKernalOffset] != 0xF0) { dstFileContent.clear(); } - if (!dstFileContent.empty() && - memcmp(&dstFileContent[descPtr->signatureOffset], STR_OR.data(), STR_OR.size()) != 0) + if (!dstFileContent.empty() && (descPtr->signatureOffset1 != 0) && + memcmp(&dstFileContent[descPtr->signatureOffset1], STR_OR.data(), STR_OR.size()) != 0) + { + dstFileContent.clear(); + } + + if (!dstFileContent.empty() && (descPtr->signatureOffset2 != 0) && + memcmp(&dstFileContent[descPtr->signatureOffset2], STR_OR.data(), STR_OR.size()) != 0) { dstFileContent.clear(); } @@ -431,21 +466,54 @@ void ROMFile::dropUnmatchingDst() void ROMFile::analyzeContent() { - auto revOffset = descPtr->signatureOffset + 3; + auto revOffset1 = (descPtr->signatureOffset1 != 0) ? (descPtr->signatureOffset1 + 3) : 0; + auto revOffset2 = (descPtr->signatureOffset2 != 0) ? (descPtr->signatureOffset2 + 3) : 0; + + if (revOffset1 == 0) + { + revOffset1 = revOffset2; + revOffset2 = 0; + } + + if (revOffset1 == 0) + { + return; + } if (dstFileContent.empty()) { return; } + // If two ID strings are present, they should be the same + + if (0 != revOffset1 && 0 != revOffset2 && + memcmp(&dstFileContent[revOffset1], &dstFileContent[revOffset2], 0x10) != 0) + { + return; + } + // Check if meaningful file content is really different - if ((memcmp(&srcFileContent[0x0000], &dstFileContent[0x0000], revOffset) == 0) && - (memcmp(&srcFileContent[revOffset + 0x10], &dstFileContent[revOffset + 0x10], - descPtr->fileSize - revOffset - 0x10) == 0)) + sameContent = true; + for (uint32_t idx = 0; idx < descPtr->fileSize; idx++) { - sameContent = true; - } + if (revOffset1 != 0 && idx - revOffset1 < 0x10) + { + continue; + } + + if (revOffset2 != 0 && idx - revOffset2 < 0x10) + { + continue; + } + + if (srcFileContent[idx] != dstFileContent[idx]) + { + sameContent = false; + break; + } + } // Determine expected length of developer ID @@ -453,12 +521,12 @@ void ROMFile::analyzeContent() // Determine if old version is a devel version compatible with this tool - if (memcmp(&dstFileContent[revOffset], STR_DEV.data(), STR_DEV.size()) != 0) + if (memcmp(&dstFileContent[revOffset1], STR_DEV.data(), STR_DEV.size()) != 0) { return; } - uint16_t idxDate = revOffset + STR_DEV.size(); + uint16_t idxDate = revOffset1 + STR_DEV.size(); uint16_t idxLimit = idxDate + ENV_dateString.length(); uint16_t idx = idxDate; @@ -503,8 +571,17 @@ void ROMFile::embedRevisionStr(const std::string &newRevisionStr) while (revStr.length() < 16) revStr = revStr + '\0'; - memcpy(&srcFileContent[descPtr->signatureOffset + 3], - revStr.data(), revStr.size()); + if (descPtr->signatureOffset1 != 0) + { + memcpy(&srcFileContent[descPtr->signatureOffset1 + 3], + revStr.data(), revStr.size()); + } + + if (descPtr->signatureOffset2 != 0) + { + memcpy(&srcFileContent[descPtr->signatureOffset2 + 3], + revStr.data(), revStr.size()); + } } void ROMFile::save() diff --git a/strings/00A9009900 b/strings/00A9009900 new file mode 100644 index 00000000..01c5cb64 --- /dev/null +++ b/strings/00A9009900 @@ -0,0 +1,3 @@ +$00 + LDA #$00 + STA (address does not fully match),Y + +Instruction + some parts. Trivial, not copyrightable. diff --git a/strings/012910F0 b/strings/012910F0 new file mode 100644 index 00000000..e106620d --- /dev/null +++ b/strings/012910F0 @@ -0,0 +1,3 @@ +$01 + AND #$10 + BEQ (offset does not match) + +Instrcution + some parts. Trivial - not copyrightable. diff --git a/strings/02A21E4C b/strings/02A21E4C new file mode 100644 index 00000000..874f43f7 --- /dev/null +++ b/strings/02A21E4C @@ -0,0 +1,3 @@ +$02 + LDX #$1E + JMP (address does not match) + +Instruction and some parts - trivial, not copyrightable. diff --git a/strings/02F0034C b/strings/02F0034C new file mode 100644 index 00000000..6b918606 --- /dev/null +++ b/strings/02F0034C @@ -0,0 +1,3 @@ +$02 + BEQ (skip next instruction) + JMP (address does not match) + +Instruction and some parts - trivial, not copyrightable. diff --git a/strings/0D505245535320504C4159204F4E20544150 b/strings/0D505245535320504C4159204F4E20544150 new file mode 100644 index 00000000..acdaf769 --- /dev/null +++ b/strings/0D505245535320504C4159204F4E20544150 @@ -0,0 +1,8 @@ + + 'PRESS PLAY ON TAP' PETSCII string + +The 'PRESS PLAY ON TAPE' cannot be copyrighted, as it is a short, not creative phrase, not used to sell anything. Since then it became a part of the popular culture, it is already used on countless -shirts, book titles, there is even a music band with such name: + +https://books.google.pl/books/about/Press_play_on_tape_Storia_di_un_videogio.html?id=tH5pngEACAAJ +https://www.youtube.com/user/pressplayontape + +Such a phrase is not copyrightable - see https://fairuse.stanford.edu/2003/09/09/copyright_protection_for_short/ diff --git a/strings/18D00902D0 b/strings/18D00902D0 new file mode 100644 index 00000000..c8fb8d9d --- /dev/null +++ b/strings/18D00902D0 @@ -0,0 +1,3 @@ +$D018 + ORA #$02 + BNE (offset does not match) + +Instruction + some parts (including address of a documented I/O register) - trivial, not copyrightable. diff --git a/strings/2044E54C b/strings/2044E54C new file mode 100644 index 00000000..147b349e --- /dev/null +++ b/strings/2044E54C @@ -0,0 +1,3 @@ +JSR $E544 (clear screen) + JMP (address does not match) + +Instruction (call to a well-known routine) + some part - trivial, not copyrightable. diff --git a/strings/20504C4159204F4E20544150 b/strings/20504C4159204F4E20544150 new file mode 100644 index 00000000..bd2305c1 --- /dev/null +++ b/strings/20504C4159204F4E20544150 @@ -0,0 +1,3 @@ +PETSCII string: ' PLAY ON TAP' + +Not even a full phrase - not copyrightable. diff --git a/strings/208AAD20 b/strings/208AAD20 new file mode 100644 index 00000000..7daa77b7 --- /dev/null +++ b/strings/208AAD20 @@ -0,0 +1,3 @@ +JSR $AD8A + JSR (address does not match) + +Instruction and a half. Trivial, not copyrightable. diff --git a/strings/20A9EEB0 b/strings/20A9EEB0 new file mode 100644 index 00000000..92ee40c6 --- /dev/null +++ b/strings/20A9EEB0 @@ -0,0 +1,3 @@ +JSR $EEA9 + BCS (offset does not match) + +Instruction + some part. TYrivial, not copyrightable. diff --git a/strings/20EAFFA5 b/strings/20EAFFA5 new file mode 100644 index 00000000..278cda7c --- /dev/null +++ b/strings/20EAFFA5 @@ -0,0 +1,3 @@ +JSR $FFEA (UDTIM) + LDA (zeropage address does not match) + +Instruction (call to the official routine) + some part. Trivial, not copyrightable. diff --git a/strings/2910F009 b/strings/2910F009 new file mode 100644 index 00000000..799507da --- /dev/null +++ b/strings/2910F009 @@ -0,0 +1,3 @@ +AND #$10 + BEQ (offset matches) + +Check whether the bit of the data in accumulator is set or not. Trivial and not creative - not copyrightable. diff --git a/strings/459B859B b/strings/459B859B new file mode 100644 index 00000000..0983a62c --- /dev/null +++ b/strings/459B859B @@ -0,0 +1,3 @@ +EOR $9B + STA $9B + +Part of the code (incomplete) calculating EOR checksum of data stream - not creative, not copyrightable. diff --git a/strings/464F554E b/strings/464F554E new file mode 100644 index 00000000..a13ffe96 --- /dev/null +++ b/strings/464F554E @@ -0,0 +1,3 @@ +'FOUN' PETSCII string + +Not even a full word - not copyrightable. diff --git a/strings/464F554E44A0 b/strings/464F554E44A0 new file mode 100644 index 00000000..b9e7886a --- /dev/null +++ b/strings/464F554E44A0 @@ -0,0 +1,3 @@ +PETSCII string, with end of string encoded by high bit set: 'FOUND ' + +Single word followed by space, string encoding common for 6502 CPU (for example, Turbo Basic XL for Atari uses the same) - not copyrightable. diff --git a/strings/48A5AF48 b/strings/48A5AF48 new file mode 100644 index 00000000..038ee560 --- /dev/null +++ b/strings/48A5AF48 @@ -0,0 +1,3 @@ +PHA + LDA $AF + PHA + +Piece of code copying EAL variable to the stack. Trivial - not copyrightable. diff --git a/strings/48A5D0F0 b/strings/48A5D0F0 new file mode 100644 index 00000000..a7e65abd --- /dev/null +++ b/strings/48A5D0F0 @@ -0,0 +1,3 @@ +PHA + LDA $D0 + BEQ (address does not match) + +Check the input (screen vs keyboard), preserving .A on stack - trivial, not copyyrightable. diff --git a/strings/494E47A0 b/strings/494E47A0 new file mode 100644 index 00000000..9c2cb283 --- /dev/null +++ b/strings/494E47A0 @@ -0,0 +1,3 @@ +PETSCII string, with end of string encoded by high bit set: 'ING ' + +Single syllable, string encoding common for 6502 CPU (for example, Turbo Basic XL for Atari uses the same) - not copyrightable. diff --git a/strings/494EC70D534156494E47A0 b/strings/494EC70D534156494E47A0 new file mode 100644 index 00000000..37fe667e --- /dev/null +++ b/strings/494EC70D534156494E47A0 @@ -0,0 +1,3 @@ +PETSCII string, with end of string encoded by high bit set: 'ING' + RETURN + 'SAVING ' + +Single word with some parts, string encoding common for 6502 CPU (for example, Turbo Basic XL for Atari uses the same) - not copyrightable. diff --git a/strings/50524553 b/strings/50524553 new file mode 100644 index 00000000..e8e7d394 --- /dev/null +++ b/strings/50524553 @@ -0,0 +1,3 @@ +'PRES' PETSCII string + +Not even a full word - not copyrightable. diff --git a/strings/505245535320 b/strings/505245535320 new file mode 100644 index 00000000..97c99f36 --- /dev/null +++ b/strings/505245535320 @@ -0,0 +1,3 @@ +PETSCII string, with end of string encoded by high bit set: 'PRESS ' + +Single word followed by space, string encoding common for 6502 CPU (for example, Turbo Basic XL for Atari uses the same) - not copyrightable. diff --git a/strings/60A599D0 b/strings/60A599D0 new file mode 100644 index 00000000..d3705eb2 --- /dev/null +++ b/strings/60A599D0 @@ -0,0 +1,3 @@ +RTS + LDA $99 + BNE (offset does not match) + +Routine starts by checking whether a documented zeropagevariable is 0 or not - trivial, not copyrightable. diff --git a/strings/6885AF6885 b/strings/6885AF6885 new file mode 100644 index 00000000..112c7f10 --- /dev/null +++ b/strings/6885AF6885 @@ -0,0 +1,3 @@ +PLA + STA $AF + PLA + STA (zero page address does not match) + +Piece of code retrieving some zero page variables from the stack (not even identical varaibles) - trivial, not copyrightable. diff --git a/strings/6885AF6885AE b/strings/6885AF6885AE new file mode 100644 index 00000000..d638c4b5 --- /dev/null +++ b/strings/6885AF6885AE @@ -0,0 +1,3 @@ +PLA + STA $AF + PLA + STA $AE + +Piece of code copying EAL variable from the stack to zero page locatioon. Trivial - not copyrightable. diff --git a/strings/6C30038593 b/strings/6C30038593 new file mode 100644 index 00000000..c854535f --- /dev/null +++ b/strings/6C30038593 @@ -0,0 +1,3 @@ +JMP ($0330) + STA $93 + +Jump via vector + loading value of a documented zero page variable - trivial, not copyrightable. diff --git a/strings/78AD11D0 b/strings/78AD11D0 new file mode 100644 index 00000000..19c817f3 --- /dev/null +++ b/strings/78AD11D0 @@ -0,0 +1,4 @@ +SEI + LDA $D011 + +Disable interrupts and load value of the I/O register - nothing creative here, to use value from $D011 one often disables interrupts, +otherwise several scanlines might pass if interrupt happens in between our routine. Not copyrightable. diff --git a/strings/83028C8402 b/strings/83028C8402 new file mode 100644 index 00000000..4e3d81c7 --- /dev/null +++ b/strings/83028C8402 @@ -0,0 +1,3 @@ +$0283 + STY $0284 + +Instruction + some part (both accessing documented related addresses) - trivial, not copyrightable. diff --git a/strings/85AF6885 b/strings/85AF6885 new file mode 100644 index 00000000..e20e5ca7 --- /dev/null +++ b/strings/85AF6885 @@ -0,0 +1,3 @@ +STA $AF + PLA + STA $AE + +Part of a routine retrieving EAL 16-bit variable value from stack - trivial, not copyrightable. diff --git a/strings/85AF6885AE b/strings/85AF6885AE new file mode 100644 index 00000000..8ef3455e --- /dev/null +++ b/strings/85AF6885AE @@ -0,0 +1,3 @@ +STA $AF + PLA + STA (zeropage address does not match) + +Part of a routine retrieving EAL 16-bit variable value from stack - trivial, not copyrightable. diff --git a/strings/8D05DDA9 b/strings/8D05DDA9 new file mode 100644 index 00000000..981b1ebd --- /dev/null +++ b/strings/8D05DDA9 @@ -0,0 +1,3 @@ +STA $DD05 + LDA (value does not match) + +Instruction (storing byte in a documented I/O register) + some part. Trivial, not copyrightable. diff --git a/strings/8E03DC8E03DD b/strings/8E03DC8E03DD new file mode 100644 index 00000000..8dced645 --- /dev/null +++ b/strings/8E03DC8E03DD @@ -0,0 +1,3 @@ +STX $DC03 + STX $DD03 + +Part of system initialization - store the same value in both CIA chips. Trivial - not copyrightable. diff --git a/strings/8E16D020 b/strings/8E16D020 new file mode 100644 index 00000000..2aa436db --- /dev/null +++ b/strings/8E16D020 @@ -0,0 +1,3 @@ +STX $D016 + JSR (address does not match) + +Instruction (storing data in a documented I/O register) + some part. Trivial - not copyrightable. diff --git a/strings/90F004A90D18604C b/strings/90F004A90D18604C new file mode 100644 index 00000000..0d90900d --- /dev/null +++ b/strings/90F004A90D18604C @@ -0,0 +1,3 @@ +$90 + BEQ (skip 3 bytes) + LDA #$0D + CLC + RTS + JMP + +Routine ending, returning error code or success - trivial, not copyrightable. diff --git a/strings/91D18810 b/strings/91D18810 new file mode 100644 index 00000000..771b2981 --- /dev/null +++ b/strings/91D18810 @@ -0,0 +1,3 @@ +STA ($D1),Y + DEY + BPL (offset does not match) + +Small part of a loop filling a screen line - trivial, not copyrightable. diff --git a/strings/A000D1AEF0 b/strings/A000D1AEF0 new file mode 100644 index 00000000..99173118 --- /dev/null +++ b/strings/A000D1AEF0 @@ -0,0 +1,3 @@ +LDY #$00 + CMP ($AE),Y + BEQ (address does not match) + +Check of the value poined by EAL variable (whether it is 0 or not) - not creative, not copyrightable. diff --git a/strings/A20FDDDAE8 b/strings/A20FDDDAE8 new file mode 100644 index 00000000..63253a2e --- /dev/null +++ b/strings/A20FDDDAE8 @@ -0,0 +1,3 @@ +LDX #$0F + CMP $E8DA,X + +Small part of a loop checking for PETSCII code in color table (the loop as a whole differs) - trivial, not copyrightable. diff --git a/strings/A5010920 b/strings/A5010920 new file mode 100644 index 00000000..f6c58a16 --- /dev/null +++ b/strings/A5010920 @@ -0,0 +1,3 @@ +LDA $01 + ORA #$20 + +Part of code (two instructions only) to set a bit in a documented I/O register (for manipulating tape motor) - trivial, not copyrightable. diff --git a/strings/A5010920D0 b/strings/A5010920D0 new file mode 100644 index 00000000..542bc60a --- /dev/null +++ b/strings/A5010920D0 @@ -0,0 +1,3 @@ +LDA $01 + ORA #$20 + BNE (offset does not match) + +Simple check whether the button on a tape deck has been pressed - trivial, not copyrightable. diff --git a/strings/A5AE48A5AF48 b/strings/A5AE48A5AF48 new file mode 100644 index 00000000..5090ea36 --- /dev/null +++ b/strings/A5AE48A5AF48 @@ -0,0 +1,3 @@ +LDA $AE + PHA + LDA $AF + PHA + +Piece of code copying EAL variable from zero page to the stack. Trivial - not copyrightable. diff --git a/strings/A5C385C1A5C4 b/strings/A5C385C1A5C4 new file mode 100644 index 00000000..13ca1511 --- /dev/null +++ b/strings/A5C385C1A5C4 @@ -0,0 +1,3 @@ +LDA $C3 + STA $C1 + LDA $C4 + +Copying one 16-bit zero page variable to another (not even complete) - trivial, not copyrightable. diff --git a/strings/A6AEA4AF b/strings/A6AEA4AF new file mode 100644 index 00000000..f0466ef6 --- /dev/null +++ b/strings/A6AEA4AF @@ -0,0 +1,3 @@ +LDX $AE + LDY $AF + +Load documented 16-bit variable (EAL) into registers .X and .Y - trivial, not copyrightable. diff --git a/strings/A92091D188 b/strings/A92091D188 new file mode 100644 index 00000000..357e4bba --- /dev/null +++ b/strings/A92091D188 @@ -0,0 +1,3 @@ +LDA #$20 + STA ($D1),Y + DEY + +Part of the loop (it macthes only partially) to fill-in a screen line with spaces - trivial, not copyrightable. diff --git a/strings/AD11D009108D11D0 b/strings/AD11D009108D11D0 new file mode 100644 index 00000000..7b25284f --- /dev/null +++ b/strings/AD11D009108D11D0 @@ -0,0 +1,3 @@ +LDA $D011 + ORA #$10 + STA $D011 + +Setting a bit in a documented I/O register (to turn on the screen) - trivial, not copyrightable. diff --git a/strings/AE48A5AF48 b/strings/AE48A5AF48 new file mode 100644 index 00000000..a754e049 --- /dev/null +++ b/strings/AE48A5AF48 @@ -0,0 +1,3 @@ +$AE + PHA + LDA $AF + PHA + +Part of a routine storing EAL 16-bit variable value to stack - trivial, not copyrightable. diff --git a/strings/AFA5C385C1A5C485C2 b/strings/AFA5C385C1A5C485C2 new file mode 100644 index 00000000..7ec2db32 --- /dev/null +++ b/strings/AFA5C385C1A5C485C2 @@ -0,0 +1,3 @@ +$AF + LDA $C3 + STA $C1 + LDA $C4 + STA $C2 + +Copyying one 16-bit zeropage variable to another. Trivial - not copyrightable. diff --git a/strings/B1B220D2FFC8C0 b/strings/B1B220D2FFC8C0 new file mode 100644 index 00000000..2b919186 --- /dev/null +++ b/strings/B1B220D2FFC8C0 @@ -0,0 +1,3 @@ +LDA ($B2),Y + JSR $FFD2 + INY + CPY (value does not match) + +Small part of loop indexed by .Y, outputing data via CHROUT - not creative, not copyrightable. diff --git a/strings/B50085C1 b/strings/B50085C1 new file mode 100644 index 00000000..31457717 --- /dev/null +++ b/strings/B50085C1 @@ -0,0 +1,3 @@ +LDA $00,X + STA $C1 + +Small part (match limited to 2 instructions) of a routine retrieving start address from the variable pointed by register - matching part is trivial, not copyrightable. diff --git a/strings/B50185C2 b/strings/B50185C2 new file mode 100644 index 00000000..ccad01a0 --- /dev/null +++ b/strings/B50185C2 @@ -0,0 +1,3 @@ +LDA $01,X + STA $C2 + +Small part (match limited to 2 instructions) of a routine retrieving start address from the variable pointed by register - matching part is trivial, not copyrightable. diff --git a/strings/B7D0034C b/strings/B7D0034C new file mode 100644 index 00000000..affc0015 --- /dev/null +++ b/strings/B7D0034C @@ -0,0 +1,3 @@ +$B7 + BNE (offset match) + JMP (address does not match) + +Instruction and some parts. Trivial, not copyrightable. diff --git a/strings/BB20D2FFC8 b/strings/BB20D2FFC8 new file mode 100644 index 00000000..d906f4e1 --- /dev/null +++ b/strings/BB20D2FFC8 @@ -0,0 +1,3 @@ +$BB + JSR $FFD2 + INY + +Call to well-known routine (CHROUT) within a loop indexed by .Y (onlyy a small part of the loop matches) - not creative, not copyrightable. diff --git a/strings/C8B1B285 b/strings/C8B1B285 new file mode 100644 index 00000000..f158c521 --- /dev/null +++ b/strings/C8B1B285 @@ -0,0 +1,3 @@ +INY + LDA ($B2),Y + STA (zeropage address does not match) + +Part of loop processing data pointed by a documented zero page variable (just 2 instructions fully match) - trivial, not copyrightable. diff --git a/strings/C8C015D0 b/strings/C8C015D0 new file mode 100644 index 00000000..b9eccdfc --- /dev/null +++ b/strings/C8C015D0 @@ -0,0 +1,3 @@ +INY + CPY #$15 + BNE (offset does not match) + +Loop condition (loop running to $15, indexed by .Y) - trivial, not copyyrightable. diff --git a/strings/C8D0F4A23C b/strings/C8D0F4A23C new file mode 100644 index 00000000..ca69ad0a --- /dev/null +++ b/strings/C8D0F4A23C @@ -0,0 +1,3 @@ +INY + BNE (offset matches) + LDX #$3C + +End of the loop indexed by .Y followed by loading a value into .X - too small piece of code to be creative, not copyrightable. diff --git a/strings/CAD0F660 b/strings/CAD0F660 new file mode 100644 index 00000000..003392c6 --- /dev/null +++ b/strings/CAD0F660 @@ -0,0 +1,3 @@ +DEX + BNE (offset matches) + RTS + +End of a loop indexed by .X register, counting down to 0 - similar code can be found in any non-trivial 6502 software. Not creative - not coprightable. diff --git a/strings/E5A9008D b/strings/E5A9008D new file mode 100644 index 00000000..6af77b2e --- /dev/null +++ b/strings/E5A9008D @@ -0,0 +1,3 @@ +$E5 + LDA #$00 + STA (address does not match) + +Instruction + some parts. Trivial, not copyrightable. diff --git a/strings/E6AED002E6AF b/strings/E6AED002E6AF new file mode 100644 index 00000000..c05bd490 --- /dev/null +++ b/strings/E6AED002E6AF @@ -0,0 +1,3 @@ +INC $AE + BNE (offset matches) + INC $AF + +Incrementing a 16-bit zeropage variable (not the hoole increment matches) - trivial, not copyrightable. diff --git a/strings/EAEAAD00DD b/strings/EAEAAD00DD new file mode 100644 index 00000000..94de0dc6 --- /dev/null +++ b/strings/EAEAAD00DD @@ -0,0 +1,4 @@ +NOP + NOP + LDA $DD00 + +Delayed reading of a documented I/O register - what's interesting, this was detected as a similarity between original IEC code +and our JiffyDOS protocol implementation (protocol, which is not supported by original ROM). Not creative - not copyrightable. diff --git a/strings/ED4C25FE4C b/strings/ED4C25FE4C new file mode 100644 index 00000000..a305a5c3 --- /dev/null +++ b/strings/ED4C25FE4C @@ -0,0 +1,3 @@ +$ED + JMP $FE25 + JMP (address does not match) + +Instruction (jump to a well-known address) + some parts. Trivial - not copyrightable. diff --git a/strings/EDAD00DD b/strings/EDAD00DD new file mode 100644 index 00000000..2a9418e9 --- /dev/null +++ b/strings/EDAD00DD @@ -0,0 +1,3 @@ +$ED + LDA $DD00 + +Instruction (reading documented I/O register) + some part. Trivial, not copyrightable. diff --git a/strings/EDAD00DD29 b/strings/EDAD00DD29 new file mode 100644 index 00000000..e22d5f1c --- /dev/null +++ b/strings/EDAD00DD29 @@ -0,0 +1,3 @@ +$ED + LDA $DD00 + AND (value does not match) + +Instruction (reading a documented I/O register) + some parts. Trivial, not copyrightable. diff --git a/strings/F0AD11D029EF8D11D0AD b/strings/F0AD11D029EF8D11D0AD new file mode 100644 index 00000000..7e16541f --- /dev/null +++ b/strings/F0AD11D029EF8D11D0AD @@ -0,0 +1,3 @@ +$F0 + LDA $D011 + AND #$EF + STA $D011 + LDA (address does not matc + +Clear bit in a documented I/O register - trivial, not copyrightable. diff --git a/strings/F3A5BA20 b/strings/F3A5BA20 new file mode 100644 index 00000000..e8d525e8 --- /dev/null +++ b/strings/F3A5BA20 @@ -0,0 +1,3 @@ +$F3 + LDA $BA + JSR (address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/F7C903F0 b/strings/F7C903F0 new file mode 100644 index 00000000..8849aa07 --- /dev/null +++ b/strings/F7C903F0 @@ -0,0 +1,3 @@ +$F7 + CMP #$03 + BEQ (offset does not match) + +Instruction and some parts - trivial, not copyrightable. diff --git a/strings/FF00000000 b/strings/FF00000000 new file mode 100644 index 00000000..f4672b03 --- /dev/null +++ b/strings/FF00000000 @@ -0,0 +1,3 @@ +$FF followed by multiple 0's + +Meaningless - results of both ROM sets having empty space. Not copyrightable. diff --git a/strings/FF0000000000 b/strings/FF0000000000 new file mode 100644 index 00000000..f4672b03 --- /dev/null +++ b/strings/FF0000000000 @@ -0,0 +1,3 @@ +$FF followed by multiple 0's + +Meaningless - results of both ROM sets having empty space. Not copyrightable. diff --git a/strings/FF586C00A0A2 b/strings/FF586C00A0A2 new file mode 100644 index 00000000..f545bc59 --- /dev/null +++ b/strings/FF586C00A0A2 @@ -0,0 +1,3 @@ +$FF + CLI + JMP ($A000) + LDX (value does not match) + +Part of the startup - matching part calls BASIC startup (via a well-known vector) with enabled interrupts. Trivial - not copyrightable. diff --git a/testsuite/testdisk.d64 b/testsuite/testdisk.d64 new file mode 100644 index 00000000..a455d2ee Binary files /dev/null and b/testsuite/testdisk.d64 differ diff --git a/testsuite/testtape-normal.tap b/testsuite/testtape-normal.tap new file mode 100644 index 00000000..be831cac Binary files /dev/null and b/testsuite/testtape-normal.tap differ diff --git a/testsuite/testtape-turbo.tap b/testsuite/testtape-turbo.tap new file mode 100644 index 00000000..eec41269 Binary files /dev/null and b/testsuite/testtape-turbo.tap differ