Merge pull request #36 from FeralChild64/master

DolphinDOS, tape normal
This commit is contained in:
gardners authored and GitHub committed 2019-12-30 09:12:15 +01:00
commit 2d2e979eef
119 files changed
+1921 -477

No files matched your search

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