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 #