Merge pull request #65 from FeralChild64/master

Loading files from D81 image on MEGA65
This commit is contained in:
FeralChild64 authored and GitHub committed 2021-03-25 19:43:16 +01:00
commit f0ce905b88
58 files changed
+1545 -601

No files matched your search

+6
View File
@@ -175,6 +175,12 @@ Enable this option if you are using a tape interface adapter with some audio sig
Enable this option if you are using a tape interface adapter lacking tape motor control (most likely every adapter currently being sold) - this will eliminate the need to quickly press space when the program header information gets displayed. Note: if you are using a cassette player with REM port, and your adapter is connected to this port too, than you do not need this option.
## Additional storage
### `UNIT_SDCARD`, `UNIT_FLOPPY`, `UNIT_RAMDISK`
MEGA65 specific pseudo-IEC devices, handled by internal DOS (work in progress). If set to 0, given unit is disabled. Otherwise - assigns IEC unit number to the given storage.
## Sound support
The original Commodore 64 had one SID sound chip installed. However, mods exists to add more of them for improved sound capabilities. Emulators and FPGA machines typically allow to simulate more than one too. Unfortunately, there is no standard regarding how these additional chips are visible in the processor address space, and there is no sane way to detect it - thus, it has to be configurable.
+49 -43
View File
@@ -63,9 +63,13 @@ SRCDIR_KERNAL = $(SRCDIR_COMMON) \
SRCDIR_DOS_M65 = $(SRCDIR_COMMON) \
src/dos_m65 \
src/dos_m65/assets \
src/dos_m65/dev_floppy \
src/dos_m65/dev_ramdisk \
src/dos_m65/dev_sdcard \
src/dos_m65/filesystem_cbm \
src/dos_m65/filesystem_vfs \
src/dos_m65/lowlevel \
src/dos_m65/pseudoiec \
src/dos_m65/unit_floppy \
src/dos_m65/unit_ramdisk \
src/dos_m65/unit_sdcard \
src/dos_m65/utils
SRCDIR_MON_M65 = $(SRCDIR_COMMON) \
@@ -327,15 +331,17 @@ build/tools/%: tools/%.cc tools/common.h
# Rules - CHARGEN
$(TARGET_CHR_ORF): $(TOOL_PNGPREPARE) assets/8x8font.png
@$(TOOL_PNGPREPARE) charrom assets/8x8font.png $@ 1>build/pngprepare.log
@$(TOOL_PNGPREPARE) charrom assets/8x8font.png $@ 1>/dev/null
$(TARGET_CHR_PXL): bin/chargen_pxlfont_2.3.rom
@cp $< $@
build/chargen_openroms.patched: $(TOOL_PATCH_CHARGEN) $(TARGET_CHR_ORF)
build/patched_chargen/openroms.pcg: $(TOOL_PATCH_CHARGEN) $(TARGET_CHR_ORF)
@mkdir -p build/patched_chargen
@$(TOOL_PATCH_CHARGEN) -i $(TARGET_CHR_ORF) -o $@ -n 7px-OpenROMs
build/chargen_pxlfont.patched: $(TOOL_PATCH_CHARGEN) $(TARGET_CHR_PXL)
build/patched_chargen/pxlfont.pcg: $(TOOL_PATCH_CHARGEN) $(TARGET_CHR_PXL)
@mkdir -p build/patched_chargen
@$(TOOL_PATCH_CHARGEN) -i $(TARGET_CHR_PXL) -o $@ -n 6px-PXLfont
# Dependencies - BASIC, DOS, and KERNAL
@@ -699,21 +705,21 @@ build/symbols_hybrid_u64.vs: $(DIR_U64)/KERNAL_combined.vs
# Rules - padding files
build/padding_4_KB:
@mkdir -p build
build/padding/4_KB:
@mkdir -p build/padding
@dd if=/dev/zero bs=4096 count=1 of=$@ status=none
build/padding_8_KB:
@mkdir -p build
build/padding/8_KB:
@mkdir -p build/padding
@dd if=/dev/zero bs=8192 count=1 of=$@ status=none
build/padding_16_KB:
@mkdir -p build
build/padding/16_KB:
@mkdir -p build/padding
@dd if=/dev/zero bs=8192 count=2 of=$@ status=none
# Rules - external CRT images
$(TARGET_GENCRT_X): $(SEG_LIST_GENCRT) $(CRT_BIN_LIST) build/padding_8_KB
$(TARGET_GENCRT_X): $(SEG_LIST_GENCRT) $(CRT_BIN_LIST) build/padding/8_KB
@echo
@echo
@echo
@@ -724,14 +730,14 @@ $(TARGET_GENCRT_X): $(SEG_LIST_GENCRT) $(CRT_BIN_LIST) build/padding_8_KB
@cat assets/cartridge/header-seg0.bin >> $@
@cat $(DIR_GENCRT)/basic.seg_1 >> $@
@cat assets/cartridge/header-seg1.bin >> $@
@cat build/padding_8_KB >> $@
@cat build/padding/8_KB >> $@
@cat assets/cartridge/header-seg2.bin >> $@
@cat $(DIR_GENCRT)/kernal.seg_1 >> $@
@cat assets/cartridge/header-seg3.bin >> $@
@cat build/padding_8_KB >> $@
@cat build/padding/8_KB >> $@
@echo
$(TARGET_U64CRT_X): $(SEG_LIST_U64CRT) $(CRT_BIN_LIST) build/padding_8_KB
$(TARGET_U64CRT_X): $(SEG_LIST_U64CRT) $(CRT_BIN_LIST) build/padding/8_KB
@echo
@echo
@echo
@@ -742,11 +748,11 @@ $(TARGET_U64CRT_X): $(SEG_LIST_U64CRT) $(CRT_BIN_LIST) build/padding_8_KB
@cat assets/cartridge/header-seg0.bin >> $@
@cat $(DIR_U64CRT)/basic.seg_1 >> $@
@cat assets/cartridge/header-seg1.bin >> $@
@cat build/padding_8_KB >> $@
@cat build/padding/8_KB >> $@
@cat assets/cartridge/header-seg2.bin >> $@
@cat $(DIR_U64CRT)/kernal.seg_1 >> $@
@cat assets/cartridge/header-seg3.bin >> $@
@cat build/padding_8_KB >> $@
@cat build/padding/8_KB >> $@
@echo
# Rules - MEGA65 platform specific
@@ -763,43 +769,43 @@ $(TARGET_U64CRT_X): $(SEG_LIST_U64CRT) $(CRT_BIN_LIST) build/padding_8_KB
# $1:$2000 - 24 KB - Z80 Virtual Machine for CP/M
# $1:$8000 - 32 KB - unused for now, padding; most likely will be used for BASIC extensions
$(TARGET_M65_x_ORF) $(TARGET_M65_x_PXL): $(SEG_LIST_M65) build/padding_16_KB $(TARGET_CHR_ORF) build/chargen_openroms.patched $(TARGET_CHR_PXL) build/chargen_pxlfont.patched
$(TARGET_M65_x_ORF) $(TARGET_M65_x_PXL): $(SEG_LIST_M65) build/padding/16_KB $(TARGET_CHR_ORF) build/patched_chargen/openroms.pcg $(TARGET_CHR_PXL) build/patched_chargen/pxlfont.pcg
@echo
@echo
@echo
@echo //-------------------------------------------------------------------------------------------
@echo // Making ROM image for MEGA65 - with Open ROMs chargen
@echo //-------------------------------------------------------------------------------------------
@cat $(DIR_M65)/dos.seg_1 > $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x_ORF)
@cat build/chargen_openroms.patched >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/kernal.seg_C >> $(TARGET_M65_x_ORF)
@cat $(TARGET_CHR_ORF) >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/mon.seg_1 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/zvm.seg_1 >> $(TARGET_M65_x_ORF)
@cat build/padding_16_KB >> $(TARGET_M65_x_ORF)
@cat build/padding_16_KB >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/dos.seg_1 > $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x_ORF)
@cat build/patched_chargen/openroms.pcg >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/kernal.seg_C >> $(TARGET_M65_x_ORF)
@cat $(TARGET_CHR_ORF) >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/mon.seg_1 >> $(TARGET_M65_x_ORF)
@cat $(DIR_M65)/zvm.seg_1 >> $(TARGET_M65_x_ORF)
@cat build/padding/16_KB >> $(TARGET_M65_x_ORF)
@cat build/padding/16_KB >> $(TARGET_M65_x_ORF)
@echo
@echo
@echo
@echo //-------------------------------------------------------------------------------------------
@echo // Making ROM image for MEGA65 - with PXL font chargen
@echo //-------------------------------------------------------------------------------------------
@cat $(DIR_M65)/dos.seg_1 > $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x_PXL)
@cat build/chargen_pxlfont.patched >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/kernal.seg_C >> $(TARGET_M65_x_PXL)
@cat $(TARGET_CHR_PXL) >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/mon.seg_1 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/zvm.seg_1 >> $(TARGET_M65_x_PXL)
@cat build/padding_16_KB >> $(TARGET_M65_x_PXL)
@cat build/padding_16_KB >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/dos.seg_1 > $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x_PXL)
@cat build/patched_chargen/pxlfont.pcg >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/kernal.seg_C >> $(TARGET_M65_x_PXL)
@cat $(TARGET_CHR_PXL) >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/mon.seg_1 >> $(TARGET_M65_x_PXL)
@cat $(DIR_M65)/zvm.seg_1 >> $(TARGET_M65_x_PXL)
@cat build/padding/16_KB >> $(TARGET_M65_x_PXL)
@cat build/padding/16_KB >> $(TARGET_M65_x_PXL)
@echo
# Rules - platform 'Commander X16' specific
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+5 -5
View File
@@ -65,9 +65,9 @@
;; #CONFIG# KEYCMD_HELP "LIST"
;; #CONFIG# KEYCMD_F9 "@20$"
;; #CONFIG# KEYCMD_F9 "@28$"
;; #CONFIG# KEYCMD_F10 "\5FL"
;; #CONFIG# KEYCMD_F11 "COLORSET 128"
;; #CONFIG# KEYCMD_F11 "@29$"
;; #CONFIG# KEYCMD_F12 "\5FHF"
;; #CONFIG# KEYCMD_F13 "JOYCRSR 2"
;; #CONFIG# KEYCMD_F14 "BOOTCPM"
@@ -90,9 +90,9 @@
; --- Built-in DOS configuration
;; #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
;; #CONFIG# UNIT_SDCARD 28
;; #CONFIG# UNIT_FLOPPY 29
;; #CONFIG# UNIT_RAMDISK 0 ; do not change, ram disk is not implemented yet
; --- Debug options
+21
View File
@@ -29,6 +29,27 @@
!addr VIC_PALSEL = $D070 ; - palette selection register
; Floppy controller registers
!addr FDC_CONTROL = $D080
!addr FDC_COMMAND = $D081
!addr FDC_STATUS_A = $D082
!addr FDC_STATUS_B = $D083
!addr FDC_TRACK = $D084
!addr FDC_SECTOR = $D085
!addr FDC_SIDE = $D086
!addr FDC_DATA = $D087
!addr FDC_CLOCK = $D088
!addr FDC_STEP = $D089
!addr FDC_PCODE = $D08A
!addr FDC_DBG0 = $D6A0
!addr FDC_DBG1 = $D6A1
!addr FDC_DATARATE = $D6A2
!addr FDC_LAST_TRACK = $D6A3
!addr FDC_LAST_SECTOR = $D6A4
!addr FDC_LAST_SIODE = $D6A5
; Palette memory areas
!addr PALETTE_R = $D100
+2 -2
View File
@@ -31,11 +31,11 @@ INITMSG_native:
; Native mode
ldx #44
ldx #46
ldy #0
jsr M65_SETWIN_XY
ldx #36
ldx #34
ldy #9
jsr M65_SETWIN_WH
+83 -19
View File
@@ -45,13 +45,13 @@
; Helper subroutines to fetch data
!addr code_LDA_nnnn_Y = $8014 ; - LDA nnnn, Y instruction
!addr par_LDA_nnnn_Y = $8015 ; - 2 bytes; address in buffer, ram disk
!addr par_LDA_nnnn_Y = $8015 ; - 2 bytes; address
!addr code_RTS_04 = $8017 ; - RTS instruction
; Parameters for utilities/helkpers
; Parameters for utilities/helpers
!addr PAR_TRACK = $8018 ; track number for status/error
!addr PAR_SECTOR = $8019 ; sector number for status/error
!addr PAR_TRACK = $8018 ; track number, also for status/error
!addr PAR_SECTOR = $8019 ; sector number, also 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
@@ -109,26 +109,90 @@
!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
; Various, most likely to be reworked
!addr SD_DESC = $8070 ; current file descriptor
!addr FD_DIRENT = $8071 ; directory entry to read, 0-15
!addr FD_LOADTRACK = $8072 ; current track for file loading
!addr FD_LOADSECTOR = $8073 ; current sector for file loading
; XXX Free space
;
; Further pages
; Various buffers, caches, and other large memory chunks
;
!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
; General purpose buffers, 512 bytes each, each starts at page start - XXX dynamic alllocation to be written
!addr SD_MEMSHADOW = $8310 ; 256 byte buffer for preserving original memory content
!addr SD_FILEBUF = $8410 ; 512 byte buffer for file reading
!addr SHARED_BUF_0 = $8200 ; XXX temporarily hardcoded for usage by SD card
!addr SHARED_BUF_1 = $8400 ; XXX temporarily hardcoded for usage by floppy
!addr SHARED_BUF_2 = $8600
!addr SHARED_BUF_3 = $8800
!addr SHARED_BUF_4 = $8A00
!addr SHARED_BUF_5 = $8C00
!addr SHARED_BUF_6 = $8E00
!addr SHARED_BUF_7 = $9000
!addr SHARED_BUF_8 = $9200
!addr SHARED_BUF_9 = $9400
!addr SHARED_BUF_A = $9600
!addr SHARED_BUF_B = $9800
!addr SHARED_BUF_C = $9A00
!addr SHARED_BUF_D = $9C00
!addr SHARED_BUF_E = $9E00
!addr SHARED_BUF_F = $A000
!addr SD_DESC = $8610 ; current file descriptor
; BAM cache for floppy drives; 2 KB (4 blocks) each, to cover up to ED floppies
!addr FD_BAM_CACHE_0 = $A200 ; - floppy disk 0 BAM
!addr SHARED_BUF_X0 = $A400 ; - buffer which can be used if disk is not ED
!addr FD_BAM_CACHE_1 = $A600 ; - floppy disk 1 BAM
!addr SHARED_BUF_X1 = $A800 ; - buffer which can be used if disk is not ED
; Memory shadow, needed for SD card support
!addr SD_MEMSHADOW_BUF = $AA00 ; 256 byte buffer for preserving original memory content
; Command/filename buffers, 128 bytes each - XXX extend to 256 bytes (change implementation)
!addr SD_CMDFN_BUF = $AB00 ; - SD card
!addr FD_CMDFN_BUF = $AC00 ; - floppy
!addr RD_CMDFN_BUF = $AD00 ; - ram disk
; Directory entry buffers, in BASIC format, $30 bytes each
!addr XX_DIRENT_BUF = $AE00
!addr SD_DIRENT_BUF = $AE00 ; - SD card
!addr FD_DIRENT_BUF = $AE30 ; - floppy
!addr RD_DIRENT_BUF = $AE60 ; - ram disk
; Status buffers, content terminated by 0, $30 bytes each
!addr XX_STATUS_BUF = $AE90
!addr SD_STATUS_BUF = $AE90 ; - SD card
!addr FD_STATUS_BUF = $AEC0 ; - floppy
!addr RD_STATUS_BUF = $AEF0 ; - ram disk
; Shared buffer metadata tables, 18 bytes each
!addr BUFTAB_UNIT = $AF20 ; which unit the buffer is assigned to
!addr BUFTAB_DEV = $AF32 ; which device within the unit
!addr BUFTAB_TRACK = $AF44 ; which track (or other kind of handle)
!addr BUFTAB_SECTOR = $AF56 ; which sector is stored in the first half of the buffer
; Common DMA list, 15 bytes
!addr DMAJOB_LIST = $AF68
!addr DMAJOB_SRC_MB = DMAJOB_LIST+2
!addr DMAJOB_DST_MB = DMAJOB_LIST+4
!addr DMAJOB_SIZE = DMAJOB_LIST+7 ; keep $0200 here
!addr DMAJOB_SRC_ADDR = DMAJOB_LIST+9
!addr DMAJOB_DST_ADDR = DMAJOB_LIST+12
;
; Reserved 20 KB for floppy track buffers + some area still free
;
!addr XX_REMAINING = $AF87
+11
View File
@@ -0,0 +1,11 @@
dos_dmalist_template:
!byte $0A ; use F018A list format (it is shorter by 1 byte)
!byte $80, $00 ; src. address is $00xxxxx
!byte $81, $00 ; dst. address is $00xxxxx
!byte $00 ; end of options
!byte $00 ; operation: COPY
!word $0200 ; data size if 512 bytes
; 3 bytes of src address + 3 bytes of dst address - not included in template
+9 -6
View File
@@ -11,7 +11,7 @@ dir_hdr: ; 32 bytes - header
!byte $12, $22 ; reverse mode, quote
!pet " " ; space for disk/directory name
!byte $22, $20 ; quote, space
!pet "00 2a" ; default ID, disk format
!pet " 2a" ; default ID, disk format
!byte $00 ; end of the line
dir_hdr_sd: ; 32 bytes - header
@@ -20,7 +20,8 @@ dir_hdr_sd: ; 32 bytes - header
!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
!pet "sd card" ; space for disk/directory name
!byte $A0, $A0, $A0, $A0, $A0, $A0, $A0, $A0, $A0
!byte $22, $20 ; quote, space
!pet "fat32" ; filesystem
!byte $00 ; end of the line
@@ -36,10 +37,12 @@ dir_end: ; 19 bytes
dir_types:
!pet "seq", $00 ; SEQ
!pet "prg", $00 ; PRG
!pet "usr", $00 ; USR
!pet "rel", $00 ; REL
!pet "del", $00 ; deleted file
!pet "seq", $00 ; sequential file
!pet "prg", $00 ; program (executable)
!pet "usr", $00 ; user type
!pet "rel", $00 ; random access file
!pet "cbm", $00 ; CBM-style partition
!pet "dir", $00 ; directory
; File types below are not mandatory
-12
View File
@@ -1,12 +0,0 @@
;
; Read more data into the buffer
;
dev_fd_cmd_READ:
; XXX provide implementation
sec ; mark EOI
rts
-17
View File
@@ -1,17 +0,0 @@
;
; 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
-250
View File
@@ -1,250 +0,0 @@
;
; 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+0
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+0
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
-151
View File
@@ -1,151 +0,0 @@
;
; 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+0
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
+27 -8
View File
@@ -4,10 +4,6 @@
;
!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
@@ -43,11 +39,28 @@ dos_INIT:
sta IDX1_TALKER
sta IDX2_TALKER
; Initialize device handlers
; Initialize buffer metadata
jsr dev_sd_init
jsr dev_fd_init
jsr dev_rd_init
lda #$0
ldx #17
@2:
sta BUFTAB_TRACK, x
dec
sta BUFTAB_UNIT, x
sta BUFTAB_DEV, x
sta BUFTAB_SECTOR, x
inc
dex
bpl @2
; Initialize DMA list
ldy #$08
@3:
lda dos_dmalist_template, y
sta DMAJOB_LIST, y
dey
bpl @3:
; Initialize helper code in RAM
@@ -65,6 +78,12 @@ dos_INIT:
sta code_RTS_03
sta code_RTS_04
; Initialize device handlers
jsr unit_sd_init
jsr unit_fd_init
jsr unit_rd_init
; Safer version of 'dos_EXIT' - does not affect speed related registers
clc
-18
View File
@@ -1,18 +0,0 @@
;
; 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
+18
View File
@@ -0,0 +1,18 @@
;
; Vector tables to device-specific routines
;
dos_cmd_OPEN_vectab:
!word unit_sd_cmd_OPEN
!word unit_fd_cmd_OPEN
!word unit_rd_cmd_OPEN
dos_cmd_CLOSE_vectab:
!word unit_sd_cmd_CLOSE
!word unit_fd_cmd_CLOSE
!word unit_rd_cmd_CLOSE
@@ -0,0 +1,133 @@
;
; CBM/CMD filesystem - helper routine to get the next directory entry
;
; Fills-in: PAR_FNAME, PAR_FTYPE, PAR_FSIZE_BYTES
; XXX work-in-progress, this should be used within directory reading code
fs_cbm_nextdirentry:
lda FD_DIRENT
; If first entry within sector - make sure it is present within the buffer
cmp #$08
beq @get_sector_lo
cmp #$10
+beq @get_sector_hi
; FALLTROUGH
@cont:
; Set address of the RAW directory entry
ldy #>SHARED_BUF_1
sty par_LDA_nnnn_Y+1
asl
asl
asl
asl
asl
sta par_LDA_nnnn_Y+0
bcc @1
inc par_LDA_nnnn_Y+1
@1:
; Set next directory entry
inc FD_DIRENT
; Copy data to parameter variables
; XXX most likely copying is not necessary (compare all CBM and CMD filesystems) -
; XXX just make the hypervisor file system emulate these structures
ldy #$02 ; determining file type
jsr code_LDA_nnnn_Y
beq fs_cbm_nextdirentry ; ignore deleted files (but allow DEL files in some cases)
tax
and #%00111111 ; for checking, filter out special bits
cmp #$06
bcs fs_cbm_nextdirentry ; ignore unknown file types
stx PAR_FTYPE
ldy #$1E ; get file size in blocks
jsr code_LDA_nnnn_Y
sta PAR_FSIZE_BLOCKS+0
iny
jsr code_LDA_nnnn_Y
sta PAR_FSIZE_BLOCKS+1
ldy #$03 ; get file starting track and sector
jsr code_LDA_nnnn_Y
sta FD_LOADTRACK
iny
jsr code_LDA_nnnn_Y
sta FD_LOADSECTOR
iny ; copy the file name
@lp1:
jsr code_LDA_nnnn_Y
sta PAR_FNAME-5,y
iny
cpy #$15
bne @lp1
clc
rts
@get_sector_lo: ; processing the 1st half of the buffer finished
; Check if this was the last sector
lda SHARED_BUF_1+0
beq @end_of_dir
; Load the next sector
sta PAR_TRACK
lda SHARED_BUF_1+1
sta PAR_SECTOR
bra @get_sector_common
@get_sector_hi: ; processing the 2nd half of the buffer finished
; Check if this was the last sector
lda SHARED_BUF_1+$100+0
beq @end_of_dir
; Load the next sector
sta PAR_TRACK
lda SHARED_BUF_1+$100+1
sta PAR_SECTOR
@get_sector_common:
jsr lowlevel_readsector ; XXX handle read errors
; Set new FD_DIRENT
lda PAR_SECTOR
and #$01
beq @2
lda #$08
@2:
sta FD_DIRENT
jmp @cont
@end_of_dir:
sec
rts
@@ -0,0 +1,109 @@
;
; CBM/CMD filesystem - helper routine to get the next file block
;
fs_cbm_nextfileblock:
; Fetch the next track/sector
lda PAR_SECTOR
and #$01
bne @part_2
@part_1:
; We were reading from the 1st half of the buffer
ldx SHARED_BUF_1+1
lda SHARED_BUF_1+0
bra @common_chk
@part_2:
; We were reading from the 2nd half of the buffer
ldx SHARED_BUF_1+$100+1
lda SHARED_BUF_1+$100+0
@common_chk:
bne fs_cbm_nextfileblock_common_load
; FALLTROUGH
fs_cbm_nextfileblock_eof:
lda #$00 ; end of file
sec
rts
fs_cbm_nextfileblock_common_load:
sta PAR_TRACK
stx PAR_SECTOR
; FALLTROUGH
fs_cbm_nextfileblock_got_ts:
; Load next track/sector
jsr lowlevel_readsector ; XXX handle read errors
; Store pointer and amount of data ready to fetch
lda #$FE
sta FD_ACPTR_LEN+0
lda #$00
sta FD_ACPTR_LEN+1
lda #$02
sta FD_ACPTR_PTR+0
lda #>SHARED_BUF_1
sta FD_ACPTR_PTR+1
lda PAR_SECTOR
and #$01
bne @part_2
@part_1:
; Sector with data is located in the 1st half of the buffer
lda SHARED_BUF_1+0
bne @exit
; Less than a full sector is used
lda SHARED_BUF_1+1
bra @not_full_buf
@part_2:
; Sector with data is located in the 2nd half of the buffer
inc FD_ACPTR_PTR+1
lda SHARED_BUF_1+$100+0
bne @exit
; Less than a full sector is used
lda SHARED_BUF_1+$100+1
@not_full_buf:
dec
cmp #$FF
beq fs_cbm_nextfileblock_eof
sta FD_ACPTR_LEN+0
; FALLTROUGH
@exit:
clc
rts
@@ -0,0 +1,201 @@
;
; CBM/CMD virtual filesystem - reading directory
;
fs_cbm_read_dir_open:
; Try to read track 40, sector 0 (disk header)
lda #40
sta PAR_TRACK
lda #$00
sta PAR_SECTOR
jsr lowlevel_readsector ; XXX handle read errors
; Create the first directory listing entry (title, id)
ldx #$1F ; first fetch the template
@lp1:
lda dir_hdr,x
sta FD_DIRENT_BUF,x
dex
bpl @lp1
ldx #$0F ; file name
@lp2:
lda SHARED_BUF_1+$04,x
sta FD_DIRENT_BUF+$08,x
dex
bpl @lp2
lda SHARED_BUF_1+$16 ; disk ID XXX test this on a disk with ID
cmp #$A0
beq @skip1
sta FD_DIRENT_BUF+$1A
@skip1:
lda SHARED_BUF_1+$17
cmp #$A0
beq @skip2
sta FD_DIRENT_BUF+$1B
@skip2:
lda SHARED_BUF_1+$19 ; dos version
sta FD_DIRENT_BUF+$1D
lda SHARED_BUF_1+$1A
sta FD_DIRENT_BUF+$1E
; Provide pointer to the header
lda #$20
sta FD_ACPTR_LEN+0
lda #$00
sta FD_ACPTR_LEN+1
lda #<FD_DIRENT_BUF
sta FD_ACPTR_PTR+0
lda #>FD_DIRENT_BUF
sta FD_ACPTR_PTR+1
; Set directory phase to 'file name'
lda #$01
sta FD_DIR_PHASE
; Copy 1st BAM sector to the cache
ldx #$00
@lp3:
lda SHARED_BUF_1+$100, x
sta FD_BAM_CACHE_0,x
inx
bne @lp3
; Load the next pair of sectors
lda #$02
sta PAR_SECTOR
jsr lowlevel_readsector ; XXX handle read errors
; Copy 2nd BAM sector to the cache
ldx #$00
@lp4:
lda SHARED_BUF_1, x
sta FD_BAM_CACHE_0+$100,x
inx
bne @lp4
; Set variables to point to the 1st directory entry in the 2nd sector of the buffer
lda #$08
sta FD_DIRENT
; Make sure the 1st sector in buffer points to 2nd one
lda #40
sta SHARED_BUF_1+0
lda #03
sta SHARED_BUF_1+1
; End
jmp dos_EXIT_CLC
fs_cbm_read_dir:
jsr fs_cbm_nextdirentry
bcs fs_cbm_read_dir_blocksfree ; XXX handle errors
jsr util_dir_filter ; XXX consider moving these calls to fs_*_nextdirentry
bne fs_cbm_read_dir ; if does not match, try the next entry
; Prepare output entry, starting from XX_DIRENT_BUF + initial offset
jsr util_dir_filesize_blocks
ldx #(FD_DIRENT_BUF - XX_DIRENT_BUF)
ldx #$30
jsr util_dir_basic
; Provide pointers and length
sta FD_ACPTR_LEN+1
txa
sec
sbc #$30
sta FD_ACPTR_LEN+0
lda #<(FD_DIRENT_BUF)
sta FD_ACPTR_PTR+0
lda #>(FD_DIRENT_BUF)
sta FD_ACPTR_PTR+1
clc
rts
fs_cbm_read_dir_blocksfree:
; Copy the 'BLOCKS FREE' line
ldx #$13
@lp1:
lda dir_end, x
sta FD_DIRENT_BUF, x
dex
bpl @lp1
; Calculate free blocks from the BAM
ldx #$10
@lp2:
lda FD_BAM_CACHE_0+$100,x
jsr @sub_free_add
cpx #$FA
beq @lp2_end
lda FD_BAM_CACHE_0+$000,x
jsr @sub_free_add
inx
inx
inx
inx
inx
inx
bra @lp2
@lp2_end:
; Set pointer and length
lda #$13
sta FD_ACPTR_LEN+0
lda #$00
sta FD_ACPTR_LEN+1
lda #<FD_DIRENT_BUF
sta FD_ACPTR_PTR+0
lda #>FD_DIRENT_BUF
sta FD_ACPTR_PTR+1
; Mark end of directory
lda #$00
sta FD_DIR_PHASE
clc
rts
@sub_free_add:
; Helper routine to calculate free blocks
clc
adc FD_DIRENT_BUF+2
sta FD_DIRENT_BUF+2
bcc @noinc
inc FD_DIRENT_BUF+3
@noinc:
rts
@@ -0,0 +1,64 @@
;
; CBM/CMD virtual filesystem - reading the file
;
fs_cbm_read_file_open:
; Get the first sector of the directory XXX deduplicate code, create a separate open directory routine
lda #40
sta PAR_TRACK
lda #$03
sta PAR_SECTOR
jsr lowlevel_readsector ; XXX handle read errors
; Set variables to point to the 1st directory entry in the 2nd sector of the buffer
lda #$08
sta FD_DIRENT
; Make sure the 1st sector in buffer points to 2nd one
lda #40
sta SHARED_BUF_1+0
lda #03
sta SHARED_BUF_1+1
; XXX deduplicate code above with fs_cbm_read_dir_open
; Try to find the file, has to be PRG
@lp_find:
jsr fs_cbm_nextdirentry
+bcs dos_EXIT
; Only accept files of type 'PRG', properly closed XXX deduplicate with fs_vfs
lda PAR_FTYPE
and #%10111111
cmp #$82
bne @lp_find
; Check if file name matches the filter XXX deduplicate with fs_vfs
jsr util_dir_filter
bne @lp_find ; if does not match, try the next entry
; Found the file, load it
lda #$03 ; mode: read file
sta FD_MODE
lda FD_LOADTRACK
sta PAR_TRACK
lda FD_LOADSECTOR
sta PAR_SECTOR
jmp fs_cbm_nextfileblock_got_ts
@@ -9,9 +9,7 @@
; NOTE: overrides page pointed by FS_HVSR_DIRENT!
; XXX work-in-progress, this should be used within directory reading code
fs_hvsr_util_nextdirentry:
fs_vfs_nextdirentry:
; Clear the page which will be used
@@ -47,26 +45,26 @@ fs_hvsr_util_nextdirentry:
;
ldx FS_HVSR_DIRENT+$40 ; file name length
beq fs_hvsr_util_nextdirentry ; do not even try for empty file name
beq fs_vfs_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
bcs fs_vfs_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
beq fs_vfs_nextdirentry ; quotation mark is illegal
cmp #$2A
beq fs_hvsr_util_nextdirentry ; asterisk is illegal, it is used for filtering
beq fs_vfs_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
beq fs_vfs_nextdirentry ; the question mark - in the MS-DOS world it is illegal
cmp #$20
bcc fs_hvsr_util_nextdirentry ; control characters are not allowed
bcc fs_vfs_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
bcc fs_vfs_nextdirentry ; some characters are not allowed
cmp #$7E
bne @lpname_1
lda #$A6 ; replace tilde / pi with something more sane
@@ -75,7 +73,7 @@ fs_hvsr_util_nextdirentry:
@lpname_1:
cmp #$7B
bcs fs_hvsr_util_nextdirentry ; PETSCII-art and control characters are illegal
bcs fs_vfs_nextdirentry ; PETSCII-art and control characters are illegal
clc
sbc #$20 ; make everything the same case
@@ -102,7 +100,7 @@ fs_hvsr_util_nextdirentry:
txa
and #$10
beq fs_hvsr_util_nextdirentry ; this type is unknown
beq fs_vfs_nextdirentry ; this type is unknown
@entity_dir:
@@ -110,11 +108,11 @@ fs_hvsr_util_nextdirentry:
lda FS_HVSR_DIRENT+$40
cmp #$11
bcs fs_hvsr_util_nextdirentry ; skip entry if file name longer than 16 characters
bcs fs_vfs_nextdirentry ; skip entry if file name longer than 16 characters
; Set the type to directory
lda #$05
lda #$06
bra @detect_attributes
@entity_file:
@@ -124,8 +122,8 @@ fs_hvsr_util_nextdirentry:
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
bmi fs_vfs_nextdirentry ; if name too short, try next entry
beq fs_vfs_nextdirentry ; if name too short, try next entry
sta FS_HVSR_DIRENT+$40 ; store corrected file name length
tax
@@ -133,7 +131,7 @@ fs_hvsr_util_nextdirentry:
lda FS_HVSR_DIRENT, x
cmp #$2E
+bne fs_hvsr_util_nextdirentry
+bne fs_vfs_nextdirentry
;
; Detect file type by extension
@@ -165,21 +163,20 @@ fs_hvsr_util_nextdirentry:
cpy #(dir_types__end - dir_types)
bcc @lpext
jmp fs_hvsr_util_nextdirentry ; file extension not detected
jmp fs_vfs_nextdirentry ; file extension not detected
@lpext_found:
cpy #$10
+beq fs_hvsr_util_nextdirentry ; file extension 'DIR' does not mean this is a directory
cpy #$18
+beq fs_vfs_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
cmp #$07 ; mark some file types (not SEQ/PRG/USR/REL/CBM/DIR) as read-only
bcc @detect_attributes
ora #$40
@@ -0,0 +1,80 @@
;
; Hypervisor virtual filesystem - helper routine to get the next file block
;
fs_vfs_nextfileblock:
; 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 #<SHARED_BUF_0
sta SD_ACPTR_PTR+0
lda #>SHARED_BUF_0
sta SD_ACPTR_PTR+1
; Copy data to SHARED_BUF_0
lda #%10000000 ; select SD card buffer
tsb SD_BUFCTL
; Copy data using DMA job
lda #$00
sta DMAJOB_DST_MB
lda #<(SHARED_BUF_0 - $8000)
sta DMAJOB_DST_ADDR+0
lda #>(SHARED_BUF_0 - $8000)
sta DMAJOB_DST_ADDR+1
lda #$01
sta DMAJOB_DST_ADDR+2
jsr util_dma_launch_from_hwbuf ; execute DMA job
clc
rts
fs_vfs_file_not_found:
jsr fs_vfs_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
@@ -0,0 +1,145 @@
;
; Hypervisor virtual filesystem - reading directory
;
fs_vfs_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+0
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_vfs_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_vfs_direntmem_prepare
jsr fs_vfs_nextdirentry
jsr fs_vfs_direntmem_restore ; processor status is preserved
; If nothing to read, output 'blocks free'
+bcs fs_vfs_read_dir_blocksfree
; Check if file name matches the filter
jsr util_dir_filter
bne fs_vfs_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_DIRENT_BUF + initial offset
ldx #(SD_DIRENT_BUF - XX_DIRENT_BUF)
jsr util_dir_basic
; Provide pointers and length
stx SD_ACPTR_LEN+0
sta SD_ACPTR_LEN+1
lda #<(SD_DIRENT_BUF)
sta SD_ACPTR_PTR+0
lda #>(SD_DIRENT_BUF)
sta SD_ACPTR_PTR+1
clc
rts
fs_vfs_read_dir_blocksfree:
; Set pointer to 'BLOCKS FREE.' line
lda #$13
sta SD_ACPTR_LEN+0
lda #$00
sta SD_ACPTR_LEN+1
lda #<dir_end
sta SD_ACPTR_PTR+0
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_vfs_direntmem_prepare:
ldx #$00
@1:
ldy $1000, x
sty SD_MEMSHADOW_BUF, x
inx
bne @1
rts
fs_vfs_direntmem_restore:
php
ldx #$00
@1:
ldy SD_MEMSHADOW_BUF, x
sty $1000, x
inx
bne @1
bne @1
plp
rts
@@ -0,0 +1,67 @@
;
; Hypervisor virtual filesystem - reading the file
;
fs_vfs_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_vfs_direntmem_prepare
@lp_find:
jsr fs_vfs_nextdirentry ; fetch the next file name
+bcs fs_vfs_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_vfs_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_vfs_nextfileblock
jmp dos_EXIT
+117
View File
@@ -0,0 +1,117 @@
; Read a sector pair from a block device
lowlevel_readsector:
; XXX compare device and unit too
; Check if buffer contains data from given track
lda PAR_TRACK
cmp BUFTAB_TRACK+1
bne lowlevel_readsector_force
; Check if sectors match
lda PAR_SECTOR
and #%11111110
cmp BUFTAB_SECTOR+1
bne lowlevel_readsector_force
; Data already loaded into buffer - do nothing
clc
rts
lowlevel_readsector_force:
; Select FDD sector as buffer
lda #%10000000 ; select floppy buffer
trb SD_BUFCTL ; $D689
lda #%00001111 ; set drive 0 (internal) and side 0
trb FDC_CONTROL ; $D080
; Select physical track and sector based on logical ones from PAR_TRACK and PAR_SECTOR
lda PAR_TRACK
dec
sta FDC_TRACK ; $D084
lda PAR_SECTOR
cmp #20
bcc @side0
@side1:
lda #%00001000 ; set side 1
tsb FDC_CONTROL ; $D080
lda PAR_SECTOR
sec
sbc #20
ldx #$01
+skip_2_bytes_trash_nvz
@side0:
ldx #$00
stx FDC_SIDE ; $D086
clc
ror
inc
sta FDC_SECTOR ; $D085
; Ask the controller to read the sector XXX how to detect errors, missing disk, etc.?
lda #$40
sta FDC_COMMAND ; $D081
; Wait for RDREQ (indicates sector found)
@lp1:
lda FDC_STATUS_B ; $D083
bpl @lp1
; Wait for BUSY flag to clear
@lp2:
lda FDC_STATUS_A ; $D082
bmi @lp2
; Wait for DRQ and EQ flags to go high
@lp3:
lda FDC_STATUS_A ; $D082
and #%01100000
cmp #%01000000 ; XXX is this correct? .A seems to stay at $40 at this point
bne @lp3
; Copy sector to buffer in RAM
lda #$00
sta DMAJOB_DST_MB
lda #<(SHARED_BUF_1 - $8000)
sta DMAJOB_DST_ADDR+0
lda #>(SHARED_BUF_1 - $8000)
sta DMAJOB_DST_ADDR+1
lda #$01
sta DMAJOB_DST_ADDR+2
jsr util_dma_launch_from_hwbuf ; execute DMA job
; Fill-in metadata for buffer #1
lda #$00
sta BUFTAB_DEV+1
lda PAR_TRACK
sta BUFTAB_TRACK+1
lda PAR_SECTOR
and #%11111110
sta BUFTAB_SECTOR+1
clc
rts
@@ -11,13 +11,13 @@ msg_ACPTR:
; Check if there is a talker active
ldx IDX1_TALKER
bmi msg_ACPTR_fail_no_talker
+bmi msg_ACPTR_fail_no_talker
; Check if active channel is status one
lda XX_CHANNEL, X
cmp #$0F
beq msg_ACPTR_status
+beq msg_ACPTR_status
; XXX add support for read contexts (multiple channels)
@@ -26,7 +26,7 @@ msg_ACPTR:
ldx IDX2_TALKER
lda XX_ACPTR_LEN+0,x
ora XX_ACPTR_LEN+1,x
beq msg_ACPTR_fail_no_data
+beq msg_ACPTR_fail_no_data
; Read a byte of data from the buffer
@@ -56,17 +56,41 @@ msg_ACPTR_read_SD:
ora SD_ACPTR_LEN+1
bne @3
jsr dev_sd_cmd_READ
jsr unit_sd_cmd_READ
bcc @3
jsr kernalstatus_EOI
@3:
jmp dos_EXIT_CLC
msg_ACPTR_read_FD:
; XXX provide implementation
; Read and return one byte
jsr FD_ACPTR_helper
sta TBTCNT
sta REG_A
; Increment pointer, decrement length
inc FD_ACPTR_PTR+0
bne @1
inc FD_ACPTR_PTR+1
@1:
dec FD_ACPTR_LEN+0
lda FD_ACPTR_LEN+0
cmp #$FF
bne @2
dec FD_ACPTR_LEN+1
@2:
; If new length is 0, try to read next block of data
ora FD_ACPTR_LEN+1
bne @3
jsr unit_fd_cmd_READ
bcc @3
jsr kernalstatus_EOI
@3:
jmp dos_EXIT_CLC
msg_ACPTR_read_RD:
@@ -90,21 +114,21 @@ msg_ACPTR_status_SD: ; get next byte of status - SD card
ldx SD_STATUS_IDX
inc SD_STATUS_IDX
lda SD_STATUS_STR,x
lda SD_STATUS_BUF,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
lda FD_STATUS_BUF,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
lda RD_STATUS_BUF,x
; FALLTROUGH
@@ -52,7 +52,7 @@ msg_CIOUT_cmdfn_SD: ; get next byte of status - SD card
lda #$A0
sta SD_CMDFN_BUF,x
plp
+bcs dev_sd_cmd_OPEN_EOI ; if EOI - execute command
+bcs unit_sd_cmd_OPEN_EOI ; if EOI - execute command
jmp dos_EXIT_CLC
msg_CIOUT_cmdfn_FD: ; get next byte of status - floppy
@@ -67,7 +67,7 @@ msg_CIOUT_cmdfn_FD: ; get next byte of status - floppy
lda #$A0
sta FD_CMDFN_BUF,x
plp
+bcs dev_fd_cmd_OPEN_EOI ; if EOI - execute command
+bcs unit_fd_cmd_OPEN_EOI ; if EOI - execute command
jmp dos_EXIT_CLC
msg_CIOUT_cmdfn_RD: ; get next byte of status - ram disk
@@ -82,7 +82,7 @@ msg_CIOUT_cmdfn_RD: ; get next byte of status - ram disk
lda #$A0
sta RD_CMDFN_BUF,x
plp
+bcs dev_rd_cmd_OPEN_EOI ; if EOI - execute command
+bcs unit_rd_cmd_OPEN_EOI ; if EOI - execute command
jmp dos_EXIT_CLC
msg_CIOUT_cmdfn_vectab:
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -4,7 +4,7 @@
;
dev_fd_cmd_CLOSE:
unit_fd_cmd_CLOSE:
; XXX provide implementation
@@ -0,0 +1,73 @@
;
; Open file for reading
;
unit_fd_cmd_OPEN:
lda #$01 ; mode: receive command or file name
sta FD_MODE
jmp dos_EXIT_CLC
unit_fd_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 floppy
lda FD_CMDFN_BUF
cmp #'$'
beq unit_fd_cmd_OPEN_dir
; FALLTROUGH
unit_fd_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 FD_CMDFN_BUF, y
cmp #$A0
beq @lp1_end
sta PAR_FPATTERN, y
iny
cpy #$10
bne @lp1
@lp1_end:
jmp fs_cbm_read_file_open
unit_fd_cmd_OPEN_dir:
lda #$02 ; mode: read directory
sta FD_MODE
; Copy the filter from command XXX this should be moved to common part and deduplicated with file opening
ldy #$00
@lp1:
lda FD_CMDFN_BUF+1, y
cmp #$A0
beq @lp1_end
sta PAR_FPATTERN, y
iny
cpy #$10
bne @lp1
@lp1_end:
jmp fs_cbm_read_dir_open
@@ -0,0 +1,20 @@
;
; Read more data into the buffer
;
unit_fd_cmd_READ:
lda FD_MODE
cmp #$03
+beq fs_cbm_nextfileblock
lda FD_DIR_PHASE
cmp #$01
+beq fs_cbm_read_dir
cmp #$02
+beq fs_cbm_read_dir_blocksfree
sec ; mark EOI
rts
@@ -4,7 +4,7 @@
;
dev_fd_init:
unit_fd_init:
; Copy status string
@@ -20,7 +20,7 @@ dev_fd_init:
@1:
inx
lda dos_sts_init_floppy,x
sta FD_STATUS_STR,x
sta FD_STATUS_BUF,x
bne @1
; End of initialization
@@ -4,7 +4,7 @@
;
dev_rd_cmd_CLOSE:
unit_rd_cmd_CLOSE:
; XXX provide implementation
@@ -4,13 +4,13 @@
;
dev_fd_cmd_OPEN:
unit_rd_cmd_OPEN:
; XXX provide implementation
jmp dos_EXIT_SEC
dev_fd_cmd_OPEN_EOI:
unit_rd_cmd_OPEN_EOI:
; XXX provide implementation
@@ -4,7 +4,7 @@
;
dev_rd_cmd_READ:
unit_rd_cmd_READ:
; XXX provide implementation
@@ -4,7 +4,7 @@
;
dev_rd_init:
unit_rd_init:
; Copy status string
@@ -20,7 +20,7 @@ dev_rd_init:
@1:
inx
lda dos_sts_init_ramdisk,x
sta RD_STATUS_STR,x
sta RD_STATUS_BUF,x
bne @1
; End of initialization
@@ -4,7 +4,7 @@
;
dev_sd_cmd_CLOSE:
unit_sd_cmd_CLOSE:
; XXX provide implementation
@@ -4,14 +4,14 @@
;
dev_sd_cmd_OPEN:
unit_sd_cmd_OPEN:
lda #$01 ; mode: receive command or file name
sta SD_MODE
jmp dos_EXIT_CLC
dev_sd_cmd_OPEN_EOI:
unit_sd_cmd_OPEN_EOI:
; XXX this dispatcher is temporary
@@ -28,11 +28,11 @@ dev_sd_cmd_OPEN_EOI:
lda SD_CMDFN_BUF
cmp #'$'
beq dev_sd_cmd_OPEN_dir
beq unit_sd_cmd_OPEN_dir
; FALLTROUGH
dev_sd_cmd_OPEN_file:
unit_sd_cmd_OPEN_file:
; Copy the filter from command XXX this should be moved to common part and deduplicated with directory opening
@@ -48,10 +48,10 @@ dev_sd_cmd_OPEN_file:
@lp1_end:
jmp fs_hvsr_read_file_open
jmp fs_vfs_read_file_open
dev_sd_cmd_OPEN_dir:
unit_sd_cmd_OPEN_dir:
lda #$02 ; mode: read directory
sta SD_MODE
@@ -70,4 +70,4 @@ dev_sd_cmd_OPEN_dir:
@lp1_end:
jmp fs_hvsr_read_dir_open
jmp fs_vfs_read_dir_open
@@ -4,17 +4,17 @@
;
dev_sd_cmd_READ:
unit_sd_cmd_READ:
lda SD_MODE
cmp #$03
+beq fs_hvsr_read_file
+beq fs_vfs_nextfileblock
lda SD_DIR_PHASE
cmp #$01
+beq fs_hvsr_read_dir
+beq fs_vfs_read_dir
cmp #$02
+beq fs_hvsr_read_dir_blocksfree
+beq fs_vfs_read_dir_blocksfree
sec ; mark EOI
rts
@@ -4,7 +4,7 @@
;
dev_sd_init:
unit_sd_init:
; Copy initial status string
@@ -21,7 +21,7 @@ dev_sd_init:
@1:
inx
lda dos_sts_init_sdcard,x
sta SD_STATUS_STR,x
sta SD_STATUS_BUF,x
bne @1
; Close all the files in the hypervisor, go to root directory
+116
View File
@@ -0,0 +1,116 @@
; Create BASIC line from directory entry
; in: .X = offset from XX_DIRENT_BUF, .Y = characters to indent after line number
; out: .X (low byte) = current position, .A = 0
util_dir_basic:
lda #$01 ; link to the next line - dummy, will be regenerated by BASIC
sta XX_DIRENT_BUF, x
inx
sta XX_DIRENT_BUF, x
inx
lda PAR_FSIZE_BLOCKS+0 ; store number of blocks
sta XX_DIRENT_BUF, x
inx
lda PAR_FSIZE_BLOCKS+1
sta XX_DIRENT_BUF, x
inx
lda #' ' ; indent file name
@lp1:
dey
bmi @lp1_done
sta XX_DIRENT_BUF, x
inx
bra @lp1
@lp1_done:
lda #$22 ; opening quote
sta XX_DIRENT_BUF, 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_DIRENT_BUF, x
inx
bra @lp2
@lp2_done:
lda #$22 ; closing quote
sta XX_DIRENT_BUF, x
inx
ldy #$10 ; put spaces for indentation
@lp3:
dey
lda PAR_FNAME, y
cmp #$A0
bne @lp3_done
lda #' '
sta XX_DIRENT_BUF, 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_DIRENT_BUF, x
inx
lda PAR_FTYPE ; put file type
and #$3F
asl
asl
tay
@lp4:
lda dir_types, y
beq @lp4_done
sta XX_DIRENT_BUF, x
inx
iny
bra @lp4
@lp4_done:
lda PAR_FTYPE ; read-only mark (if needed)
and #$40
beq @skipro
lda #'<'
sta XX_DIRENT_BUF, x
inx
@skipro:
lda #$00 ; put end of the line
sta XX_DIRENT_BUF, x
inx
rts
+67 -2
View File
@@ -1,5 +1,5 @@
; Check if file name matches the filter (if so - Zero flag set)
; Check if file name/type matches the filter (if so - Zero flag set)
util_dir_filter:
@@ -14,15 +14,80 @@ util_dir_filter:
lda PAR_FPATTERN, y
cmp #'*'
beq @done ; branch on wildcard
beq @asterisk ; branch on wildcard
cmp #'?'
beq @lp1_next ; question mark substitutes any character
cmp PAR_FNAME, y
bne @done ; branch if does not match
@lp1_next:
iny
cpy #$10
bne @lp1 ; next iteration if maximum length not reached
@done_match:
lda #$00
@done:
rts
@asterisk:
iny ; check if the next character after asterisk is '='
cpy #$10
beq @done
lda PAR_FPATTERN, y
cmp #'='
bne @done_match
iny
cpy #$10
beq @done
lda PAR_FPATTERN, y
sta $1000
cmp #$44 ; if 'D' - require a directory XXX documment this extension
beq @require_dir
cmp #$50 ; if 'P' - require PRG file
beq @require_prg
cmp #$52 ; if 'R' - require REL file
beq @require_rel
cmp #$53 ; if 'S' - require SEQ file
beq @require_seq
cmp #$55 ; if 'U' - require USR file
bne @done
@require_usr:
lda #$03
+skip_2_bytes_trash_nvz
@require_seq:
lda #$01
+skip_2_bytes_trash_nvz
@require_rel:
lda #$04
+skip_2_bytes_trash_nvz
@require_prg:
lda #$02
+skip_2_bytes_trash_nvz
@require_dir:
lda #$06
eor PAR_FTYPE
and #%00111111
rts
+33
View File
@@ -0,0 +1,33 @@
; Launch the DMA list
util_dma_launch_from_hwbuf:
; Operation from source $FFD6E00 (hardware SD card / floppy buffer)
; Destination has to be set by the caller
lda #$FF
sta DMAJOB_SRC_MB
lda #$00
sta DMAJOB_SRC_ADDR+0
lda #$6E
sta DMAJOB_SRC_ADDR+1
lda #$0D
sta DMAJOB_SRC_ADDR+2
; FALLTROUGH
util_dma_launch:
lda #$01
sta DMA_ADDRBANK ; $D702
dec
sta DMA_ADDRMB ; $D704
lda #>(DMAJOB_LIST-$8000)
sta DMA_ADDRMSB ; $D701
lda #<(DMAJOB_LIST-$8000)
sta DMA_ETRIG ; $D705
rts
+7 -7
View File
@@ -50,7 +50,7 @@ util_status_common:
@lp:
jsr code_LDA_nnnn_Y
beq @lp_end
sta XX_STATUS_STR, x
sta XX_STATUS_BUF, x
iny
inx
bra @lp
@@ -69,13 +69,13 @@ util_status_common:
; Mark end of status and quit
lda #$00
sta XX_STATUS_STR, x
sta XX_STATUS_BUF, x
rts
util_status_store_comma:
ldy #','
sty XX_STATUS_STR, x
sty XX_STATUS_BUF, x
inx
rts
@@ -86,7 +86,7 @@ util_status_store_number:
cmp #200
bcc @store_00_199
ldy #'2'
sty XX_STATUS_STR, x
sty XX_STATUS_BUF, x
inx
sec
sbc #200
@@ -97,7 +97,7 @@ util_status_store_number:
cmp #100
bcc @store_00_99
ldy #'1'
sty XX_STATUS_STR, x
sty XX_STATUS_BUF, x
inx
sec
sbc #100
@@ -115,11 +115,11 @@ util_status_store_number:
@store_finalize: ; first digit to store in .Y, second in .A (need no add '0')
sty XX_STATUS_STR, x
sty XX_STATUS_BUF, x
inx
clc
adc #'0'
sta XX_STATUS_STR, x
sta XX_STATUS_BUF, x
inx
rts
+1 -1
View File
@@ -52,7 +52,7 @@ ZVM: ; entry point
; Check if extended memory is present
; XXX enable test jsr ZVM_memtest
jsr ZVM_memtest
; Generate CPU tables, reset the CPU
+3 -3
View File
@@ -306,8 +306,8 @@ const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc",
{ false, true, true, false, false, "STR_MEM_STRS", "\r STRS" },
{ false, true, true, false, false, "STR_MEM_FREE", "\r\r FREE" },
{ false, false, true, false, false, "STR_DOS_FD", ", FDD " },
{ false, false, true, false, false, "STR_DOS_RD", ", RAM " },
{ false, false, true, false, false, "STR_DOS_FD", ", FLOPPY " },
{ false, false, true, false, false, "STR_DOS_RD", ", RAM DISK " },
{ false, false, true, false, false, "STR_SI_HEADER", "OPEN ROMS, " },
{ false, false, true, false, false, "STR_SI_MODE64", "LEGACY MODE" },
@@ -1224,7 +1224,7 @@ void DataSet::generateConfigDepStrings()
// CBDOS features
featureStrM65 += "CBDOS : SD CARD ";
featureStrM65 += "\rSD CARD ";
// Keyboard support features