diff --git a/.gitmodules b/.gitmodules
index a7fa85bb..9010ba90 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "3rdparty/zmac"]
path = 3rdparty/zmac
url = https://github.com/FeralChild64/zmac
+[submodule "3rdparty/z80exer"]
+ path = 3rdparty/z80exer
+ url = https://github.com/FeralChild64/z80exer
diff --git a/3rdparty/z80exer b/3rdparty/z80exer
new file mode 160000
index 00000000..8634cccd
--- /dev/null
+++ b/3rdparty/z80exer
@@ -0,0 +1 @@
+Subproject commit 8634cccdd362e030efebcdeec1aeb8b4f2ce9179
diff --git a/Makefile b/Makefile
index a03f3f39..bea33050 100644
--- a/Makefile
+++ b/Makefile
@@ -62,8 +62,11 @@ SRCDIR_KERNAL = $(SRCDIR_COMMON) \
SRCDIR_DOS_M65 = $(SRCDIR_COMMON) \
src/dos_m65 \
- # src/dos_m65/cmdrdos \
- src/dos_m65/sdcard
+ src/dos_m65/assets \
+ src/dos_m65/dev_floppy \
+ src/dos_m65/dev_ramdisk \
+ src/dos_m65/dev_sdcard \
+ src/dos_m65/utils
SRCDIR_MON_M65 = $(SRCDIR_COMMON) \
src/mon_m65
@@ -107,6 +110,7 @@ DIR_ZMAC = 3rdparty/zmac/src
DIR_ZMAC_TMP = build/,tmp_zmac
HDR_ZMAC = $(filter-out $(wildcard $(DIR_ZMAC)/_*.h),$(wildcard $(DIR_ZMAC)/*.h))
SRC_ZMAC = $(DIR_ZMAC)/mio.c $(DIR_ZMAC)/doc.c $(DIR_ZMAC)/zi80dis.cpp
+SRC_Z80TEST = 3rdparty/z80exer/cpm/zexdoc.src
GEN_ZMAC_C = $(DIR_ZMAC_TMP)/zmac.c
GEN_ZMAC_H = $(DIR_ZMAC_TMP)/doc.inl
@@ -209,6 +213,7 @@ TARGET_LIST_TST = $(TARGET_TST_B) $(TARGET_TST_K)
TARGET_LIST_U64 = $(TARGET_U64_B) $(TARGET_U64_K)
TARGET_LIST_U64CRT = $(TARGET_U64CRT_B) $(TARGET_U64CRT_K) $(TARGET_U64CRT_X)
+TARGET_Z80TEST = ./build/cpm/Z80TEST.COM
TARGET_LIST = $(TARGET_CHR_ORF) \
$(TARGET_LIST_CUS) \
@@ -289,7 +294,7 @@ $(ROM_CBM_BASIC):
# Rules - tools
-$(DIR_ACME) $(SRC_ACME) $(DIR_ZMAC) $(SRC_ZMAC):
+$(DIR_ACME) $(SRC_ACME) $(DIR_ZMAC) $(SRC_ZMAC) $(SRC_Z80TEST):
@echo
@echo Fetching 3rd party source code...
@git submodule init
@@ -390,7 +395,7 @@ $(DIR_M65)/kernal.seg_C $(DIR_M65)/KERNAL_C_combined.vs $(DIR_M65)/KERNAL_C_comb
$(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1_combined.vs $(DIR_M65)/KERNAL_1_combined.sym: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_KERNAL) $(CFG_M65) $(GEN_STR_M65) $(DIR_M65)/KERNAL_0_combined.sym
$(DIR_M65)/dos.seg_1 $(DIR_M65)/DOS_1_combined.vs $(DIR_M65)/DOS_1_combined.sym: \
- $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_DOS_M65) $(CFG_M65)
+ $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_DOS_M65) $(CFG_M65) $(DIR_M65)/KERNAL_0_combined.sym
$(DIR_M65)/mon.seg_1 $(DIR_M65)/MON_1_combined.vs $(DIR_M65)/MON_1_combined.sym: \
$(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(DEP_MON_M65) $(CFG_M65) $(DIR_M65)/KERNAL_0_combined.sym $(DIR_M65)/BASIC_1_combined.sym
$(DIR_M65)/zvm.seg_1 $(DIR_M65)/ZVM_1_combined.vs $(DIR_M65)/ZVM_1_combined.sym: \
@@ -881,8 +886,9 @@ testsimilarity: $(TOOL_SIMILARITY) $(DIR_GEN)/OUTx_x.BIN $(ROM_CBM_KERNAL) $(ROM
# Z80 part
#
+
.PHONY: cpm
-cpm: $(TOOL_ASSEMBLER_Z80)
+cpm: $(TOOL_ASSEMBLER_Z80) $(TARGET_Z80TEST)
$(DIR_ZMAC_TMP)/doc: $(SRC_ZMAC)
@mkdir -p $(DIR_ZMAC_TMP)
@@ -904,3 +910,11 @@ $(TOOL_ASSEMBLER_Z80): $(DIR_ZMAC) $(SRC_ZMAC) $(GEN_ZMAC_C) $(GEN_ZMAC_H) $(HDR
@echo Compiling tool $@ ...
@mkdir -p build/tools
@$(CC) -o $(TOOL_ASSEMBLER_Z80) $(SRC_ZMAC) $(GEN_ZMAC_C) -lm -w -I$(DIR_ZMAC) -I$(DIR_ZMAC_TMP)
+
+$(TARGET_Z80TEST) : $(TOOL_ASSEMBLER_Z80) $(SRC_Z80TEST)
+ @echo
+ @echo Compiling Z80 CPU tester ...
+ @mkdir -p build/cpm
+ @rm -f $(TARGET_Z80TEST).CIM $(TARGET_Z80TEST)
+ @$(TOOL_ASSEMBLER_Z80) -o $(TARGET_Z80TEST).CIM $(SRC_Z80TEST)
+ @mv -f $(TARGET_Z80TEST).CIM $(TARGET_Z80TEST)
diff --git a/STATUS.md b/STATUS.md
index c4f1f877..392ef05c 100644
--- a/STATUS.md
+++ b/STATUS.md
@@ -101,6 +101,7 @@ The following ROM features are currently missing:
| :----------------: | :------: | :------------------------------------------------: |
| standard | DONE | |
| JiffyDOS | PARTIAL | LOAD needs improvement for better performance |
+| ELoad v1 | NOT DONE | |
| DolphinDOS | DONE | |
| CIA burst mod | NOT DONE | |
| MEGA65 burst | NOT DONE | |
@@ -125,10 +126,11 @@ The following ROM features are currently missing:
-| Driver | Status | Remarks |
-| :----------------: | :------: | :-------------------------------------------------------------------------: |
-| internal floppy | NOT DONE | try to reuse https://github.com/commanderx16/x16-rom/tree/master/dos |
-| SD card access | NOT DONE | tryy to reuse https://github.com/commanderx16/x16-rom/tree/master/dos/fat32 |
+| Driver | Status | Remarks |
+| :----------------: | :------: | :------------------------------------------------: |
+| SD card | PARTIAL | work-in-progress, can already load files |
+| floppy drive | NOT DONE | |
+| ram disk | NOT DONE | |
diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom
index 72385907..a25f8f71 100644
Binary files a/bin/basic_generic.rom and b/bin/basic_generic.rom differ
diff --git a/bin/basic_generic_crt.rom b/bin/basic_generic_crt.rom
index 164de140..3bbe6e02 100644
Binary files a/bin/basic_generic_crt.rom and b/bin/basic_generic_crt.rom differ
diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom
index 1e141fc8..343bb505 100644
Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ
diff --git a/bin/extrom_generic_crt.crt b/bin/extrom_generic_crt.crt
index d8b319dc..71b735c7 100644
Binary files a/bin/extrom_generic_crt.crt and b/bin/extrom_generic_crt.crt differ
diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom
index 2a298fb7..69d5ba38 100644
Binary files a/bin/kernal_generic.rom and b/bin/kernal_generic.rom differ
diff --git a/bin/kernal_generic_crt.rom b/bin/kernal_generic_crt.rom
index 3afde4f6..c36887df 100644
Binary files a/bin/kernal_generic_crt.rom and b/bin/kernal_generic_crt.rom differ
diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom
index 75aa326e..88ab184e 100644
Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ
diff --git a/bin/mega65.rom b/bin/mega65.rom
index f8f628be..01106fb7 100644
Binary files a/bin/mega65.rom and b/bin/mega65.rom differ
diff --git a/bin/mega65_orfont.rom b/bin/mega65_orfont.rom
index 831695b3..8249e7c5 100644
Binary files a/bin/mega65_orfont.rom and b/bin/mega65_orfont.rom differ
diff --git a/doc/Development.md b/doc/Development.md
index a1b33f45..e0e458de 100644
--- a/doc/Development.md
+++ b/doc/Development.md
@@ -186,6 +186,8 @@ Last, but not least - the `#TAKE-HIGH` is intended to be used for BASIC routines
### MEGA65 computer-based DOS
+Both the internal DOS and all the IEC operations leave with CPU speed set to 1 MHz (in case of legacy compatibility mode) or 40 MHz (in case of native mode). Also the fast interrupts and badline emulation is set according to the mode.
+
TODO
### CPU-specific optimizations
diff --git a/src/,,config_mega65.s b/src/,,config_mega65.s
index dbf5f316..37bca28b 100644
--- a/src/,,config_mega65.s
+++ b/src/,,config_mega65.s
@@ -30,7 +30,6 @@
;; #CONFIG# IEC_DOLPHINDOS NO
;; #CONFIG# IEC_DOLPHINDOS_FAST NO
;; #CONFIG# IEC_JIFFYDOS NO ; fastloaders do not work on MEGA65 yet!
-;; #CONFIG# IEC_JIFFYDOS_BLANK NO
;; #CONFIG# IEC_BURST_M65 NO ; please keep disabled for now
@@ -66,7 +65,7 @@
;; #CONFIG# KEYCMD_HELP "LIST"
-;; #CONFIG# KEYCMD_F9 "REM F9"
+;; #CONFIG# KEYCMD_F9 "@20$"
;; #CONFIG# KEYCMD_F10 "\5FL"
;; #CONFIG# KEYCMD_F11 "COLORSET 128"
;; #CONFIG# KEYCMD_F12 "\5FHF"
@@ -91,9 +90,7 @@
; --- Built-in DOS configuration
-;; #CONFIG# CMDRDOS NO ; do not change, DOS is not implemented yet
-
-;; #CONFIG# UNIT_SDCARD 0 ; do not change, DOS is not implemented yet
+;; #CONFIG# UNIT_SDCARD 20 ; do not change, DOS is not implemented yet
;; #CONFIG# UNIT_FLOPPY 0 ; do not change, DOS is not implemented yet
;; #CONFIG# UNIT_RAMDISK 0 ; do not change, DOS is not implemented yet
diff --git a/src/aliases/,aliases_config.s b/src/aliases/,aliases_config.s
index 524eaabc..eaffde27 100644
--- a/src/aliases/,aliases_config.s
+++ b/src/aliases/,aliases_config.s
@@ -112,6 +112,7 @@
!ifdef CONFIG_MB_MEGA65 {
!ifdef CONFIG_IEC_BURST_CIA1 { !error "Do not use CONFIG_IEC_BURST_CIA1 options for MEGA65 motherboard, CONFIG_IEC_BURST_M65 instead" }
!ifdef CONFIG_IEC_BURST_CIA2 { !error "Do not use CONFIG_IEC_BURST_CIA2 options for MEGA65 motherboard, CONFIG_IEC_BURST_M65 instead" }
+ !ifdef IEC_JIFFYDOS_BLANK { !error "Do not use IEC_JIFFYDOS_BLANK option for MEGA65 motherboard, it is not needed" }
!ifndef CONFIG_DOS_WEDGE { !error "MEGA65 build requires CONFIG_DOS_WEDGE" }
}
!ifndef CONFIG_MB_MEGA65 {
@@ -247,12 +248,6 @@
!ifndef CONFIG_VIC_PALETTE { !error "CONFIG_VIC_PALETTE not specified" }
}
-; Check that internal DOS configuration is correct
-
-!ifdef CONFIG_CMDRDOS { !ifndef CONFIG_MB_M65 {
- !error "CONFIG_CMDRDOS requires CONFIG_MB_M65"
-} }
-
; Check that startup banner configuration is correct
@@ -424,12 +419,6 @@
-; Handle non-LGPL3 code
-
-!ifdef CONFIG_CMDRDOS { !set HAS_NOLGPL3_WARN = 1 }
-
-
-
; Determine if we need space-savings in BASIC code
!ifndef CONFIG_MB_M65 { !ifndef ROM_LAYOUT_CRT {
diff --git a/src/aliases/,aliases_hardware_m65.s b/src/aliases/,aliases_hardware_m65.s
index bfc5e178..4c5126e4 100644
--- a/src/aliases/,aliases_hardware_m65.s
+++ b/src/aliases/,aliases_hardware_m65.s
@@ -48,6 +48,7 @@
!addr SD_CTL = $D680
!addr SD_ADDR = $D681 ; 4 bytes
+ !addr SD_BUFCTL = $D689
!addr SD_ERRCODE = $D6DA
; SD card sector buffer, $FFFD6E00
@@ -72,6 +73,11 @@
!addr MISC_BOARDID = $D629 ; board identification byte
!addr MISC_EMU = $D710 ; to enable badlines and slow interrupts
+ ; Hypervisor traps
+
+ !addr HTRAP00 = $D640
+
+
; SID offsets
!set __SID_R1_OFFSET = $00 ; right SID 1, $D400
diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s
index cdce7464..ed03d9c9 100644
--- a/src/aliases/,aliases_ram_lowmem.s
+++ b/src/aliases/,aliases_ram_lowmem.s
@@ -291,7 +291,7 @@
!set IEC_BURST = 3
}
!ifdef CONFIG_MB_M65 {
- !set IEC_ROMDOS = 4
+ !set IEC_CBDOS = 4
}
diff --git a/src/basic/,imports.s b/src/basic/,imports.s
index 767bf70a..d3626678 100644
--- a/src/basic/,imports.s
+++ b/src/basic/,imports.s
@@ -50,6 +50,8 @@
;; #ALIAS# m65_shadow_BZP = KERNAL_0.m65_shadow_BZP
;; #ALIAS# proxy_M1_IO_end = KERNAL_0.proxy_M1_IO_end
+;; #ALIAS# m65dos_unitnum = KERNAL_0.m65dos_unitnum
+
;
; Ultimate 64 specific parts
;
diff --git a/src/basic/assets/str_nolgpl3_warn.s b/src/basic/assets/str_nolgpl3_warn.s
deleted file mode 100644
index 88bf8fa9..00000000
--- a/src/basic/assets/str_nolgpl3_warn.s
+++ /dev/null
@@ -1,15 +0,0 @@
-;; #LAYOUT# M65 BASIC_1 #TAKE
-;; #LAYOUT# * * #IGNORE
-
-
-
-!ifdef HAS_NOLGPL3_WARN {
-
-str_nonlgpl3_warn:
-
- !byte $0D, $0D, $0D, $0D
- !pet "build contains non-lgpl3 code"
- !byte $0D
- !pet " *** do not distribute ***"
- !byte $0D, $0D, $00
-}
diff --git a/src/basic/basic_commands_04/cmd_sysinfo.s b/src/basic/basic_commands_04/cmd_sysinfo.s
index 27f5c5b3..dfed12c2 100644
--- a/src/basic/basic_commands_04/cmd_sysinfo.s
+++ b/src/basic/basic_commands_04/cmd_sysinfo.s
@@ -106,12 +106,46 @@ print_sysinfo_video:
@5:
jsr print_packed_misc_str
- ; Print build featires information
+ ; Print build features information
ldx #IDX__STR_SI_FEATURES
- jmp print_packed_misc_str
+ jsr print_packed_misc_str
+ ; Print SD CARD unit ID
+ lda #$00
+ jsr cmd_sysinfo_print_dev
+
+ ldx #IDX__STR_DOS_FD
+ jsr print_packed_misc_str
+
+ ; Print floppy unit ID
+
+ lda #$01
+ jsr cmd_sysinfo_print_dev
+
+ ; Print ram disk unit ID
+
+ ldx #IDX__STR_DOS_RD
+ jsr print_packed_misc_str
+
+ lda #$02
+ jsr cmd_sysinfo_print_dev
+
+ jmp print_return
+
+cmd_sysinfo_print_dev:
+
+ jsr m65dos_unitnum
+ bcs @nounit
+ tax
+ lda #$00
+ jmp print_integer
+
+@nounit:
+
+ lda #'-'
+ jmp JCHROUT
cmd_sysinfo_hw_ids:
diff --git a/src/basic/board_m65/mega65_imports.s b/src/basic/board_m65/mega65_imports.s
index 999391b6..613df99e 100644
--- a/src/basic/board_m65/mega65_imports.s
+++ b/src/basic/board_m65/mega65_imports.s
@@ -46,3 +46,4 @@
;; #ALIAS# fetch_character_skip_spaces = BASIC_0.proxy_B1_fetch_character_skip_spaces
;; #ALIAS# fetch_uint8 = BASIC_0.proxy_B1_fetch_uint8
;; #ALIAS# shell_main_loop = BASIC_0.proxy_B1_shell_main_loop
+;; #ALIAS# m65dos_unitnum = BASIC_0.proxy_B1_m65dos_unitnum
diff --git a/src/basic/board_m65/mega65_proxies.s b/src/basic/board_m65/mega65_proxies.s
index a218be22..953e9658 100644
--- a/src/basic/board_m65/mega65_proxies.s
+++ b/src/basic/board_m65/mega65_proxies.s
@@ -156,3 +156,9 @@ proxy_M1_print_kernal_error:
jsr do_error_print_only
jmp proxy_M1_IO_end
}
+
+proxy_B1_m65dos_unitnum:
+
+ jsr map_NORMAL
+ jsr m65dos_unitnum
+ bra proxy_B1_end_2
diff --git a/src/basic/init/initmsg_m65.s b/src/basic/init/initmsg_m65.s
index e36672d7..72c1f2c0 100644
--- a/src/basic/init/initmsg_m65.s
+++ b/src/basic/init/initmsg_m65.s
@@ -31,11 +31,11 @@ INITMSG_native:
; Native mode
- ldx #48
+ ldx #44
ldy #0
jsr M65_SETWIN_XY
- ldx #32
+ ldx #36
ldy #9
jsr M65_SETWIN_WH
@@ -64,18 +64,9 @@ INITMSG_native:
jsr initmsg_bytes_free
-!ifdef HAS_NOLGPL3_WARN {
-
- lda #str_nonlgpl3_warn
- jmp STROUT
-
-} else {
-
ldx #$09
ldy #$00
jmp plot_set
-}
INITMSG_main_banner:
diff --git a/src/basic/init/initmsg_real.s b/src/basic/init/initmsg_real.s
index d8a21c32..01384071 100644
--- a/src/basic/init/initmsg_real.s
+++ b/src/basic/init/initmsg_real.s
@@ -115,5 +115,3 @@ initmsg_real:
}
}
-
-!ifdef HAS_NOLGPL3_WARN { !error "HAS_NOLGPL3_WARN not implemented" }
diff --git a/src/dos_m65/,aliases_dos.s b/src/dos_m65/,aliases_dos.s
index 9a00472e..8a11c5f6 100644
--- a/src/dos_m65/,aliases_dos.s
+++ b/src/dos_m65/,aliases_dos.s
@@ -3,40 +3,132 @@
;
; NOTES:
-; - DOS zeropage is mirrored at $8000
; - starting from $8000, 16KB RAM is available (starting from $10000 in C65 address space)
; - additional 16KB RAM is reserved for DOS too ($14000-$17FFF), and can be banked-in if needed
-
;
- ; Page 0
+ ; Temporary storage locations
;
- !addr MAGICSTR = $00 ; magic string; if not matching, DOS considered non-functional
+ !addr FS_HVSR_DIRENT = $1000
+
+
+ ;
+ ; Page start+0
+ ;
+
+ !addr MAGICSTR = $8000 ; magic string; if not matching, DOS considered non-functional
+
+ ; Register storage
+
+ !addr REG_A = $8005
+ !addr REG_X = $8006
+ !addr REG_Y = $8007
+ !addr REG_Z = $8008
+
+ ; Reserved: $8009 - $800C
; General DOS configuration
- !addr UNIT_SDCARD = $05
- !addr UNIT_FLOPPY = $06
- !addr UNIT_RAMDISK = $07
+ !addr UNIT_SDCARD = $800D ; unit number for device, 0 = none
+ !addr UNIT_FLOPPY = $800E ; as above
+ !addr UNIT_RAMDISK = $800F ; as above
- ; SD/SDHC card variables
+ ; General DOS status
- !addr CARD_INIT_DONE = $08 ; $80 - init done, $00 - init not done
- !addr CARD_IS_SDHC = $09 ; $00 = SD, $80 = SDHC
- !addr CARD_SIZE = $0A ; 4 bytes
- !addr CARD_SECNUM = $0E ; 4 bytes - sector number
+ !addr IDX1_LISTENER = $8010 ; listener idx, >=$80 = none
+ !addr IDX2_LISTENER = $8011 ; listener idx * 2, >=$80 = none - for calling routines via vector table
+ !addr IDX1_TALKER = $8012 ; talker idx, >=$80 = none
+ !addr IDX2_TALKER = $8013 ; talker idx * 2, >=$80 = none - for calling routines via vector table
- !addr CARD_TMP_STEP = $12 ; 4 bytes
- !addr CARD_TMP_RETRIES = $16 ; 1 byte
+ ; Helper subroutines to fetch data
- !addr CARD_BUFPNT1 = $17 ; 4 bytes - pointer to hardware sector buffer XXX replace copy routines with DMAgic
- !addr CARD_BUFPNT2 = $1B ; 4 bytes - as above, but points to the 2nd page of the hardware buffer
+ !addr code_LDA_nnnn_Y = $8014 ; - LDA nnnn, Y instruction
+ !addr par_LDA_nnnn_Y = $8015 ; - 2 bytes; address in buffer, ram disk
+ !addr code_RTS_04 = $8017 ; - RTS instruction
+ ; Parameters for utilities/helkpers
+
+ !addr PAR_TRACK = $8018 ; track number for status/error
+ !addr PAR_SECTOR = $8019 ; sector number for status/error
+
+ !addr PAR_FSIZE_BYTES = $801A ; 4 bytes - file size in bytes
+ !addr PAR_FSIZE_BLOCKS = $801E ; 2 bytes - file size in blocks
+
+ !addr PAR_FTYPE = $8020 ; bits 0-5 - type, bits 6-7 - protected, closed
+ !addr PAR_FNAME = $8021 ; 16 bytes - filename, filled with $A0
+ !addr PAR_FPATTERN = $8031 ; 16 bytes - pattern to match, filled with $A0
+
+ ; Various temporary data
+
+ !addr XX_DIR_PHASE = $8041 ; directory output phase, values deponds on device driver, but 0 = not reading
+ !addr SD_DIR_PHASE = $8041 ; - SD card
+ !addr FD_DIR_PHASE = $8042 ; - floppy
+ !addr RD_DIR_PHASE = $8043 ; - ram disk
+
+ ; Free space: $8044-$8063
+
+ !addr SD_ACPTR_helper = $8052 ; subroutine in RAM to read a byte
+ !addr code_LDA_01 = $8052 ; - LDA instruction
+ !addr SD_ACPTR_PTR = $8053 ; - 2 bytes; address in buffer, SD card
+ !addr code_RTS_01 = $8055 ; - RTS instruction
+
+ !addr FD_ACPTR_helper = $8056 ; subroutine in RAM to read a byte
+ !addr code_LDA_02 = $8056 ; - LDA instruction
+ !addr FD_ACPTR_PTR = $8057 ; - 2 bytes; address in buffer, floppy
+ !addr code_RTS_02 = $8059 ; - RTS instruction
+
+ !addr RD_ACPTR_helper = $805A ; subroutine in RAM to read a byte
+ !addr code_LDA_03 = $805A ; - LDA instruction
+ !addr RD_ACPTR_PTR = $805B ; - 2 bytes; address in buffer, ram disk
+ !addr code_RTS_03 = $805D ; - RTS instruction
+
+ !addr XX_ACPTR_LEN = $805E ; 2 bytes - length of data left for ACPTR
+ !addr SD_ACPTR_LEN = $805E ; - SD card
+ !addr FD_ACPTR_LEN = $8060 ; - floppy
+ !addr RD_ACPTR_LEN = $8062 ; - ram disk
+
+ !addr XX_MODE = $8064 ; current mode (0 = none, 1 = receiving command/file name)
+ !addr SD_MODE = $8064 ; - SD card
+ !addr FD_MODE = $8065 ; - floppy
+ !addr RD_MODE = $8066 ; - ram disk
+
+ !addr XX_CHANNEL = $8067 ; current channel
+ !addr SD_CHANNEL = $8067 ; - SD card
+ !addr FD_CHANNEL = $8068 ; - floppy
+ !addr RD_CHANNEL = $8069 ; - ram disk
+
+ !addr XX_CMDFN_IDX = $806A ; index byte for storing file name/command
+ !addr SD_CMDFN_IDX = $806A ; - SD card
+ !addr FD_CMDFN_IDX = $806B ; - floppy
+ !addr RD_CMDFN_IDX = $806C ; - ram disk
+
+ !addr XX_STATUS_IDX = $806D ; index byte for reading status
+ !addr SD_STATUS_IDX = $806D ; - SD card
+ !addr FD_STATUS_IDX = $806E ; - floppy
+ !addr RD_STATUS_IDX = $806F ; - ram disk
+
+ !addr XX_STATUS_STR = $8070
+ !addr SD_STATUS_STR = $8070 ; status string for SD card, terminated by 0
+ !addr FD_STATUS_STR = $80A0 ; status string for floppy drive, terminated by 0
+ !addr RD_STATUS_STR = $80D0 ; status string for ram disk, terminated by 0
;
- ; High memory
+ ; Further pages
;
- !addr CARD_BUF = $8100 ; 512 bytes, up to $82FF - buffer for reading/writing data
+ !addr SD_CMDFN_BUF = $8100 ; buffer for command and/or file name, 128 bytes, SD card
+ !addr FD_CMDFN_BUF = $8180 ; buffer for command and/or file name, 128 bytes, floppy
+ !addr RD_CMDFN_BUF = $8200 ; buffer for command and/or file name, 128 bytes, ram disk
+
+ !addr XX_DIR_ENTRY = $8280 ; directory entry in BASIC format
+ !addr SD_DIR_ENTRY = $8280 ; - SD card
+ !addr FD_DIR_ENTRY = $82B0 ; - floppy
+ !addr RD_DIR_ENTRY = $82E0 ; - ram disk
+
+ !addr SD_MEMSHADOW = $8310 ; 256 byte buffer for preserving original memory content
+ !addr SD_FILEBUF = $8410 ; 512 byte buffer for file reading
+
+ !addr SD_DESC = $8610 ; current file descriptor
+
diff --git a/src/dos_m65/4020.dos_vectable.s b/src/dos_m65/4020.dos_vectable.s
index 63d31009..fb940b73 100644
--- a/src/dos_m65/4020.dos_vectable.s
+++ b/src/dos_m65/4020.dos_vectable.s
@@ -2,13 +2,14 @@
; A vector table to integrate DOS with the MEGA65 Kernal
!word dos_INIT
-!word dos_CHKUNIT
-!word dos_SETUNIT
-!word dos_ACPTR
-!word dos_CIOUT
-!word dos_LISTEN
-!word dos_SECOND
-!word dos_TALK
-!word dos_TKSA
-!word dos_UNTLK
-!word dos_UNLSN
+!word dos_UNITCHK
+!word dos_UNITSET
+!word dos_UNITNUM
+!word msg_ACPTR
+!word msg_CIOUT
+!word msg_LISTEN
+!word msg_SECOND
+!word msg_TALK
+!word msg_TKSA
+!word msg_UNTLK
+!word msg_UNLSN
diff --git a/src/dos_m65/dos_magicstr.s b/src/dos_m65/assets/dos_magicstr.s
similarity index 100%
rename from src/dos_m65/dos_magicstr.s
rename to src/dos_m65/assets/dos_magicstr.s
diff --git a/src/dos_m65/assets/dos_parts_dir.s b/src/dos_m65/assets/dos_parts_dir.s
new file mode 100644
index 00000000..a81e9e89
--- /dev/null
+++ b/src/dos_m65/assets/dos_parts_dir.s
@@ -0,0 +1,62 @@
+
+;
+; Data used to generate directory in CBM BASIC format
+;
+
+dir_hdr: ; 32 bytes - header
+
+ !byte $01, $08 ; program location
+ !byte $01, $01 ; link to the next line - dummy, will be regenerated by BASIC
+ !byte $00, $00 ; line number 0
+ !byte $12, $22 ; reverse mode, quote
+ !pet " " ; space for disk/directory name
+ !byte $22, $20 ; quote, space
+ !pet "00 2a" ; default ID, disk format
+ !byte $00 ; end of the line
+
+dir_hdr_sd: ; 32 bytes - header
+
+ !byte $01, $08 ; program location
+ !byte $01, $01 ; link to the next line - dummy, will be regenerated by BASIC
+ !byte $00, $00 ; line number 0
+ !byte $12, $22 ; reverse mode, quote
+ !pet "sd card " ; space for disk/directory name
+ !byte $22, $20 ; quote, space
+ !pet "fat32" ; filesystem
+ !byte $00 ; end of the line
+
+dir_end: ; 19 bytes
+
+ !byte $01, $01 ; link to the next line - dummy, will be regenerated by BASIC
+ !byte $00, $00 ; line number 0 (blocks available)
+ !pet "blocks free."
+ !byte $00, $00, $00 ; end of the line, end of program marker
+
+; File types / extensions
+
+dir_types:
+
+ !pet "seq", $00 ; SEQ
+ !pet "prg", $00 ; PRG
+ !pet "usr", $00 ; USR
+ !pet "rel", $00 ; REL
+ !pet "dir", $00 ; directory
+
+; File types below are not mandatory
+
+ !pet "tap", $00 ; tape image
+ !pet "d67", $00 ; CBM 2040 (DOS 1) - disk image
+ !pet "d64", $00 ; CBM 1541 / 2031 / 3040 / 4040 - disk image
+ !pet "d71", $00 ; CBM 1571 - disk image
+ !pet "d81", $00 ; CBM 1581 - disk image
+ !pet "d80", $00 ; CBM 8050 - disk image
+ !pet "d81", $00 ; CBM 8250 / 1001 - disk image
+ !pet "d90", $00 ; CBM D9060 / D9090 - hard disk image
+ !pet "d1m", $00 ; CMD FD 2000 / 4000 - disk image (DD)
+ !pet "d2m", $00 ; CMD FD 2000 / 4000 - disk image (HD)
+ !pet "d4m", $00 ; CMD FD 4000 - disk image (ED)
+ !pet "dhd", $00 ; CMD HD - hard disk image
+ !pet "rom", $00 ; rom image
+ !pet "m65", $00 ; MEGA65 utility
+
+dir_types__end:
diff --git a/src/dos_m65/assets/dos_status_strings.s b/src/dos_m65/assets/dos_status_strings.s
new file mode 100644
index 00000000..8c89421e
--- /dev/null
+++ b/src/dos_m65/assets/dos_status_strings.s
@@ -0,0 +1,184 @@
+
+;
+; DOS error codes and strings
+;
+
+
+; XXX get rid of unnecessary error messages
+
+
+dos_sts_init_sdcard:
+
+ !pet "73,m65 dos sd card,00,00", 0
+
+dos_sts_init_floppy:
+
+ !pet "73,m65 dos floppy,00,00", 0
+
+dos_sts_init_ramdisk:
+
+ !pet "73,m65 dos ram disk,00,00", 0
+
+
+; List compiled from various manuals (CBM 1571, CBM 1581, CMD FD4000, MSD Super Disk, IDE64)
+
+dos_sts_00: ; not an error
+
+ !pet " ok", 0
+
+dos_sts_01: ; not an error
+
+ !pet "files scratched", 0
+
+dos_sts_02: ; not an error
+
+ !pet "partition selected", 0
+
+dos_sts_20: ; header not found
+dos_sts_21: ; no data addres mark
+dos_sts_22: ; block not found
+dos_sts_23: ; data error
+dos_sts_27: ; header error
+
+ !pet "read error", 0
+
+dos_sts_25:
+
+ !pet "write error", 0
+
+dos_sts_26:
+
+ !pet "write protect on", 0
+
+dos_sts_29:
+
+ !pet "disk changed", 0
+
+dos_sts_30: ; invalid characters in command
+dos_sts_31: ; unrecognized command
+dos_sts_32: ; command too long
+dos_sts_33: ; illegal file name
+dos_sts_34: ; missing file name
+
+ !pet "syntax error", 0
+
+dos_sts_39:
+
+ !pet "file not found", 0
+
+dos_sts_49: ; disk formatted, but format not supported
+
+ !pet "invalid format", 0
+
+dos_sts_50:
+
+ !pet "record not present", 0
+
+dos_sts_51:
+
+ !pet "overflow in record", 0
+
+dos_sts_52:
+
+ !pet "file too large", 0
+
+dos_sts_60:
+
+ !pet "write file open", 0
+
+dos_sts_61:
+
+ !pet "file not open", 0
+
+dos_sts_62:
+
+ !pet "file not found", 0
+
+dos_sts_63:
+
+ !pet "file exists", 0
+
+dos_sts_64:
+
+ !pet "file type mismatch", 0
+
+dos_sts_65:
+
+ !pet "no block", 0
+
+dos_sts_66:
+
+ !pet "illegal track and sector", 0
+
+dos_sts_67:
+
+ !pet "illegal system t or s", 0
+
+dos_sts_70:
+
+ !pet "no channel", 0
+
+dos_sts_71:
+
+ !pet "directory error", 0
+
+dos_sts_72:
+
+ !pet "partition full", 0
+
+dos_sts_73:
+
+ !pet "dos mismatch", 0
+
+dos_sts_74:
+
+ !pet "drive not ready", 0
+
+dos_sts_75:
+
+ !pet "format error", 0
+
+dos_sts_76:
+
+ !pet "controller error", 0
+
+dos_sts_77:
+
+ !pet "selected partition illegal", 0
+
+dos_sts_78:
+
+ !pet "system error", 0
+
+dos_sts_79: ; SD2IEC compatible
+
+ !pet "image invalid", 0
+
+dos_sts_XX: ; Open ROMs specific - unspecified error
+
+ !pet "internal error", 0
+
+
+dos_sts_tab_lo:
+
+ !byte dos_sts_00, >dos_sts_01, >dos_sts_02, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX
+ !byte >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX
+ !byte >dos_sts_20, >dos_sts_21, >dos_sts_22, >dos_sts_23, >dos_sts_XX, >dos_sts_25, >dos_sts_26, >dos_sts_27, >dos_sts_XX, >dos_sts_29
+ !byte >dos_sts_30, >dos_sts_31, >dos_sts_32, >dos_sts_33, >dos_sts_34, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_39
+ !byte >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_49
+ !byte >dos_sts_50, >dos_sts_51, >dos_sts_52, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX, >dos_sts_XX
+ !byte >dos_sts_60, >dos_sts_61, >dos_sts_62, >dos_sts_63, >dos_sts_64, >dos_sts_65, >dos_sts_66, >dos_sts_67, >dos_sts_XX, >dos_sts_XX
+ !byte >dos_sts_70, >dos_sts_71, >dos_sts_72, >dos_sts_73, >dos_sts_74, >dos_sts_75, >dos_sts_76, >dos_sts_77, >dos_sts_78, >dos_sts_79
+ !byte >dos_sts_XX
diff --git a/src/dos_m65/cmdrdos/,check_nonlgpl3.s b/src/dos_m65/cmdrdos/,check_nonlgpl3.s
deleted file mode 100644
index a5e16f82..00000000
--- a/src/dos_m65/cmdrdos/,check_nonlgpl3.s
+++ /dev/null
@@ -1,4 +0,0 @@
-
-!ifndef HAS_NOLGPL3_WARN {
- !error "No LGPL3 incompatible warning issued"
-}
diff --git a/src/dos_m65/dev_floppy/dev_fd_cmd_close.s b/src/dos_m65/dev_floppy/dev_fd_cmd_close.s
new file mode 100644
index 00000000..cf2b6b6f
--- /dev/null
+++ b/src/dos_m65/dev_floppy/dev_fd_cmd_close.s
@@ -0,0 +1,11 @@
+
+;
+; Close currently opened file
+;
+
+
+dev_fd_cmd_CLOSE:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_SEC
diff --git a/src/dos_m65/dev_floppy/dev_fd_cmd_open.s b/src/dos_m65/dev_floppy/dev_fd_cmd_open.s
new file mode 100644
index 00000000..8029650e
--- /dev/null
+++ b/src/dos_m65/dev_floppy/dev_fd_cmd_open.s
@@ -0,0 +1,17 @@
+
+;
+; Open file for reading
+;
+
+
+dev_fd_cmd_OPEN:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_SEC
+
+dev_fd_cmd_OPEN_EOI:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_CLC
diff --git a/src/dos_m65/dev_floppy/dev_fd_cmd_read.s b/src/dos_m65/dev_floppy/dev_fd_cmd_read.s
new file mode 100644
index 00000000..1ef268af
--- /dev/null
+++ b/src/dos_m65/dev_floppy/dev_fd_cmd_read.s
@@ -0,0 +1,12 @@
+
+;
+; Read more data into the buffer
+;
+
+
+dev_fd_cmd_READ:
+
+ ; XXX provide implementation
+
+ sec ; mark EOI
+ rts
diff --git a/src/dos_m65/dev_floppy/dev_fd_init.s b/src/dos_m65/dev_floppy/dev_fd_init.s
new file mode 100644
index 00000000..501bcc61
--- /dev/null
+++ b/src/dos_m65/dev_floppy/dev_fd_init.s
@@ -0,0 +1,28 @@
+
+;
+; Initializes DOS part of floppy controller
+;
+
+
+dev_fd_init:
+
+ ; Copy status string
+
+ ldx #$00
+ stx FD_STATUS_IDX
+ stx FD_CMDFN_IDX
+ stx FD_MODE
+ stx FD_ACPTR_LEN+0
+ stx FD_ACPTR_LEN+1
+ stx FD_ACPTR_PTR+0
+ stx FD_ACPTR_PTR+1
+ dex
+@1:
+ inx
+ lda dos_sts_init_floppy,x
+ sta FD_STATUS_STR,x
+ bne @1
+
+ ; End of initialization
+
+ rts
diff --git a/src/dos_m65/dev_ramdisk/dev_rd_cmd_close.s b/src/dos_m65/dev_ramdisk/dev_rd_cmd_close.s
new file mode 100644
index 00000000..87575b81
--- /dev/null
+++ b/src/dos_m65/dev_ramdisk/dev_rd_cmd_close.s
@@ -0,0 +1,11 @@
+
+;
+; Close currently opened file
+;
+
+
+dev_rd_cmd_CLOSE:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_SEC
diff --git a/src/dos_m65/dev_ramdisk/dev_rd_cmd_open.s b/src/dos_m65/dev_ramdisk/dev_rd_cmd_open.s
new file mode 100644
index 00000000..4e2b436e
--- /dev/null
+++ b/src/dos_m65/dev_ramdisk/dev_rd_cmd_open.s
@@ -0,0 +1,17 @@
+
+;
+; Open file for reading
+;
+
+
+dev_rd_cmd_OPEN:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_SEC
+
+dev_rd_cmd_OPEN_EOI:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_CLC
diff --git a/src/dos_m65/dev_ramdisk/dev_rd_cmd_read.s b/src/dos_m65/dev_ramdisk/dev_rd_cmd_read.s
new file mode 100644
index 00000000..36a95300
--- /dev/null
+++ b/src/dos_m65/dev_ramdisk/dev_rd_cmd_read.s
@@ -0,0 +1,12 @@
+
+;
+; Read more data into the buffer
+;
+
+
+dev_rd_cmd_READ:
+
+ ; XXX provide implementation
+
+ sec ; mark EOI
+ rts
diff --git a/src/dos_m65/dev_ramdisk/dev_rd_init.s b/src/dos_m65/dev_ramdisk/dev_rd_init.s
new file mode 100644
index 00000000..e7be8d2c
--- /dev/null
+++ b/src/dos_m65/dev_ramdisk/dev_rd_init.s
@@ -0,0 +1,28 @@
+
+;
+; Initializes DOS part of ram disk
+;
+
+
+dev_rd_init:
+
+ ; Copy status string
+
+ ldx #$00
+ stx RD_STATUS_IDX
+ stx RD_CMDFN_IDX
+ stx RD_MODE
+ stx RD_ACPTR_LEN+0
+ stx RD_ACPTR_LEN+1
+ stx RD_ACPTR_PTR+0
+ stx RD_ACPTR_PTR+1
+ dex
+@1:
+ inx
+ lda dos_sts_init_ramdisk,x
+ sta RD_STATUS_STR,x
+ bne @1
+
+ ; End of initialization
+
+ rts
diff --git a/src/dos_m65/dev_sdcard/dev_sd_cmd_close.s b/src/dos_m65/dev_sdcard/dev_sd_cmd_close.s
new file mode 100644
index 00000000..9d0c23da
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/dev_sd_cmd_close.s
@@ -0,0 +1,11 @@
+
+;
+; Close currently opened file
+;
+
+
+dev_sd_cmd_CLOSE:
+
+ ; XXX provide implementation
+
+ jmp dos_EXIT_CLC
diff --git a/src/dos_m65/dev_sdcard/dev_sd_cmd_open.s b/src/dos_m65/dev_sdcard/dev_sd_cmd_open.s
new file mode 100644
index 00000000..17a34318
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/dev_sd_cmd_open.s
@@ -0,0 +1,73 @@
+
+;
+; Open file for reading
+;
+
+
+dev_sd_cmd_OPEN:
+
+ lda #$01 ; mode: receive command or file name
+ sta SD_MODE
+
+ jmp dos_EXIT_CLC
+
+dev_sd_cmd_OPEN_EOI:
+
+ ; XXX this dispatcher is temporary
+
+ ; Erase filter pattern XXX this should be moved to common part
+
+ ldy #$0F
+ lda #$A0
+@lp1:
+ sta PAR_FPATTERN, y
+ dey
+ bpl @lp1
+
+ ; XXX add support for second card
+
+ lda SD_CMDFN_BUF
+ cmp #'$'
+ beq dev_sd_cmd_OPEN_dir
+
+ ; FALLTROUGH
+
+dev_sd_cmd_OPEN_file:
+
+ ; Copy the filter from command XXX this should be moved to common part and deduplicated with directory opening
+
+ ldy #$00
+@lp1:
+ lda SD_CMDFN_BUF, y
+ cmp #$A0
+ beq @lp1_end
+ sta PAR_FPATTERN, y
+ iny
+ cpy #$10
+ bne @lp1
+
+@lp1_end:
+
+ jmp fs_hvsr_read_file_open
+
+
+dev_sd_cmd_OPEN_dir:
+
+ lda #$02 ; mode: read directory
+ sta SD_MODE
+
+ ; Copy the filter from command XXX this should be moved to common part and deduplicated with file opening
+
+ ldy #$00
+@lp1:
+ lda SD_CMDFN_BUF+1, y
+ cmp #$A0
+ beq @lp1_end
+ sta PAR_FPATTERN, y
+ iny
+ cpy #$10
+ bne @lp1
+
+@lp1_end:
+
+ jmp fs_hvsr_read_dir_open
diff --git a/src/dos_m65/dev_sdcard/dev_sd_cmd_read.s b/src/dos_m65/dev_sdcard/dev_sd_cmd_read.s
new file mode 100644
index 00000000..9852d5b0
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/dev_sd_cmd_read.s
@@ -0,0 +1,20 @@
+
+;
+; Read more data into the buffer
+;
+
+
+dev_sd_cmd_READ:
+
+ lda SD_MODE
+ cmp #$03
+ +beq fs_hvsr_read_file
+
+ lda SD_DIR_PHASE
+ cmp #$01
+ +beq fs_hvsr_read_dir
+ cmp #$02
+ +beq fs_hvsr_read_dir_blocksfree
+
+ sec ; mark EOI
+ rts
diff --git a/src/dos_m65/dev_sdcard/dev_sd_init.s b/src/dos_m65/dev_sdcard/dev_sd_init.s
new file mode 100644
index 00000000..526e5d3a
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/dev_sd_init.s
@@ -0,0 +1,39 @@
+
+;
+; Initializes DOS part of SD card
+;
+
+
+dev_sd_init:
+
+ ; Copy initial status string
+
+ ldx #$00
+ stx SD_STATUS_IDX
+ stx SD_CMDFN_IDX
+ stx SD_MODE
+ stx SD_ACPTR_LEN+0
+ stx SD_ACPTR_LEN+1
+ stx SD_ACPTR_PTR+0
+ stx SD_ACPTR_PTR+1
+ stx SD_DIR_PHASE
+ dex
+@1:
+ inx
+ lda dos_sts_init_sdcard,x
+ sta SD_STATUS_STR,x
+ bne @1
+
+ ; Close all the files in the hypervisor, go to root directory
+
+ lda #$22 ; dos_closeall
+ sta HTRAP00
+ +nop
+
+ lda #$3C ; dos_cdrootdir
+ sta HTRAP00
+ +nop
+
+ ; End of initialization
+
+ rts
diff --git a/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s b/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s
new file mode 100644
index 00000000..91bb422e
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/fs_hvsr_read_dir.s
@@ -0,0 +1,250 @@
+
+;
+; Hypervisor virtual filesystem - reading directory
+;
+
+
+fs_hvsr_read_dir_open:
+
+ ; Open the directory
+
+ lda #$12 ; dos_opendir
+ sta HTRAP00
+ +nop
+
+ ; XXX handle read errors
+
+ sta SD_DESC ; store directory descriptor XXX invent better name
+
+ ; Reset status to OK
+
+ lda #$00
+ sta PAR_TRACK
+ sta PAR_SECTOR
+ jsr util_status_SD
+
+ ; Provide pointer to the header
+
+ lda #$20
+ sta SD_ACPTR_LEN+0
+ lda #$00
+ sta SD_ACPTR_LEN+1
+
+ lda #dir_hdr_sd
+ sta SD_ACPTR_PTR+1
+
+ ; Set directory phase to 'file name'
+
+ lda #$01
+ sta SD_DIR_PHASE
+
+ ; End
+
+ jmp dos_EXIT_CLC
+
+fs_hvsr_read_dir:
+
+ ; Read dirent structure into $1000, process it, restore the memory content.
+ ; Starting at $1000 VIC sees chargen, so this should be a safe place
+
+ jsr fs_hvsr_direntmem_prepare
+ jsr fs_hvsr_util_nextdirentry
+ jsr fs_hvsr_direntmem_restore ; processor status is preserved
+
+ ; If nothing to read, output 'blocks free'
+
+ +bcs fs_hvsr_read_dir_blocksfree
+
+ ; Check if file name matches the filter
+
+ jsr util_dir_filter
+ bne fs_hvsr_read_dir ; if does not match, try the next entry
+
+ ; Otherwise, convert the file length from bytes to blocks to display
+
+ jsr util_dir_filesize_bytes
+
+ ; Prepare output entry, starting from XX_DIR_ENTRY + initial offset
+
+ ldx #$00 ; offset for SD card unit
+
+ lda #$01 ; link to the next line - dummy, will be regenerated by BASIC
+ sta XX_DIR_ENTRY, x
+ inx
+ sta XX_DIR_ENTRY, x
+ inx
+
+ lda PAR_FSIZE_BLOCKS+0 ; store number of blocks
+ sta XX_DIR_ENTRY, x
+ inx
+ lda PAR_FSIZE_BLOCKS+1
+ sta XX_DIR_ENTRY, x
+ inx
+
+ lda #' ' ; indent file name
+
+@lp1:
+ dey
+ bmi @lp1_done
+ sta XX_DIR_ENTRY, x
+ inx
+ bra @lp1
+
+@lp1_done:
+
+ lda #$22 ; opening quote
+ sta XX_DIR_ENTRY, x
+ inx
+
+ ldy #$FF ; put file name
+
+@lp2:
+
+ iny
+ lda PAR_FNAME, y
+ cmp #$A0
+ beq @lp2_done
+ cpy #$10
+ beq @lp2_done
+ sta XX_DIR_ENTRY, x
+ inx
+ bra @lp2
+
+@lp2_done:
+
+ lda #$22 ; closing quote
+ sta XX_DIR_ENTRY, x
+ inx
+
+ ldy #$10 ; put spaces for indentation
+
+@lp3:
+
+ dey
+ lda PAR_FNAME, y
+ cmp #$A0
+ bne @lp3_done
+
+ lda #' '
+ sta XX_DIR_ENTRY, x
+ inx
+ bra @lp3
+
+@lp3_done:
+
+ lda PAR_FTYPE ; put 'damaged' mark if needed
+ bmi @closed
+ lda #'*'
+ +skip_2_bytes_trash_nvz
+
+@closed:
+
+ lda #' '
+ sta XX_DIR_ENTRY, x
+ inx
+
+ lda PAR_FTYPE ; put file type
+ and #$3F
+ dec
+ asl
+ asl
+ tay
+
+@lp4:
+
+ lda dir_types, y
+ beq @lp4_done
+ sta XX_DIR_ENTRY, x
+ inx
+ iny
+ bra @lp4
+
+@lp4_done:
+
+ lda PAR_FTYPE ; read-only mark (if needed)
+ and #$40
+ beq @skipro
+ lda #'<'
+ sta XX_DIR_ENTRY, x
+ inx
+
+@skipro:
+
+ lda #$00 ; put end of the line
+ sta XX_DIR_ENTRY, x
+ inx
+
+ stx SD_ACPTR_LEN+0
+ sta SD_ACPTR_LEN+1
+
+ lda #<(XX_DIR_ENTRY)
+ sta SD_ACPTR_PTR+0
+ lda #>(XX_DIR_ENTRY)
+ sta SD_ACPTR_PTR+1
+
+ clc
+ rts
+
+fs_hvsr_read_dir_blocksfree:
+
+ ; Set pointer to 'BLOCKS FREE.' line
+
+ ; XXX determine free space
+
+ lda #$13
+ sta SD_ACPTR_LEN+0
+ lda #$00
+ sta SD_ACPTR_LEN+1
+
+ lda #dir_end
+ sta SD_ACPTR_PTR+1
+
+ ; Mark end of directory
+
+ lda #$00
+ sta SD_DIR_PHASE
+
+ ; Close the directory within the hypervisor XXX maybe move it to close routine
+
+ ldx SD_DESC
+ lda #$16 ; dos_closedir
+ sta HTRAP00
+ +nop
+
+ clc
+ rts
+
+;
+; Helper routines
+;
+
+fs_hvsr_direntmem_prepare:
+
+ ldx #$00
+@1:
+ ldy $1000, x
+ sty SD_MEMSHADOW, x
+ inx
+ bne @1
+
+ rts
+
+fs_hvsr_direntmem_restore:
+
+ php
+
+ ldx #$00
+@1:
+ ldy SD_MEMSHADOW, x
+ sty $1000, x
+ inx
+ bne @1
+
+ bne @1
+
+ plp
+ rts
diff --git a/src/dos_m65/dev_sdcard/fs_hvsr_read_file.s b/src/dos_m65/dev_sdcard/fs_hvsr_read_file.s
new file mode 100644
index 00000000..61977c37
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/fs_hvsr_read_file.s
@@ -0,0 +1,151 @@
+
+;
+; Hypervisor virtual filesystem - opening the file
+;
+
+
+fs_hvsr_read_file_open:
+
+ ; Open the directory
+
+ lda #$12 ; dos_opendir
+ sta HTRAP00
+ +nop
+
+ ; XXX handle read errors
+
+ sta SD_DESC ; store directory descriptor XXX invent better name
+
+ ; Reset status to OK
+
+ lda #$00
+ sta PAR_TRACK
+ sta PAR_SECTOR
+ jsr util_status_SD
+
+ ; XXX deduplicate part above with opening directory
+
+ ; Read dirent structures into $1000, find the first matching file
+ ; Starting at $1000 VIC sees chargen, so this should be a safe place
+
+ jsr fs_hvsr_direntmem_prepare
+
+@lp_find:
+
+ jsr fs_hvsr_util_nextdirentry ; fetch the next file name
+ +bcs fs_hvsr_file_not_found
+
+ ; Only accept files of type 'PRG', properly closed
+
+ lda PAR_FTYPE
+ and #%10111111
+ cmp #$82
+ bne @lp_find
+
+ ; Check if file name matches the filter
+
+ jsr util_dir_filter
+ bne @lp_find ; if does not match, try the next entry
+
+ ; Found the file - load it
+
+ jsr fs_hvsr_direntmem_restore ; restore $1000 memory content
+
+ lda #$18 ; dos_openfile
+ sta HTRAP00
+ +nop
+
+ ; XXX check error code
+
+ ; Read the first 512-byte chunk
+
+ lda #$03 ; mode: read file
+ sta SD_MODE
+
+ jsr fs_hvsr_read_file
+ jmp dos_EXIT
+
+fs_hvsr_read_file:
+
+ ; Read chunk of data to SD card buffer
+
+ ldx SD_DESC
+ lda #$1A ; dos_readfile
+ sta HTRAP00
+ +nop
+
+ ; XXX check error code
+
+ ; Store number of bytes read
+
+ stx SD_ACPTR_LEN+0
+ sty SD_ACPTR_LEN+1
+
+ ; Check if any data was read
+
+ tya
+ ora SD_ACPTR_LEN+0
+ bne @copy
+
+ lda #$20 ; dos_closefile
+ sta HTRAP00
+ +nop
+
+ lda #$00
+ sec
+ rts
+
+@copy:
+
+ ; Set pointer to new data
+
+ lda #SD_FILEBUF
+ sta SD_ACPTR_PTR+1
+
+ ; Copy data to SD_FILEBUF
+
+ lda #%10000000 ; select SD card buffer
+ tsb SD_BUFCTL
+
+ lda #$02
+ sta DMA_ADDRBANK ; $D702
+ lda #$00
+ sta DMA_ADDRMB ; $D704
+
+ lda #>(@dmalist-$4000)
+ sta DMA_ADDRMSB ; $D701
+ lda #<(@dmalist-$4000)
+ sta DMA_ETRIG ; $D705
+
+ clc
+ rts
+
+@dmalist:
+
+ !byte $0A ; use F018A list format (it is shorter by 1 byte)
+ !byte $80, $FF ; src. address is $FFxxxxx
+ !byte $81, $00 ; dst. address is $00xxxxx
+ !byte $00 ; end of options
+ !byte $00 ; operation: COPY
+ !word $0200 ; data size if 512 bytes
+ !byte $00, $6E, $0D ; src. addr is $xxD6E00
+ !byte <(SD_FILEBUF - $8000)
+ !byte >(SD_FILEBUF - $8000)
+ !byte $01 ; dst. addr is $xx1xxxx (internal buffer)
+
+fs_hvsr_file_not_found:
+
+ jsr fs_hvsr_direntmem_restore ; restore $1000 memory content
+
+ ldx SD_DESC
+ lda #$16 ; dos_closedir
+ sta HTRAP00
+ +nop
+
+ lda #39 ; file not found error
+ jsr util_status_SD
+
+ lda #K_ERR_FILE_NOT_FOUND
+ jmp dos_EXIT_SEC_A
diff --git a/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s b/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s
new file mode 100644
index 00000000..5db911a3
--- /dev/null
+++ b/src/dos_m65/dev_sdcard/fs_hvsr_util_nextdirentry.s
@@ -0,0 +1,243 @@
+
+;
+; Hypervisor virtual filesystem - helper routine to get the next directory entry
+;
+
+
+; Fills-in: PAR_FNAME, PAR_FTYPE, PAR_FSIZE_BYTES
+
+; NOTE: overrides page pointed by FS_HVSR_DIRENT!
+
+
+; XXX work-in-progress, this should be used within directory reading code
+
+fs_hvsr_util_nextdirentry:
+
+ ; Clear the page which will be used
+
+ ldx #$00
+ txa
+
+@lpclear:
+
+ sta FS_HVSR_DIRENT, x
+ inx
+ bne @lpclear
+
+ ; Ask the hypervisor to read the next dirent structure
+
+ ldx SD_DESC ; directory descriptor XXX rename to FS_HVSR_DESC
+ ldy #>FS_HVSR_DIRENT ; target page number
+
+ lda #$14 ; dos_readdir
+ sta HTRAP00
+ +nop
+
+ +bcc @fail
+
+ ; Reading entry succeeded, try to decode it. Important dirent fileds:
+
+ ; - $00-$3F - file name
+ ; - $40 - file name length
+ ; - $52-$55 - file length
+ ; - $56-$57 - file type ($10 = dir, $20 = regular) and attributes ($01 for read-only)
+
+ ;
+ ; Preprocess/validate the filename
+ ;
+
+ ldx FS_HVSR_DIRENT+$40 ; file name length
+ beq fs_hvsr_util_nextdirentry ; do not even try for empty file name
+ cpx #20
+ bcs fs_hvsr_util_nextdirentry ; if longer than 16 characters + dot + extension - also skip this one
+ dex
+
+@lpname:
+
+ lda FS_HVSR_DIRENT,x
+ cmp #$22
+ beq fs_hvsr_util_nextdirentry ; quotation mark is illegal
+ cmp #$2A
+ beq fs_hvsr_util_nextdirentry ; asterisk is illegal, it is used for filtering
+ cmp #$3F
+ beq fs_hvsr_util_nextdirentry ; the question mark - in the MS-DOS world it is illegal
+ cmp #$20
+ bcc fs_hvsr_util_nextdirentry ; control characters are not allowed
+ cmp #$5B
+ bcc @lpname_next ; up to PETSCII 'Z' is OK
+ cmp #$61
+ bcc fs_hvsr_util_nextdirentry ; some characters are not allowed
+ cmp #$7E
+ bne @lpname_1
+ lda #$A6 ; replace tilde / pi with something more sane
+ bra @lpname_store_next
+
+@lpname_1:
+
+ cmp #$7B
+ bcs fs_hvsr_util_nextdirentry ; PETSCII-art and control characters are illegal
+ clc
+ sbc #$20 ; make everything the same case
+
+@lpname_store_next:
+
+ sta FS_HVSR_DIRENT,x ; use this when file name has to be adapted
+
+@lpname_next:
+
+ dex
+ bpl @lpname
+
+ ;
+ ; Determine type (file/directory)
+ ;
+
+ lda FS_HVSR_DIRENT+$56
+ tax
+ and #$FE
+ beq @entity_file ; workaround for older hypervisors
+
+ and #$20
+ bne @entity_file ; branch on file
+
+ txa
+ and #$10
+ beq fs_hvsr_util_nextdirentry ; this type is unknown
+
+@entity_dir:
+
+ ; Once again validate the name length, with more precise information
+
+ lda FS_HVSR_DIRENT+$40
+ cmp #$11
+ bcs fs_hvsr_util_nextdirentry ; skip entry if file name longer than 16 characters
+
+ ; Set the type to directory
+
+ lda #$05
+ bra @detect_attributes
+
+@entity_file:
+
+ ; Once again validate the name length, with more precise information
+
+ lda FS_HVSR_DIRENT+$40
+ sec
+ sbc #$04 ; strip 4 bytes - for dot and extension
+ bmi fs_hvsr_util_nextdirentry ; if name too short, try next entry
+ beq fs_hvsr_util_nextdirentry ; if name too short, try next entry
+ sta FS_HVSR_DIRENT+$40 ; store corrected file name length
+ tax
+
+ ; Make sure there is a dot marking the start of a 3-byte extension
+
+ lda FS_HVSR_DIRENT, x
+ cmp #$2E
+ +bne fs_hvsr_util_nextdirentry
+
+ ;
+ ; Detect file type by extension
+ ;
+
+ inx
+ ldy #$00
+
+@lpext:
+
+ lda FS_HVSR_DIRENT+0, x
+ cmp dir_types+0, y
+ bne @lpext_next
+
+ lda FS_HVSR_DIRENT+1, x
+ cmp dir_types+1, y
+ bne @lpext_next
+
+ lda FS_HVSR_DIRENT+2, x
+ cmp dir_types+2, y
+ beq @lpext_found
+
+@lpext_next:
+
+ iny
+ iny
+ iny
+ iny
+ cpy #(dir_types__end - dir_types)
+ bcc @lpext
+
+ jmp fs_hvsr_util_nextdirentry ; file extension not detected
+
+@lpext_found:
+
+ cpy #$10
+ +beq fs_hvsr_util_nextdirentry ; file extension 'DIR' does not mean this is a directory
+ tya
+
+ clc
+ ror
+ clc
+ ror
+ inc
+
+ cmp #$06 ; mark some file types (not SEQ/PRG/USR/REL/DIR) as read-only
+ bcc @detect_attributes
+ ora #$40
+
+@detect_attributes:
+
+ ora #$80 ; mark the file as closed, FAT32 does not have a 'not closed' attribute
+ sta PAR_FTYPE
+
+ lda FS_HVSR_DIRENT+$56 ; also apply read-only attribute from FAT32
+ and #$01
+ beq @copy_size
+
+ lda PAR_FTYPE
+ ora #$40
+ sta PAR_FTYPE
+
+@copy_size:
+
+ ; Copy the file size
+
+ ldx #$03
+
+@lpsize:
+
+ lda FS_HVSR_DIRENT+$52,x ; copy file size in byytes
+ sta PAR_FSIZE_BYTES,x
+ dex
+ bpl @lpsize
+
+@copy_name:
+
+ ; Last, but not least - copy file name
+
+ lda #$A0 ; fill-in empty bytes with $A0, to simulate CBM file system
+ ldx #$0F
+
+@lpname_cpy:
+
+ cpx FS_HVSR_DIRENT+$40
+ bcs @lpname_fill
+ lda FS_HVSR_DIRENT, x
+
+@lpname_fill:
+
+ sta PAR_FNAME,x
+ dex
+ bpl @lpname_cpy
+
+ ; All done
+
+ clc
+ rts
+
+@fail:
+
+ ; Reading next entry failed, this is the end
+
+ ; XXX check error code
+
+ sec
+ rts
diff --git a/src/dos_m65/dos_chkunit.s b/src/dos_m65/dos_chkunit.s
deleted file mode 100644
index a530850d..00000000
--- a/src/dos_m65/dos_chkunit.s
+++ /dev/null
@@ -1,63 +0,0 @@
-
-;
-; Unit number handling. For detailed description see 'm65dos_bridge.s' file
-;
-
-
-dos_CHKUNIT:
-
- ; Check for magic string
-
- pha
- phx
-
- ldx #$04
-@1:
- lda MAGICSTR, x
- cmp dos_magicstr, x
- bne dos_CHKUNIT_mem_fail
- dex
- bpl @1
-
- plx
- pla
-
- ; Check for unit
-
- cmp UNIT_SDCARD
- beq dos_CHKUNIT_sdcard
- cmp UNIT_FLOPPY
- beq dos_CHKUNIT_floppy
- cmp UNIT_RAMDISK
- beq dos_CHKUNIT_ramdisk
-
- sec
- rts
-
-dos_CHKUNIT_sdcard:
-
- lda #$00
- +skip_2_bytes_trash_nvz
-
- ; FALLTROUGH
-
-dos_CHKUNIT_floppy:
-
- lda #$01
- +skip_2_bytes_trash_nvz
-
- ; FALLTROUGH
-
-dos_CHKUNIT_ramdisk:
-
- lda #$02
-
- clc
- rts
-
-dos_CHKUNIT_mem_fail:
-
- plx
- pla
- sec
- rts
diff --git a/src/dos_m65/dos_enter_exit.s b/src/dos_m65/dos_enter_exit.s
new file mode 100644
index 00000000..a44c681e
--- /dev/null
+++ b/src/dos_m65/dos_enter_exit.s
@@ -0,0 +1,58 @@
+
+; Helper routines for entering/exiting the context
+
+
+
+dos_ENTER: ; enter DOS context
+
+ php
+ jsr m65_speed_tape_cbdos
+ plp
+
+ sta REG_A
+ stx REG_X
+ sty REG_Y
+ stz REG_Z
+
+ rts
+
+
+dos_EXIT_SEC: ; exit DOS context with Carry set
+
+ sec
+ bra dos_EXIT
+
+dos_EXIT_CLC: ; exit DOS context with Carry clear
+
+ clc
+
+ ; FALLTROUGH
+
+dos_EXIT:
+
+ lda REG_A
+ bra dos_EXIT_A
+
+
+dos_EXIT_SEC_A: ; exit DOS context with Carry set, return .A
+
+ sec
+ bra dos_EXIT_A
+
+dos_EXIT_CLC_A: ; exit DOS context with Carry clear, return .A
+
+ clc
+
+ ; FALLTROUGH
+
+dos_EXIT_A:
+
+ ldz REG_Z
+ ldy REG_Y
+ ldx REG_X
+
+ php
+ jsr m65_speed_restore
+ plp
+
+ rts
diff --git a/src/dos_m65/dos_imports.s b/src/dos_m65/dos_imports.s
new file mode 100644
index 00000000..825cd530
--- /dev/null
+++ b/src/dos_m65/dos_imports.s
@@ -0,0 +1,14 @@
+
+;; #IMPORT# KERNAL_0 = KERNAL_0_combined.sym
+
+;
+; Definitions for calling MEGA65 segment KERNAL_0 routines from DOS_1
+;
+
+;; #ALIAS# MONITOR = KERNAL_0.MONITOR
+
+;; #ALIAS# kernalstatus_EOI = KERNAL_0.kernalstatus_EOI
+;; #ALIAS# kernalstatus_DEVICE_NOT_FOUND = KERNAL_0.kernalstatus_DEVICE_NOT_FOUND
+
+;; #ALIAS# m65_speed_tape_cbdos = KERNAL_0.m65_speed_tape_cbdos
+;; #ALIAS# m65_speed_restore = KERNAL_0.m65_speed_restore
diff --git a/src/dos_m65/dos_init.s b/src/dos_m65/dos_init.s
index 5654e923..93397519 100644
--- a/src/dos_m65/dos_init.s
+++ b/src/dos_m65/dos_init.s
@@ -3,11 +3,22 @@
; Initializes DOS. For detailed description see 'm65dos_bridge.s' file
;
+
+!set CONFIG_UNIT_FLOPPY = 0 ; XXX floppy not supported yet
+!set CONFIG_UNIT_RAMDISK = 0 ; XXX RAM disk not supported yet
+
+
dos_INIT:
+ ; Safer version of 'dos_ENTER' - does not affect speed related registers
+
+ sta REG_A
+ stx REG_X
+ sty REG_Y
+ stz REG_Z
+
; Set the magic string 'CBDOS'
- phx
ldx #$04
@1:
lda dos_magicstr, x
@@ -15,8 +26,6 @@ dos_INIT:
dex
bpl @1
- plx
-
; Set default device numbers
lda #CONFIG_UNIT_SDCARD
@@ -26,9 +35,42 @@ dos_INIT:
lda #CONFIG_UNIT_RAMDISK
sta UNIT_RAMDISK
- ; Mark SD card as not initialized
+ ; Clear listener / talker
- lda #$00
- sta CARD_INIT_DONE
+ lda #$FF
+ sta IDX1_LISTENER
+ sta IDX2_LISTENER
+ sta IDX1_TALKER
+ sta IDX2_TALKER
+
+ ; Initialize device handlers
+
+ jsr dev_sd_init
+ jsr dev_fd_init
+ jsr dev_rd_init
+
+ ; Initialize helper code in RAM
+
+ lda #$AD ; LDA opcode, absolute
+ sta code_LDA_01
+ sta code_LDA_02
+ sta code_LDA_03
+
+ lda #$B9 ; LDA nnnn, y opcode
+ sta code_LDA_nnnn_Y
+
+ lda #$60 ; RTS opcode
+ sta code_RTS_01
+ sta code_RTS_02
+ sta code_RTS_03
+ sta code_RTS_04
+
+ ; Safer version of 'dos_EXIT' - does not affect speed related registers
+
+ clc
+ ldz REG_Z
+ ldy REG_Y
+ ldx REG_X
+ lda REG_A
rts
diff --git a/src/dos_m65/dos_memchk.s b/src/dos_m65/dos_memchk.s
new file mode 100644
index 00000000..cde237bb
--- /dev/null
+++ b/src/dos_m65/dos_memchk.s
@@ -0,0 +1,50 @@
+
+;
+; Check if DOS memory is not overwritten
+;
+
+
+dos_MEMCHK:
+
+ pha
+ phx
+
+ ; Check for magic string
+
+ ldx #$04
+@1:
+ lda MAGICSTR, x
+ cmp dos_magicstr, x
+ bne @fail
+ dex
+ bpl @1
+
+ ; Check if helper code is undamaged
+
+ lda #$AD
+ cmp code_LDA_01
+ bne @fail
+ cmp code_LDA_02
+ bne @fail
+ cmp code_LDA_03
+ bne @fail
+
+ lda #$60
+ cmp code_RTS_01
+ bne @fail
+ cmp code_RTS_02
+ bne @fail
+ cmp code_RTS_03
+ bne @fail
+
+ plx
+ pla
+ clc
+ rts
+
+@fail:
+
+ plx
+ pla
+ sec
+ rts
diff --git a/src/dos_m65/dos_setunit.s b/src/dos_m65/dos_setunit.s
deleted file mode 100644
index 1863dfe9..00000000
--- a/src/dos_m65/dos_setunit.s
+++ /dev/null
@@ -1,42 +0,0 @@
-
-;
-; Unit number handling. For detailed description see 'm65dos_bridge.s' file
-;
-
-
-dos_SETUNIT:
-
- ; XXX check if .X is valid
-
- cmp #$00
- beq dos_SETUNIT_sdcard
- cmp #$01
- beq dos_SETUNIT_floppy
- cmp #$02
- beq dos_SETUNIT_ramdisk
-
- sec
- rts
-
-dos_SETUNIT_sdcard:
-
- stx UNIT_SDCARD
- +skip_2_bytes_trash_nvz
-
- ; FALLTROUGH
-
-dos_SETUNIT_floppy:
-
- stx UNIT_FLOPPY
- +skip_2_bytes_trash_nvz
-
- ; FALLTROUGH
-
-dos_SETUNIT_ramdisk:
-
- stx UNIT_RAMDISK
-
- ; FALLTROUGH
-
- clc
- rts
diff --git a/src/dos_m65/dos_unitchk.s b/src/dos_m65/dos_unitchk.s
new file mode 100644
index 00000000..b14c09f9
--- /dev/null
+++ b/src/dos_m65/dos_unitchk.s
@@ -0,0 +1,50 @@
+
+;
+; Unit number handling. For detailed description see 'm65dos_bridge.s' file
+;
+
+
+dos_UNITCHK:
+
+ ; Before the start make sure memory content is not damaged
+
+ jsr dos_MEMCHK
+ bcc @ok
+ rts
+@ok:
+ jsr dos_ENTER
+
+ ; Check for unit
+
+ cmp UNIT_SDCARD
+ beq dos_UNITCHK_sdcard
+ cmp UNIT_FLOPPY
+ beq dos_UNITCHK_floppy
+ cmp UNIT_RAMDISK
+ beq dos_UNITCHK_ramdisk
+
+ ; FALLTROUGH
+
+dos_UNITCHK_fail:
+
+ jmp dos_EXIT_SEC
+
+dos_UNITCHK_sdcard:
+
+ lda #$00
+ +skip_2_bytes_trash_nvz
+
+ ; FALLTROUGH
+
+dos_UNITCHK_floppy:
+
+ lda #$01
+ +skip_2_bytes_trash_nvz
+
+ ; FALLTROUGH
+
+dos_UNITCHK_ramdisk:
+
+ lda #$02
+
+ jmp dos_EXIT_CLC_A
diff --git a/src/dos_m65/dos_unitnum.s b/src/dos_m65/dos_unitnum.s
new file mode 100644
index 00000000..06857073
--- /dev/null
+++ b/src/dos_m65/dos_unitnum.s
@@ -0,0 +1,56 @@
+
+;
+; Unit number handling. For detailed description see 'm65dos_bridge.s' file
+;
+
+
+dos_UNITNUM:
+
+ ; Before the start make sure memory content is not damaged
+
+ jsr dos_MEMCHK
+ bcc @ok
+ lda #$00 ; failure
+ rts
+@ok:
+ jsr dos_ENTER
+
+ ; Check what kind of device was requested
+
+ cmp #$00
+ beq dos_UNITNUM_sdcard
+ cmp #$01
+ beq dos_UNITNUM_floppy
+ cmp #$02
+ beq dos_UNITNUM_ramdisk
+
+ ; FALLTROUGH
+
+dos_UNITNUM_fail:
+
+ lda #$00
+
+ jmp dos_EXIT_SEC_A
+
+dos_UNITNUM_sdcard:
+
+ lda UNIT_SDCARD
+ bra dos_UNITNUM_common
+
+dos_UNITNUM_floppy:
+
+ lda UNIT_FLOPPY
+ bra dos_UNITNUM_common
+
+dos_UNITNUM_ramdisk:
+
+ lda UNIT_RAMDISK
+
+ ; FALLTROUGH
+
+dos_UNITNUM_common:
+
+ cmp #$00
+ beq dos_UNITNUM_fail
+
+ jmp dos_EXIT_CLC_A
diff --git a/src/dos_m65/dos_unitset.s b/src/dos_m65/dos_unitset.s
new file mode 100644
index 00000000..a82e6316
--- /dev/null
+++ b/src/dos_m65/dos_unitset.s
@@ -0,0 +1,49 @@
+
+;
+; Unit number handling. For detailed description see 'm65dos_bridge.s' file
+;
+
+
+dos_UNITSET:
+
+ ; Before the start make sure memory content is not damaged
+
+ jsr dos_MEMCHK
+ bcc @ok
+ rts
+@ok:
+ jsr dos_ENTER
+
+ ; XXX do not allow illegal device numbers... above 30 or below 8 ?
+
+ ; Check what kind of device was requested
+
+ cmp #$00
+ beq dos_UNITSET_sdcard
+ ; XXX devices below are not implemented yet
+ ; cmp #$01
+ ; beq dos_UNITSET_floppy
+ ; cmp #$02
+ ; beq dos_UNITSET_ramdisk
+
+ jmp dos_EXIT_SEC
+
+dos_UNITSET_sdcard:
+
+ stx UNIT_SDCARD
+ +skip_2_bytes_trash_nvz
+
+ ; FALLTROUGH
+
+dos_UNITSET_floppy:
+
+ stx UNIT_FLOPPY
+ +skip_2_bytes_trash_nvz
+
+ ; FALLTROUGH
+
+dos_UNITSET_ramdisk:
+
+ stx UNIT_RAMDISK
+
+ jmp dos_EXIT_CLC
diff --git a/src/dos_m65/dos_vectab_dev.s b/src/dos_m65/dos_vectab_dev.s
new file mode 100644
index 00000000..d11f837c
--- /dev/null
+++ b/src/dos_m65/dos_vectab_dev.s
@@ -0,0 +1,18 @@
+
+;
+; Vector tables to device-specific routines
+;
+
+
+dos_cmd_OPEN_vectab:
+
+ !word dev_sd_cmd_OPEN
+ !word dev_fd_cmd_OPEN
+ !word dev_rd_cmd_OPEN
+
+
+dos_cmd_CLOSE_vectab:
+
+ !word dev_sd_cmd_CLOSE
+ !word dev_fd_cmd_CLOSE
+ !word dev_rd_cmd_CLOSE
diff --git a/src/dos_m65/msg_acptr.s b/src/dos_m65/msg_acptr.s
new file mode 100644
index 00000000..e3bffd87
--- /dev/null
+++ b/src/dos_m65/msg_acptr.s
@@ -0,0 +1,158 @@
+
+;
+; Implementation of ACPTR command. For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_ACPTR:
+
+ jsr dos_ENTER
+
+ ; Check if there is a talker active
+
+ ldx IDX1_TALKER
+ bmi msg_ACPTR_fail_no_talker
+
+ ; Check if active channel is status one
+
+ lda XX_CHANNEL, X
+ cmp #$0F
+ beq msg_ACPTR_status
+
+ ; XXX add support for read contexts (multiple channels)
+
+ ; Not a status channel - check if we have something to read out
+
+ ldx IDX2_TALKER
+ lda XX_ACPTR_LEN+0,x
+ ora XX_ACPTR_LEN+1,x
+ beq msg_ACPTR_fail_no_data
+
+ ; Read a byte of data from the buffer
+
+ jmp (msg_ACPTR_read_vectab, X)
+
+msg_ACPTR_read_SD:
+
+ ; Read and return one byte
+
+ jsr SD_ACPTR_helper
+ sta TBTCNT
+ sta REG_A
+
+ ; Increment pointer, decrement length
+
+ inc SD_ACPTR_PTR+0
+ bne @1
+ inc SD_ACPTR_PTR+1
+@1:
+ dec SD_ACPTR_LEN+0
+ lda SD_ACPTR_LEN+0
+ cmp #$FF
+ bne @2
+ dec SD_ACPTR_LEN+1
+@2:
+ ; If new length is 0, try to read next block of data
+
+ ora SD_ACPTR_LEN+1
+ bne @3
+ jsr dev_sd_cmd_READ
+ bcc @3
+ jsr kernalstatus_EOI
+@3:
+ jmp dos_EXIT_CLC
+
+
+msg_ACPTR_read_FD:
+
+ ; XXX provide implementation
+
+
+msg_ACPTR_read_RD:
+
+ ; XXX provide implementation
+
+
+msg_ACPTR_fail_no_data:
+
+ ; XXX What should be the reaction when trying to read and no data is present?
+
+ sta TBTCNT
+ sta REG_A
+ bra msg_ACPTR_EOI
+
+msg_ACPTR_status:
+
+ ldx IDX2_TALKER
+ jmp (msg_ACPTR_status_vectab, X)
+
+msg_ACPTR_status_SD: ; get next byte of status - SD card
+
+ ldx SD_STATUS_IDX
+ inc SD_STATUS_IDX
+ lda SD_STATUS_STR,x
+ bra msg_ACPTR_status_got
+
+msg_ACPTR_status_FD: ; get next byte of status - floppy
+
+ ldx FD_STATUS_IDX
+ inc FD_STATUS_IDX
+ lda FD_STATUS_STR,x
+ bra msg_ACPTR_status_got
+
+msg_ACPTR_status_RD: ; get next byte of status - ram disk
+
+ ldx RD_STATUS_IDX
+ inc RD_STATUS_IDX
+ lda RD_STATUS_STR,x
+
+ ; FALLTROUGH
+
+msg_ACPTR_status_got:
+
+ sta TBTCNT ; byte return
+ beq msg_ACPTR_reset_status
+
+ jmp dos_EXIT_CLC_A
+
+msg_ACPTR_fail_no_talker:
+
+ ; XXX set error code
+
+ jmp dos_EXIT_SEC
+
+msg_ACPTR_reset_status:
+
+ ldx IDX2_TALKER
+ lda #$00
+ sta PAR_TRACK
+ sta PAR_SECTOR
+ jsr (msg_ACPTR_set_status_vectab, x)
+
+ ; FALLTROUGH
+
+msg_ACPTR_EOI:
+
+ jsr kernalstatus_EOI
+ jmp dos_EXIT_CLC
+
+
+; Vector tables for jumps
+
+msg_ACPTR_status_vectab:
+
+ !word msg_ACPTR_status_SD
+ !word msg_ACPTR_status_FD
+ !word msg_ACPTR_status_RD
+
+msg_ACPTR_read_vectab:
+
+ !word msg_ACPTR_read_SD
+ !word msg_ACPTR_read_FD
+ !word msg_ACPTR_read_RD
+
+msg_ACPTR_set_status_vectab:
+
+ !word util_status_SD
+ !word util_status_FD
+ !word util_status_RD
diff --git a/src/dos_m65/msg_ciout.s b/src/dos_m65/msg_ciout.s
new file mode 100644
index 00000000..56ec372a
--- /dev/null
+++ b/src/dos_m65/msg_ciout.s
@@ -0,0 +1,92 @@
+
+;
+; Implementation of ACPTR command. For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_CIOUT:
+
+ jsr dos_ENTER
+ php
+
+ ; Check operation mode
+
+ ldx IDX1_LISTENER
+ bmi msg_CIOUT_fail
+ lda XX_MODE, x
+
+ cmp #$01
+ bne @1
+
+ ; Receiving command or file name
+
+ ldx IDX2_LISTENER
+ lda REG_A
+ jmp (msg_CIOUT_cmdfn_vectab, X)
+@1:
+ ; XXX handle cases of transferring data
+
+ plp
+ jmp dos_EXIT_SEC
+
+msg_CIOUT_fail:
+
+ ; XXX should we set status?
+ lda #K_ERR_DEVICE_NOT_FOUND
+
+ jmp dos_EXIT_SEC_A
+
+
+
+; Receiving command/file name
+
+msg_CIOUT_cmdfn_SD: ; get next byte of status - SD card
+
+ ldx SD_CMDFN_IDX
+ sta SD_CMDFN_BUF,x
+ inx
+ bpl @1
+ ldx #$7F
+@1:
+ stx SD_CMDFN_IDX
+ lda #$A0
+ sta SD_CMDFN_BUF,x
+ plp
+ +bcs dev_sd_cmd_OPEN_EOI ; if EOI - execute command
+ jmp dos_EXIT_CLC
+
+msg_CIOUT_cmdfn_FD: ; get next byte of status - floppy
+
+ ldx FD_CMDFN_IDX
+ sta FD_CMDFN_BUF,x
+ inx
+ bpl @1
+ ldx #$7F
+@1:
+ stx FD_CMDFN_IDX
+ lda #$A0
+ sta FD_CMDFN_BUF,x
+ plp
+ +bcs dev_fd_cmd_OPEN_EOI ; if EOI - execute command
+ jmp dos_EXIT_CLC
+
+msg_CIOUT_cmdfn_RD: ; get next byte of status - ram disk
+
+ ldx RD_CMDFN_IDX
+ sta RD_CMDFN_BUF,x
+ inx
+ bpl @1
+ ldx #$7F
+@1:
+ stx RD_CMDFN_IDX
+ lda #$A0
+ sta RD_CMDFN_BUF,x
+ plp
+ +bcs dev_rd_cmd_OPEN_EOI ; if EOI - execute command
+ jmp dos_EXIT_CLC
+
+msg_CIOUT_cmdfn_vectab:
+
+ !word msg_CIOUT_cmdfn_SD
+ !word msg_CIOUT_cmdfn_FD
+ !word msg_CIOUT_cmdfn_RD
diff --git a/src/dos_m65/msg_listen.s b/src/dos_m65/msg_listen.s
new file mode 100644
index 00000000..b8c3f3a8
--- /dev/null
+++ b/src/dos_m65/msg_listen.s
@@ -0,0 +1,54 @@
+
+;
+; Implementation of LISTEN commands.
+; For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_LISTEN:
+
+ jsr dos_ENTER
+
+ and #$1F
+ beq msg_LISTEN_fail ; branch if device 0 (used to denote lack of device)
+
+ cmp UNIT_SDCARD
+ bne @1
+
+ ; LISTEN on SD card
+
+ lda #$00
+ bra msg_LISTEN_success
+@1:
+ cmp UNIT_FLOPPY
+ bne @2
+
+ ; LISTEN on floppy
+
+ lda #$01
+ bra msg_LISTEN_success
+@2:
+ cmp UNIT_RAMDISK
+ bne msg_LISTEN_fail
+
+ ; LISTEN on ram disk
+
+ lda #$02
+
+ ; FALLTROUGH
+
+msg_LISTEN_success:
+
+ sta IDX1_LISTENER
+ asl
+ sta IDX2_LISTENER
+
+ ; XXX should we reset XX_CMDFN_IDX ?
+
+ jmp dos_EXIT_CLC
+
+msg_LISTEN_fail:
+
+ lda #K_ERR_DEVICE_NOT_FOUND
+
+ jmp dos_EXIT_SEC_A
diff --git a/src/dos_m65/msg_second.s b/src/dos_m65/msg_second.s
new file mode 100644
index 00000000..c0481254
--- /dev/null
+++ b/src/dos_m65/msg_second.s
@@ -0,0 +1,49 @@
+
+;
+; Implementation of SECOND command.
+; For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_SECOND:
+
+ jsr dos_ENTER
+
+ ; First store the channel
+
+ tay
+ and #$0F ; support channels 0-15, like 1541 drive
+
+ ldx IDX1_LISTENER
+ bmi msg_SECOND_done ; do nothing if no listener
+ sta XX_CHANNEL, x ; store channel
+
+ ; Determine command type
+
+ tya
+ and #$F0
+
+ cmp #$F0
+ beq msg_SECOND_OPEN
+ cmp #$E0
+ beq msg_SECOND_CLOSE
+
+ ; XXX provide implementation
+
+ ; FALLTROUGH
+
+msg_SECOND_done:
+
+ jmp dos_EXIT_CLC
+
+msg_SECOND_OPEN:
+
+ lda #$00
+ sta XX_CMDFN_IDX, x ; reset the index to the command/filename
+ ldx IDX2_LISTENER
+ jmp (dos_cmd_OPEN_vectab, x)
+
+msg_SECOND_CLOSE:
+
+ ldx IDX2_LISTENER
+ jmp (dos_cmd_CLOSE_vectab, x)
diff --git a/src/dos_m65/msg_talk.s b/src/dos_m65/msg_talk.s
new file mode 100644
index 00000000..28bb56e2
--- /dev/null
+++ b/src/dos_m65/msg_talk.s
@@ -0,0 +1,52 @@
+
+;
+; Implementation of TALK commands.
+; For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_TALK:
+
+ jsr dos_ENTER
+
+ and #$1F
+ beq msg_TALK_fail ; branch if device 0 (used to denote lack of device)
+
+ cmp UNIT_SDCARD
+ bne @1
+
+ ; TALK on SD card
+
+ lda #$00
+ bra msg_TALK_success
+@1:
+ cmp UNIT_FLOPPY
+ bne @2
+
+ ; TALK on floppy
+
+ lda #$01
+ bra msg_TALK_success
+@2:
+ cmp UNIT_RAMDISK
+ bne msg_TALK_fail
+
+ ; TALK on ram disk
+
+ lda #$02
+
+ ; FALLTROUGH
+
+msg_TALK_success:
+
+ sta IDX1_TALKER
+ asl
+ sta IDX2_TALKER
+
+ jmp dos_EXIT_CLC
+
+msg_TALK_fail:
+
+ lda #K_ERR_DEVICE_NOT_FOUND
+
+ jmp dos_EXIT_SEC_A
diff --git a/src/dos_m65/msg_tksa.s b/src/dos_m65/msg_tksa.s
new file mode 100644
index 00000000..018a0f62
--- /dev/null
+++ b/src/dos_m65/msg_tksa.s
@@ -0,0 +1,22 @@
+
+;
+; Implementation of TKSA commands.
+; For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_TKSA:
+
+ jsr dos_ENTER
+
+ and #$0F ; support channels 0-15, like 1541 drive
+
+ ldx IDX1_TALKER
+ bmi msg_TKSA_done ; do nothing if no taalker
+ sta XX_CHANNEL, x ; store channel
+
+ ; FALLTROUGH
+
+msg_TKSA_done:
+
+ jmp dos_EXIT_CLC
diff --git a/src/dos_m65/msg_unlsn_untlk.s b/src/dos_m65/msg_unlsn_untlk.s
new file mode 100644
index 00000000..5bf9030b
--- /dev/null
+++ b/src/dos_m65/msg_unlsn_untlk.s
@@ -0,0 +1,25 @@
+
+;
+; Implementation of UNLSN/UNTLK messages.
+; For detailed description see 'm65dos_bridge.s' file.
+;
+
+
+msg_UNLSN:
+
+ jsr dos_ENTER
+
+ lda #$FF
+ sta IDX1_LISTENER
+ sta IDX2_LISTENER
+
+ jmp dos_EXIT_CLC
+
+msg_UNTLK:
+
+ jsr dos_ENTER
+
+ sta IDX1_TALKER
+ sta IDX2_TALKER
+
+ jmp dos_EXIT_CLC
diff --git a/src/dos_m65/sdcard/sdcard_helpers.s b/src/dos_m65/sdcard/sdcard_helpers.s
deleted file mode 100644
index 053af35f..00000000
--- a/src/dos_m65/sdcard/sdcard_helpers.s
+++ /dev/null
@@ -1,93 +0,0 @@
-
-;
-; Various helper routines for SD card support
-;
-
-; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
-
-
-
-;
-; Sets read/write address
-;
-; Input: CARD_SECNUM, CARD_IS_SDHC
-; Output: Carry set = error
-; Preserves: .X, .Y, .Z
-;
-
-sdcard_set_addr:
-
- bit CARD_IS_SDHC
- bpl sdcard_set_addr_sdsc
-
-sdcard_set_addr_sdhc:
-
- lda CARD_SECNUM+0
- sta SD_ADDR+0
- lda CARD_SECNUM+1
- sta SD_ADDR+1
- lda CARD_SECNUM+2
- sta SD_ADDR+2
- lda CARD_SECNUM+3
- sta SD_ADDR+3
-
- ; FALLTROUGH
-
-sdcard_set_addr_done:
-
- clc
- rts
-
-sdcard_set_addr_sdsc:
-
- ; Multiply sector number by 512
-
- lda #$00
- sta SD_ADDR+0
- clc
- lda CARD_SECNUM+0
- rol
- sta SD_ADDR+1
- lda CARD_SECNUM+1
- rol
- sta SD_ADDR+2
- lda CARD_SECNUM+2
- rol
- sta SD_ADDR+3
- bcs sdcard_helper_fail ; branch if sector number too large for SD card
- lda CARD_SECNUM+3
- beq sdcard_set_addr_done ; do not branch if sector number too large for SD card
-
- ; FALLTROUGH
-
-sdcard_helper_fail:
-
- sec
- rts
-
-
-;
-; Wait till card is ready
-;
-; Input: none
-; Output: Carry set = error
-; Preserves: .Y, .Z
-
-sdcard_wait_ready:
-
- ; XXX if card does not get ready, try to reset it
-
- lda SD_CTL
- ; Sometimes we see this result, i.e., sdcard.vhdl thinks it is done,
- ; but sdcardio.vhdl thinks not. This means a read error.
- cmp #$01
- beq sdcard_helper_fail
- tax
- and #$40
- bne sdcard_helper_fail
- txa
- and #$03
- bne sdcard_wait_ready
-
- clc
- rts
diff --git a/src/dos_m65/sdcard/sdcard_init.s b/src/dos_m65/sdcard/sdcard_init.s
deleted file mode 100644
index 7103ca38..00000000
--- a/src/dos_m65/sdcard/sdcard_init.s
+++ /dev/null
@@ -1,243 +0,0 @@
-
-;
-; Initialize memory card, determine it's type and size
-;
-
-; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
-
-
-
-; XXX finish the routine
-
-
-sdcard_init:
-
- ; Initialize most important variables
-
- lda #$00
- sta CARD_IS_SDHC
-
- lda #SD_SECBUF_0
- sta CARD_BUFPNT1+0
- sta CARD_BUFPNT2+0
- lda #SD_SECBUF_1
- sta CARD_BUFPNT1+1
- inc
- sta CARD_BUFPNT2+1
- lda #SD_SECBUF_2
- sta CARD_BUFPNT1+2
- sta CARD_BUFPNT2+2
- lda #SD_SECBUF_3
- sta CARD_BUFPNT1+3
- sta CARD_BUFPNT2+3
-
- ; Reset the card
-
- jsr sdcard_reset
-
- ; Try to read first sector to see if card is operable
-
- lda #$00
- sta SD_ADDR+0
- sta SD_ADDR+1
- sta SD_ADDR+2
- sta SD_ADDR+3
-
- jsr sdcard_init_read
- bcs sdcard_init_getsize_fail ; if failure, mark card as not operable and quit
-
- ; Work out if this is SD or SDHC card - SD cards can't read at non-sector aligned addresses
-
- lda #$02
- sta SD_ADDR+0
- lda #$00
- sta SD_ADDR+1
- sta SD_ADDR+2
- sta SD_ADDR+3
-
- jsr sdcard_init_read
-
- lda SD_CTL
- beq sdcard_init_sdsc
-
- ; FALLTROUGH
-
-sdcard_init_sdhc:
-
- lda #$80
- sta CARD_IS_SDHC
-
- bra sdcard_init_getsize
-
-sdcard_init_sdsc:
-
- lda #$00
- sta CARD_IS_SDHC
- lda #CARD_CMD_SDHC_OFF ; $40 - use byte addressing
- sta SD_CTL
-
- ; FALLTROUGH
-
-sdcard_init_getsize:
-
- ; Work out size of SD card in a safe way
- ; (binary search of sector numbers is NOT safe for some reason.
- ; It frequently reports bigger than the size of the card)
-
- ; step (and first sector) = 16*2048
-
- sta CARD_TMP_STEP+0
- sta CARD_SECNUM+0
- sta CARD_TMP_STEP+2
- sta CARD_SECNUM+2
- sta CARD_TMP_STEP+3
- sta CARD_SECNUM+3
- lda #$08
- sta CARD_TMP_STEP+1
- sta CARD_SECNUM+1
-
- ; FALLTROUGH
-
-sdcard_init_getsize_read:
-
- ; Try to read sector
-
- jsr sdcard_readsector
- bcc sdcard_init_getsize_next ; XXX original code checks PEEK(sd_ctl)&0x63;...
-
- ; Failed to read - restore card state and sector number
-
- jsr sdcard_reset
-
- sec
- lda CARD_SECNUM+0
- sbc CARD_TMP_STEP+0
- sta CARD_SECNUM+0
- lda CARD_SECNUM+1
- sbc CARD_TMP_STEP+1
- sta CARD_SECNUM+1
- lda CARD_SECNUM+2
- sbc CARD_TMP_STEP+2
- sta CARD_SECNUM+2
- lda CARD_SECNUM+3
- sbc CARD_TMP_STEP+3
- sta CARD_SECNUM+3
-
- ; Divide step by 2, skip bytes which are always 0
-
- clc
- ; ror CARD_TMP_STEP+3
- ; ror CARD_TMP_STEP+2
- ror CARD_TMP_STEP+1
- ror CARD_TMP_STEP+0
-
- ; FALLTROUGH
-
-sdcard_init_getsize_next:
-
- ; Increment sector number by step
-
- clc
- lda CARD_SECNUM+0
- adc CARD_TMP_STEP+0
- sta CARD_SECNUM+0
- lda CARD_SECNUM+1
- adc CARD_TMP_STEP+1
- sta CARD_SECNUM+1
- lda CARD_SECNUM+2
- adc CARD_TMP_STEP+2
- sta CARD_SECNUM+2
- lda CARD_SECNUM+3
- adc CARD_TMP_STEP+3
- sta CARD_SECNUM+3
-
- ; If sector number is 0 - report failure
-
- lda CARD_SECNUM+0
- ora CARD_SECNUM+1
- ora CARD_SECNUM+2
- ora CARD_SECNUM+3
- beq sdcard_init_getsize_fail
-
- ; If step is 0 - this is the end, we know maximum size
-
- lda CARD_TMP_STEP+0
- ora CARD_TMP_STEP+1
- ora CARD_TMP_STEP+2
- ora CARD_TMP_STEP+3
- beq sdcard_init_getsize_done
-
- ; Check sector number, should be below $10:$00:$00:$00
-
- lda CARD_SECNUM+3
- and #$F0
- bne sdcard_init_getsize_read
-
- ; It is not - report maximum size
-
- lda #$FF
- sta CARD_SECNUM+0
- sta CARD_SECNUM+1
- sta CARD_SECNUM+2
- lda #$0F
- sta CARD_SECNUM+3
-
- ; FALLTROUGH
-
-sdcard_init_getsize_done:
-
- ; Return sector number as maximum readable sector
-
- lda CARD_SECNUM+0
- sta CARD_SIZE+0
- lda CARD_SECNUM+1
- sta CARD_SIZE+1
- lda CARD_SECNUM+2
- sta CARD_SIZE+2
- lda CARD_SECNUM+3
- sta CARD_SIZE+3
-
- clc
- rts
-
-sdcard_init_getsize_fail:
-
- ; XXX mark card as inoperable
-
- sec
- rts
-
-
-
-;
-; Helper routines
-;
-
-
-sdcard_init_read:
-
- ; Trigger read
-
- lda #CARD_CMD_READ ; $02
- sta SD_CTL
-
- ; Wait for result
-
- ldx #90
-@1:
- jsr sdcard_wait_16000_usec
- lda SD_CTL
- and #$03
- beq @2
- dex
- bne @1
-
- ; Read failed
-
- sec
- rts
-@2:
- ;; Success
-
- clc
- rts
diff --git a/src/dos_m65/sdcard/sdcard_readsector.s b/src/dos_m65/sdcard/sdcard_readsector.s
deleted file mode 100644
index c2523185..00000000
--- a/src/dos_m65/sdcard/sdcard_readsector.s
+++ /dev/null
@@ -1,97 +0,0 @@
-
-;
-; Reads the sector from the SD card
-;
-
-; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
-
-
-; XXX provide documentation
-
-
-sdcard_readsector:
-
- ; XXX check if card initialized and operable
-
- ; Set read address
-
- jsr sdcard_set_addr
- bcs sdcard_readsector_fail
-
- ; FALLTROUGH
-
-sdcard_readsector_read:
-
- ; Set number of retries
-
- lda #$0A
- sta CARD_TMP_RETRIES
-
- ; FALLTROUGH
-
-sdcard_readsector_try_loop:
-
- ; Wait till card is ready
-
- jsr sdcard_wait_ready
- bcs sdcard_readsector_fail
-
- ; Read command
-
- lda #CARD_CMD_READ ; $02
- sta SD_CTL
-
- ; Wait for command completion
-
- jsr sdcard_wait_ready
- bcs sdcard_readsector_fail
-
- lda SD_CTL
- and #$67
- bne sdcard_readsector_copy_data
-
- jsr sdcard_reset
- dec CARD_TMP_RETRIES
- bne sdcard_readsector_try_loop
-
- ; FALLTROUGH
-
-sdcard_readsector_fail:
-
- sec
- rts
-
-
-;
-; Helper routines
-;
-
-sdcard_readsector_copy_data:
-
- ; XXX use DMAgic for this
-
- phz
- phx
-
- ldx #$00
- ldz #$00
-
-@1:
- lda [CARD_BUFPNT],z
- sta CARD_BUF,x
- inc CARD_BUFPNT+1
- lda [CARD_BUFPNT],z
- sta CARD_BUF+$100,x
- dec CARD_BUFPNT+1
-
- inz
- inx
- bne @1
-
- ; Restore registers and quit
-
- plx
- plz
-
- clc
- rts
diff --git a/src/dos_m65/sdcard/sdcard_reset.s b/src/dos_m65/sdcard/sdcard_reset.s
deleted file mode 100644
index 244233bf..00000000
--- a/src/dos_m65/sdcard/sdcard_reset.s
+++ /dev/null
@@ -1,32 +0,0 @@
-
-;
-; Resets the SD card
-;
-
-; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
-
-
-
-sdcard_reset:
-
- ldx #CARD_CMD_SDHC_OFF ; $40
- stx SD_CTL
- ldy #CARD_CMD_RESET ; $00
- sty SD_CTL
- ldy #CARD_CMD_END_RESET ; $01
- sty SD_CTL
-
- ; Wait till SD card resets
-@1:
- lda SD_CTL
- and #$03
- bne @1
-
- ; For SDHC card set appropriate mode
-
- bit CARD_IS_SDHC
- bpl @2
- ldx #CARD_CMD_SDHC_ON ; $41
- stx SD_CTL
-@2:
- rts
diff --git a/src/dos_m65/sdcard/sdcard_wait.s b/src/dos_m65/sdcard/sdcard_wait.s
deleted file mode 100644
index 59f89cb7..00000000
--- a/src/dos_m65/sdcard/sdcard_wait.s
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-sdcard_wait_16000_usec:
-
- ; Uses VIC-II raster register; wait time is not exactly precise, but should be
- ; a good approximation
-
- phx
- pha
-
- ldx #$FF
-
- ; XXX wait below is same as in KKERNAL, wait_x_lines - consider importing and reusing
- lda VIC_RASTER
-@1:
- cmp VIC_RASTER
- beq @1
- lda VIC_RASTER
- dex
- bne @1
-
- pla
- plx
-
- rts
diff --git a/src/dos_m65/sdcard/sdcard_writesector.s b/src/dos_m65/sdcard/sdcard_writesector.s
deleted file mode 100644
index e4e1ac25..00000000
--- a/src/dos_m65/sdcard/sdcard_writesector.s
+++ /dev/null
@@ -1,175 +0,0 @@
-
-;
-; Writes the sector to the SD card
-;
-
-; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c
-
-
-; XXX finish, provide documentation
-
-
-sdcard_writesector:
-
- ; XXX check if card initialized and operable
-
- lda SD_CTL
- and #$03
- bne sdcard_writesector ; XXX add a timer here
-
- ; End reset XXX is this needed? should this be done for sector reading too?
-
- lda #CARD_CMD_END_RESET ; $01
- sta SD_CTL
-
- ; Set write address
-
- jsr sdcard_set_addr
- bcs sdcard_writesector_fail
-
- ; FALLTROUGH
-
-sdcard_writesector_write:
-
- ; Set number of retries
-
- lda #$0A
- sta CARD_TMP_RETRIES
-
- ; FALLTROUGH
-
-sdcard_writesector_try_loop:
-
- jsr sdcard_writesector_copy_data
-
- ; Wait till card is ready
-
- jsr sdcard_wait_ready
- bcs sdcard_writesector_fail
-
- ; Write command
-
- lda #CARD_CMD_WRITE ; $03
- sta SD_CTL
-
- ; Wait for command completion
-
- jsr sdcard_wait_ready
- bcs sdcard_writesector_fail
-
- ; Check result
-
- lda SD_CTL
- and #$67
- bne sdcard_writesector_verify
-
- ; Write failed - retry
-
- jsr sdcard_reset
- dec CARD_TMP_RETRIES
- bne sdcard_writesector_try_loop
-
- ; FALLTROUGH
-
-sdcard_writesector_fail:
-
- sec
- rts
-
-sdcard_writesector_verify:
-
- ; There is a bug in the SD controller; you have to read between writes,
- ; or it gets really upset
-
-@1:
- lda SD_CTL
- and #$03
- bne @1
-
- lda #CARD_CMD_READ ; $02
- sta SD_CTL
-
-@2:
- lda SD_CTL
- and #$03
- beq @2
-
-@3: ; XXX deduplicate this ppart
- lda SD_CTL
- and #$03
- bne @3
-
- ; FALLTROUGH
-
-sdcard_writesector_verify_loop:
-
- ; Compare buffers
-
- phx
- phz
-
- ldx #$00
- ldz #$00
-
- lda [CARD_BUFPNT1],z
- cmp CARD_BUF, x
- bne sdcard_writesector_verify_fail
-
- lda [CARD_BUFPNT2],z
- cmp CARD_BUF+$100, x
- bne sdcard_writesector_verify_fail
-
- inz
- inx
- bne sdcard_writesector_verify_loop
-
- ; FALLTROUGH
-
-sdcard_writesector_verify_success:
-
- plz
- plx
-
- clc
- rts
-
-sdcard_writesector_verify_fail:
-
- plz
- plx
-
- sec
- rts
-
-
-;
-; Helper routines
-;
-
-sdcard_writesector_copy_data:
-
- ; XXX use DMAgic for this
-
- phz
- phx
-
- ldx #$00
- ldz #$00
-
-@1:
- lda CARD_BUF,x
- sta [CARD_BUFPNT1],z
- lda CARD_BUF+$100,x
- sta [CARD_BUFPNT2],z
-
- inz
- inx
- bne @1
-
- ; Restore registers and quit
-
- plx
- plz
-
- clc
- rts
diff --git a/src/dos_m65/stubs.s b/src/dos_m65/stubs.s
deleted file mode 100644
index 17c67de7..00000000
--- a/src/dos_m65/stubs.s
+++ /dev/null
@@ -1,22 +0,0 @@
-
-; Dummy implementations - XXX to be replaced with real ones
-
-dos_ACPTR:
- +nop
-dos_CIOUT:
- +nop
-dos_LISTEN:
- +nop
-dos_SECOND:
- +nop
-dos_TALK:
- +nop
-dos_TKSA:
- +nop
-dos_UNTLK:
- +nop
-dos_UNLSN:
- +nop
-
- sec
- rts
diff --git a/src/dos_m65/utils/util_dir_filesize.s b/src/dos_m65/utils/util_dir_filesize.s
new file mode 100644
index 00000000..ee8c4f2c
--- /dev/null
+++ b/src/dos_m65/utils/util_dir_filesize.s
@@ -0,0 +1,182 @@
+
+; Adapt the file size for displaying in a directory list
+
+
+util_dir_filesize_bytes: ; preserves .X
+
+ ; Convert file size in bytes (32-bit value) to blocks, afterwards
+ ; continue processing in 'util_dir_filesize_blocks'
+
+ ; Start from handling some large values
+
+ lda PAR_FSIZE_BYTES+3
+ +bne util_dir_filesize_max ; file over 16MB size
+ lda PAR_FSIZE_BYTES+2
+ inc
+ +beq util_dir_filesize_max ; file over 8MB size
+
+ ; Set initial size as 0 blocks
+
+ lda #$00
+ sta PAR_FSIZE_BLOCKS+0
+ sta PAR_FSIZE_BLOCKS+1
+
+ ; Calculate number of blocks
+
+ ldy #$03
+
+@lp:
+
+ lda PAR_FSIZE_BYTES+2
+ cmp util_dir_cmptab_hi,y
+ bcc @lp_next
+ bne @lp_adc_sbc
+ lda PAR_FSIZE_BYTES+1
+ cmp util_dir_cmptab_mi,y
+ bcc @lp_next
+ bne @lp_adc_sbc
+ lda PAR_FSIZE_BYTES+0
+ cmp util_dir_cmptab_lo,y
+ bcc @lp_next
+
+@lp_adc_sbc:
+
+ clc
+ lda PAR_FSIZE_BLOCKS+0
+ adc util_dir_addtab_lo,y
+ sta PAR_FSIZE_BLOCKS+0
+ lda PAR_FSIZE_BLOCKS+1
+ adc util_dir_addtab_hi,y
+ sta PAR_FSIZE_BLOCKS+1
+
+ sec
+ lda PAR_FSIZE_BYTES+0
+ sbc util_dir_cmptab_lo, y
+ sta PAR_FSIZE_BYTES+0
+ lda PAR_FSIZE_BYTES+1
+ sbc util_dir_cmptab_mi, y
+ sta PAR_FSIZE_BYTES+1
+ lda PAR_FSIZE_BYTES+2
+ sbc util_dir_cmptab_hi, y
+ sta PAR_FSIZE_BYTES+2
+
+ bra @lp
+
+@lp_next:
+
+ dey
+ bpl @lp
+
+ ; Correct for bytes not filling in the whole block
+
+ lda PAR_FSIZE_BYTES+0
+ beq util_dir_filesize_blocks
+
+ inc PAR_FSIZE_BLOCKS+0
+ bne util_dir_filesize_blocks
+ inc PAR_FSIZE_BLOCKS+1
+
+ ; FALLTROUGH
+
+util_dir_filesize_blocks: ; preserves .X
+
+ ; Take file size in blocks (16-bit value), clip to max 9999,
+ ; return in .Y the amount of spaces needed for indentation
+
+ lda PAR_FSIZE_BLOCKS+1
+ cmp #>9999
+ beq @cmp_9999_p2
+ bcs util_dir_filesize_max
+ bcc @size_ok
+
+@cmp_9999_p2:
+
+ lda PAR_FSIZE_BLOCKS+0
+ cmp #<9999
+ bcs util_dir_filesize_max
+
+@size_ok:
+
+ lda PAR_FSIZE_BLOCKS+1
+ beq @size_123
+
+@size_34: ; file size is 256 or above (3 or 4 digits)
+
+ cmp #>1000
+ beq @cmp_1000_p2
+ bcs util_dir_filesize_4
+ bra util_dir_filesize_3
+
+@cmp_1000_p2:
+
+ lda PAR_FSIZE_BLOCKS+0
+ cmp #<1000
+ bcs util_dir_filesize_4
+ bra util_dir_filesize_3
+
+@size_123: ; file size is 255 or below (1, 2, or 3 digits)
+
+ lda PAR_FSIZE_BLOCKS+0
+ cmp #10
+ bcs util_dir_filesize_23
+
+ ; FALLTROUGH
+
+util_dir_filesize_1: ; file size needs 1 digit
+
+ ldy #$03
+ rts
+
+util_dir_filesize_23: ; file size needs 2 or 3 digits, size in .A
+
+ cmp #100
+ bcs util_dir_filesize_3
+
+ ; FALLTROUGH
+
+util_dir_filesize_2: ; file size needs 2 digits
+
+ ldy #$02
+ rts
+
+util_dir_filesize_3: ; file size needs 3 digits
+
+ ldy #$01
+ rts
+
+util_dir_filesize_max:
+
+ lda #<9999
+ sta PAR_FSIZE_BLOCKS+0
+ lda #>9999
+ sta PAR_FSIZE_BLOCKS+1
+
+ ; FALLTROUGH
+
+util_dir_filesize_4: ; file size needs 4 digits
+
+ ldy #$00
+ rts
+
+
+; Tables for calculating blocks from bytes
+
+util_dir_addtab_hi:
+
+ !byte $00, $00 ; 2 next bytes same as in 'lo' table
+
+util_dir_addtab_lo:
+
+ !byte $01, $10, $00, $00
+
+util_dir_cmptab_hi:
+
+ !byte ^(254), ^(254 * 16), ^(254 * 16 * 16), ^(254 * 16 * 16 * 16), ^(254 * 16 * 16 * 16 * 16)
+
+util_dir_cmptab_mi:
+
+ !byte >(254), >(254 * 16), >(254 * 16 * 16), >(254 * 16 * 16 * 16), >(254 * 16 * 16 * 16 * 16)
+
+util_dir_cmptab_lo:
+
+ !byte <(254), <(254 * 16), <(254 * 16 * 16), <(254 * 16 * 16 * 16), <(254 * 16 * 16 * 16 * 16)
diff --git a/src/dos_m65/utils/util_dir_filter.s b/src/dos_m65/utils/util_dir_filter.s
new file mode 100644
index 00000000..9e20041b
--- /dev/null
+++ b/src/dos_m65/utils/util_dir_filter.s
@@ -0,0 +1,28 @@
+
+; Check if file name matches the filter (if so - Zero flag set)
+
+
+util_dir_filter:
+
+ lda PAR_FPATTERN
+ cmp #$A0
+ beq @done ; branch if no filter
+
+ ldy #$00
+
+@lp1:
+
+ lda PAR_FPATTERN, y
+ cmp #'*'
+ beq @done ; branch on wildcard
+
+ cmp PAR_FNAME, y
+ bne @done ; branch if does not match
+
+ iny
+ cpy #$10
+ bne @lp1 ; next iteration if maximum length not reached
+
+@done:
+
+ rts
diff --git a/src/dos_m65/utils/util_status.s b/src/dos_m65/utils/util_status.s
new file mode 100644
index 00000000..126f7a96
--- /dev/null
+++ b/src/dos_m65/utils/util_status.s
@@ -0,0 +1,125 @@
+
+; Set current status or error
+
+
+; XXX add code for handling the LEDs
+
+
+; .A = status to set
+
+util_status_SD:
+
+ ldx #$00
+ stx SD_STATUS_IDX ; set first byte of status to read
+ ldx #$00 ; offset to status buffer
+ bra util_status_common
+
+util_status_FD:
+
+ ldx #$00
+ stx FD_STATUS_IDX ; set first byte of status to read
+ ldx #$20 ; offset to status buffer
+ bra util_status_common
+
+util_status_RD:
+
+ ldx #$00
+ stx RD_STATUS_IDX ; set first byte of status to read
+ ldx #$40 ; offset to status buffer
+
+ ; FALLLTROUGH
+
+util_status_common:
+
+ ; Store the error number
+
+ taz
+ jsr util_status_store_number
+ jsr util_status_store_comma
+
+ ; Store the status / error string
+
+ tza ; prepare helper routine
+ tay
+ lda dos_sts_tab_lo, y
+ sta par_LDA_nnnn_Y+0
+ lda dos_sts_tab_hi, y
+ sta par_LDA_nnnn_Y+1
+
+ ldy #$00 ; copy the string
+@lp:
+ jsr code_LDA_nnnn_Y
+ beq @lp_end
+ sta XX_STATUS_STR, x
+ iny
+ inx
+ bra @lp
+
+@lp_end:
+
+ ; Store track and sector
+
+ jsr util_status_store_comma
+ lda PAR_TRACK
+ jsr util_status_store_number
+ jsr util_status_store_comma
+ lda PAR_SECTOR
+ jsr util_status_store_number
+
+ ; Mark end of status and quit
+
+ lda #$00
+ sta XX_STATUS_STR, x
+ rts
+
+util_status_store_comma:
+
+ ldy #','
+ sty XX_STATUS_STR, x
+ inx
+ rts
+
+util_status_store_number:
+
+ ; Check if number to store is 200 or above
+
+ cmp #200
+ bcc @store_00_199
+ ldy #'2'
+ sty XX_STATUS_STR, x
+ inx
+ sec
+ sbc #200
+ bra @store_00_99
+
+@store_00_199: ; number to store is within 00-199 range
+
+ cmp #100
+ bcc @store_00_99
+ ldy #'1'
+ sty XX_STATUS_STR, x
+ inx
+ sec
+ sbc #100
+
+@store_00_99: ; number to store is within 00-99 range - separate digits
+
+ ldy #'0'
+@lp:
+ cmp #10
+ bcc @store_finalize
+ iny
+ sec
+ sbc #10
+ bra @lp
+
+@store_finalize: ; first digit to store in .Y, second in .A (need no add '0')
+
+ sty XX_STATUS_STR, x
+ inx
+ clc
+ adc #'0'
+ sta XX_STATUS_STR, x
+ inx
+
+ rts
diff --git a/src/kernal/board_m65/mega65_iec_slow_fast.s b/src/kernal/board_m65/mega65_iec_slow_fast.s
deleted file mode 100644
index 310df6e3..00000000
--- a/src/kernal/board_m65/mega65_iec_slow_fast.s
+++ /dev/null
@@ -1,45 +0,0 @@
-;; #LAYOUT# M65 KERNAL_0 #TAKE
-;; #LAYOUT# * * #IGNORE
-
-;
-; Checks if system is in MEGA65 native mode; if so, switches CPU speed to fast/slow - for IEC routines;
-; Alters only status bits, all remaining registers preserved
-;
-
-!ifdef CONFIG_IEC {
-
-
-m65_iec_slow:
-
- jsr M65_MODEGET
- bcs m65_iec_fast_slow_done
-
- ; Switch CPU speed
-
- pha
- lda VIC_CTRLB
- and #%10111111
- bra m65_iec_fast_slow_common
-
-m65_iec_fast:
-
- jsr M65_MODEGET
- bcs m65_iec_fast_slow_done
-
- pha
- lda VIC_CTRLB
- ora #%01000000
-
- ; FALLTROUGH
-
-m65_iec_fast_slow_common:
-
- sta VIC_CTRLB
- pla
-
- ; FALLTROUGH
-
-m65_iec_fast_slow_done:
-
- rts
-}
diff --git a/src/kernal/board_m65/mega65_imports_1.s b/src/kernal/board_m65/mega65_imports_1.s
index fdad4bb5..1d5fd086 100644
--- a/src/kernal/board_m65/mega65_imports_1.s
+++ b/src/kernal/board_m65/mega65_imports_1.s
@@ -40,6 +40,9 @@
;; #ALIAS# viciv_hotregs_on = KERNAL_0.viciv_hotregs_on
;; #ALIAS# viciv_hotregs_off = KERNAL_0.viciv_hotregs_off
+;; #ALIAS# m65_speed_tape_cbdos = KERNAL_0.m65_speed_tape_cbdos
+;; #ALIAS# m65_speed_restore = KERNAL_0.m65_speed_restore
+
;; #ALIAS# m65_clr_magictstr = KERNAL_0.m65_clr_magictstr
;; #ALIAS# m65_scrtab_txtwidth = KERNAL_0.m65_scrtab_txtwidth
;; #ALIAS# m65_scrtab_txtheight = KERNAL_0.m65_scrtab_txtheight
diff --git a/src/kernal/board_m65/mega65_map_helpers.s b/src/kernal/board_m65/mega65_map_helpers.s
index 0c9005bf..8cfb5b59 100644
--- a/src/kernal/board_m65/mega65_map_helpers.s
+++ b/src/kernal/board_m65/mega65_map_helpers.s
@@ -76,12 +76,8 @@ map_DOS_1:
phy
phz
- lda #$80
- tab ; from now on, zeropage starts from $C000
-
ldy #$80
- lda #$30
- taz ; $8000 <- map 16KB RAM from $10000
+ ldz #$30 ; $8000 <- map 16KB RAM from $10000
lda #$C0
ldx #$C1 ; $4000 <- map 16KB ROM from $20000
@@ -89,19 +85,6 @@ map_DOS_1:
map
bra map_end_no_eom ; no EOM, we do not want interrupts within DOS!
-map_NORMAL_from_DOS_1:
-
- php
- pha
- phx
- phy
- phz
-
- lda #$00
- tab
-
- bra map_NORMAL_common
-
map_MON_1:
php
diff --git a/src/kernal/board_m65/mega65_speed.s b/src/kernal/board_m65/mega65_speed.s
new file mode 100644
index 00000000..537671b0
--- /dev/null
+++ b/src/kernal/board_m65/mega65_speed.s
@@ -0,0 +1,110 @@
+;; #LAYOUT# M65 KERNAL_0 #TAKE
+;; #LAYOUT# * * #IGNORE
+
+;
+; Checks if system is in MEGA65 native mode; if so, switches CPU speed to fast/slow for IO routines
+; Alters only status bits, all remaining registers preserved
+;
+
+; Entry points:
+; - m65_speed_iec - at the start of IEC operations
+; - m65_speed_tape_cbdos - at the start of tape or CBDOS operations
+; - m65_speed_restore - restore current mode standard speed, hide VIC-IV for compatibility mode
+
+
+!ifdef CONFIG_IEC {
+
+m65_speed_iec:
+
+ ; If compatibility mode, unlock VIC-IV
+
+ jsr M65_MODEGET
+ pha
+ bcc @1
+ jsr viciv_unhide
+@1:
+ ; Switch CPU speed to approx. 1 MHz
+
+ lda #%01000000
+ trb VIC_CTRLB
+
+ ; Disable badlines and slow interrupt emulation
+
+ bra m65_speed_tape_cbdos_ME
+}
+
+
+m65_speed_tape_cbdos:
+
+ ; If compatibility mode, unlock VIC-IV
+
+ jsr M65_MODEGET
+ pha
+ bcc @1
+ jsr viciv_unhide
+@1:
+ ; Set the maximum possible speed
+
+ lda #%01000000
+ tsb VIC_CTRLB
+
+ ; FALLTROUGH
+
+m65_speed_tape_cbdos_ME:
+
+ ; Disable badlines and slow interrupt emulation
+
+ lda #$00
+ sta MISC_EMU
+
+ pla
+ rts
+
+
+m65_speed_restore:
+
+ ; Restore proper speed depending on the mode
+
+ jsr M65_MODEGET
+ pha
+ bcc m65_speed_restore_native
+
+ ; FALLTROUGH
+
+m65_speed_restore_compat:
+
+ ; C64 compatibility mode - approx 1 MHz, badlines and slow interrupts enabled
+
+ lda #%01000000
+ trb VIC_CTRLB
+
+ ; FALLTROUGH
+
+m65_speed_ME_compat:
+
+ ; Reenable badlines and slow interrupt emulation
+
+ lda #$03
+ sta MISC_EMU
+
+ ; Hide the VIC-IV
+
+ sta VIC_KEY
+
+ ; Return
+
+ pla
+ rts
+
+m65_speed_restore_native:
+
+ ; Native mode - maximum speed
+
+ lda #%01000000
+ tsb VIC_CTRLB
+
+ ; All the special speed modes disable badlines and slow interrupts,
+ ; so there is no need to restore them
+
+ pla
+ rts
diff --git a/src/kernal/board_m65/mega65_tape_fast_cpu.s b/src/kernal/board_m65/mega65_tape_fast_cpu.s
deleted file mode 100644
index 0be56175..00000000
--- a/src/kernal/board_m65/mega65_tape_fast_cpu.s
+++ /dev/null
@@ -1,31 +0,0 @@
-;; #LAYOUT# M65 KERNAL_1 #TAKE
-;; #LAYOUT# * * #IGNORE
-
-;
-; Tape helper routine
-;
-; - unlocks VIC-IV
-; - switches CPU to fast processing mode and disables badlines
-; - stores previous VIC_CTRLB in NXTBIN
-;
-
-!ifdef HAS_TAPE {
-
-
-tape_fast_cpu:
-
- jsr M65_MODEGET
- bcc @1
-
- jsr viciv_unhide
-@1:
- lda VIC_CTRLB
- ora #%01000000
- sta VIC_CTRLB
- sta NXTBIT
-
- lda #$00
- sta MISC_EMU
-
- rts
-}
diff --git a/src/kernal/errors.s b/src/kernal/errors.s
index 917317d7..0f4bc83a 100644
--- a/src/kernal/errors.s
+++ b/src/kernal/errors.s
@@ -91,8 +91,8 @@ kernalerror_TOP_MEM_RS232:
lda #K_ERR_TOP_MEM_RS232
!ifdef CONFIG_MB_M65 {
- ; If in native mode, switch back to fast mode
- jsr m65_iec_fast
+ ; Restore the proper speed
+ jsr m65_speed_restore
}
sec
rts
diff --git a/src/kernal/iec/acptr.s b/src/kernal/iec/acptr.s
index 732d3b96..973f8bd4 100644
--- a/src/kernal/iec/acptr.s
+++ b/src/kernal/iec/acptr.s
@@ -24,7 +24,7 @@ ACPTR:
!ifdef CONFIG_MB_M65 {
jsr m65dos_check
- +bcc m65dos_acptr ; branch if device is handeld by internal DOS
+ +bcc m65dos_acptr ; branch if device is handeld by internal DOS
}
!ifdef CONFIG_IEC {
diff --git a/src/kernal/iec/iec_return.s b/src/kernal/iec/iec_return.s
index bf9972f7..c80323b7 100644
--- a/src/kernal/iec/iec_return.s
+++ b/src/kernal/iec/iec_return.s
@@ -26,8 +26,8 @@ iec_return_success:
+plx_trash_a
!ifdef CONFIG_MB_M65 {
- ; If in native mode, switch back to fast mode
- jsr m65_iec_fast
+ ; Restore the proper speed
+ jsr m65_speed_restore
}
; Report success
diff --git a/src/kernal/iec/iec_rx_byte.s b/src/kernal/iec/iec_rx_byte.s
index fc565c85..61a7329c 100644
--- a/src/kernal/iec/iec_rx_byte.s
+++ b/src/kernal/iec/iec_rx_byte.s
@@ -17,8 +17,8 @@
iec_rx_dispatch:
!ifdef CONFIG_MB_M65 {
- ; If in native mode, switch to 1 MHz
- jsr m65_iec_slow
+ ; Ensure 1 Mhz mode and disabled badlines
+ jsr m65_speed_iec
}
lda IECPROTO
@@ -33,8 +33,8 @@ iec_rx_dispatch:
iec_rx_byte:
!ifdef CONFIG_MB_M65 { !ifndef CONFIG_IEC_JIFFYDOS {
- ; If in native mode, switch to 1 MHz
- jsr m65_iec_slow
+ ; Ensure 1 Mhz mode and disabled badlines
+ jsr m65_speed_iec
} }
; Store .X and .Y on the stack - preserve them
@@ -161,8 +161,8 @@ iec_rx_acknowledge:
iec_rx_end:
!ifdef CONFIG_MB_M65 {
- ; If in native mode, switch back to fast mode
- jsr m65_iec_fast
+ ; Restore the proper speed
+ jsr m65_speed_restore
}
+ply_trash_a
diff --git a/src/kernal/iec/iec_send_file_name.s b/src/kernal/iec/iec_send_file_name.s
index 19cd316b..e32c76d3 100644
--- a/src/kernal/iec/iec_send_file_name.s
+++ b/src/kernal/iec/iec_send_file_name.s
@@ -11,11 +11,18 @@
iec_send_file_name:
- ldy #0
+
+ ldy #$00
+
+!ifdef CONFIG_MB_M65 {
+ jsr m65dos_check
+ +bcc m65dos_send_file_name_loop ; branch if device is handeld by internal DOS
+}
iec_send_file_name_loop:
+
cpy FNLEN
- beq iec_send_file_name_done
+ +beq UNLSN
!ifdef CONFIG_MEMORY_MODEL_60K {
ldx #return_from_interrupt
- sta CINV+1
+ ; XXX uncomment this when debugging is finished
+ ; lda #return_from_interrupt
+ ; sta CINV+1
; Make sure $C000-$CFFF ROM is mapped-in, we keep our proxies there
; Also make sure the palette is taken from RAM
@@ -51,16 +52,24 @@ ZVM: ; entry point
; Check if extended memory is present
- jsr ZVM_memtest
+ ; XXX enable test jsr ZVM_memtest
+
+ ; Generate CPU tables, reset the CPU
+
+ jsr Z80_table_gen
+ ; XXX jsr Z80_reset_MEM
+ jsr Z80_reset_CPU
+
+ ; Try CPU test
+
+ jsr ZVM_cputest
- ; Generate CPU tables
- jsr z80_table_gen
; XXX code is not ready to progress further
jsr PRIMM
!pet $0D, "Implementation not finished yet.", 0
- jmp ZVM_halt
+ jmp ZVM_syshalt
jmp zvm_BIOS_00_BOOT
@@ -82,12 +91,10 @@ ZVM: ; entry point
-
-
ZVM_memtest:
; Simple memory test
- ; XXX this test is temporary
+ ; XXX this test fails for now
lda #$00
sta PTR_DATA+0
@@ -98,7 +105,7 @@ ZVM_memtest:
ldx #$F0
@1:
- ldy #$00
+ ldy #$10
@2:
lda PTR_DATA+2
eor #%01111111
@@ -130,7 +137,7 @@ ZVM_halt_memtest_failed:
; FALLTROUGH
-ZVM_halt:
+ZVM_syshalt:
jsr PRIMM
!pet " * System HALTED *", 0
diff --git a/src/zvm_m65/zvm_bios.s b/src/zvm_m65/zvm_bios.s
index 86d6b7f4..e3454ff0 100644
--- a/src/zvm_m65/zvm_bios.s
+++ b/src/zvm_m65/zvm_bios.s
@@ -55,9 +55,9 @@ zvm_BIOS_00_BOOT: ; Cold start
; XXX fetch RAM disk image, CPM3.SYS, command interpreter
; XXX close all the files, reset I/O, set screen mode
- ; XXX clear memory
- jsr Z80_reset
+ jsr Z80_reset_MEM
+ jsr Z80_reset_CPU
; FALLTROUGH
diff --git a/src/zvm_m65/zvm_cpmemu.s b/src/zvm_m65/zvm_cpmemu.s
new file mode 100644
index 00000000..168a105d
--- /dev/null
+++ b/src/zvm_m65/zvm_cpmemu.s
@@ -0,0 +1,37 @@
+
+;
+; Z80 Virtual Machine CP/M simulation (just to run selected binaries)
+;
+
+
+zvm_CPMemu:
+
+ ldx REG_C
+ cpx #$09
+ beq zvm_CPMemu_09
+ cpx #$02
+ beq zvm_CPMemu_02
+
+ ; XXX implement additional functions if needed
+
+ ; FALLTROUGH
+
+zvm_CPMemu_end:
+
+ jmp Z80_instr_C9 ; RET
+
+zvm_CPMemu_02: ; C_WRITE
+
+ lda REG_E
+ jsr CHROUT
+ bra zvm_CPMemu_end
+
+zvm_CPMemu_09: ; C_WRITESTR
+
+ +Z80_FETCH_VIA_DE
+ cmp #$24 ; CP/M string termination character
+ beq zvm_CPMemu_end
+
+ jsr CHROUT
+ inw REG_DE
+ bra zvm_CPMemu_09
diff --git a/src/zvm_m65/zvm_cputest.s b/src/zvm_m65/zvm_cputest.s
new file mode 100644
index 00000000..94601f4d
--- /dev/null
+++ b/src/zvm_m65/zvm_cputest.s
@@ -0,0 +1,176 @@
+
+;
+; Z80 Virtual Machine CPU test
+;
+
+
+ZVM_cputest:
+
+ ; XXX move loading code to separate routine(s)
+
+
+ ; Copy file name to RAM
+
+ ldx #$FF
+
+@loop1:
+
+ inx
+ lda ZVM_filename_Z80TEST, x
+ sta BUF, x
+ bne @loop1
+
+ ; Set Z80TEST.COM file name
+
+ ldy #>BUF
+ ldx #