diff --git a/Makefile b/Makefile index 1f57c808..6cd4d894 100644 --- a/Makefile +++ b/Makefile @@ -35,6 +35,8 @@ SRCDIR_BASIC = $(SRCDIR_COMMON) \ SRCDIR_DOS_M65 = $(SRCDIR_COMMON) \ src/dos_m65 \ + # src/dos_m65/cmdrdos \ + src/dos_m65/sdcard SRCDIR_KERNAL = $(SRCDIR_COMMON) \ src/kernal \ diff --git a/src/,,config_mega65.s b/src/,,config_mega65.s index 95856675..823fb077 100644 --- a/src/,,config_mega65.s +++ b/src/,,config_mega65.s @@ -94,6 +94,8 @@ ; --- 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_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 f6cd8a46..db5b2380 100644 --- a/src/aliases/,aliases_config.s +++ b/src/aliases/,aliases_config.s @@ -241,6 +241,13 @@ +; 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 !set counter = 0 @@ -415,6 +422,12 @@ +; 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 { diff --git a/src/basic/init/initmsg_m65.s b/src/basic/init/initmsg_m65.s index baedbe52..40d9a782 100644 --- a/src/basic/init/initmsg_m65.s +++ b/src/basic/init/initmsg_m65.s @@ -59,9 +59,18 @@ INITMSG_end: 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: @@ -99,3 +108,16 @@ INITMSG_revision: lda #rom_revision_basic_string jmp STROUT + + + +!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/init/initmsg_real.s b/src/basic/init/initmsg_real.s index b470d316..2fea1804 100644 --- a/src/basic/init/initmsg_real.s +++ b/src/basic/init/initmsg_real.s @@ -106,3 +106,5 @@ 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 93cad552..954435dd 100644 --- a/src/dos_m65/,aliases_dos.s +++ b/src/dos_m65/,aliases_dos.s @@ -2,17 +2,41 @@ ; Memory locations for the DOS ; +; 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 ; - !addr MAGICSTR = $00 ; magic string; if not matching, DOS considered non-functional + !addr MAGICSTR = $00 ; magic string; if not matching, DOS considered non-functional - !addr UNIT_SDCARD = $05 - !addr UNIT_FLOPPY = $06 - !addr UNIT_RAMDISK = $07 + ; General DOS configuration - ; 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 + !addr UNIT_SDCARD = $05 + !addr UNIT_FLOPPY = $06 + !addr UNIT_RAMDISK = $07 + + ; SD/SDHC card variables + + !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 CARD_TMP_STEP = $12 ; 4 bytes + !addr CARD_TMP_RETRIES = $16 ; 1 byte + + !addr CARD_BUFPNT = $FC ; 4 bytes - pointer to hardware sector buffer XXX replace copy routines with DMAgic + + + + ; + ; High memory + ; + + !addr CARD_BUF = $8100 ; 512 bytes, up to $82FF - buffer for reading/writing data diff --git a/src/dos_m65/cmdrdos/,check_nonlgpl3.s b/src/dos_m65/cmdrdos/,check_nonlgpl3.s new file mode 100644 index 00000000..a5e16f82 --- /dev/null +++ b/src/dos_m65/cmdrdos/,check_nonlgpl3.s @@ -0,0 +1,4 @@ + +!ifndef HAS_NOLGPL3_WARN { + !error "No LGPL3 incompatible warning issued" +} diff --git a/src/dos_m65/dos_init.s b/src/dos_m65/dos_init.s index 8cc6e213..5654e923 100644 --- a/src/dos_m65/dos_init.s +++ b/src/dos_m65/dos_init.s @@ -26,6 +26,9 @@ dos_INIT: lda #CONFIG_UNIT_RAMDISK sta UNIT_RAMDISK - ; XXX initialize drivers, etc. + ; Mark SD card as not initialized + + lda #$00 + sta CARD_INIT_DONE rts diff --git a/src/dos_m65/m65_sdcard.s b/src/dos_m65/m65_sdcard.s deleted file mode 100644 index 9ca80a71..00000000 --- a/src/dos_m65/m65_sdcard.s +++ /dev/null @@ -1,380 +0,0 @@ - -; -; MEGA65 SD/SDHC card support -; - -; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c - - - -; Permanent values XXX addresses are temporary - -!addr CARD_IS_SDHC = $80 ; $00 = SD, $80 = SDHC -!addr CARD_SIZE = $81 ; 4 bytes -!addr CARD_SECNUM = $85 ; 4 bytes - sector number -!addr CARD_BUFPNT = $89 ; 4 bytes - pointer to hardware sector buffer - - -; Temporary data XXX addresses are temporary - -!addr TMP_STEP = $8D ; 4 bytes -!addr TMP_RETRIES = $8E ; 1 byte - -!addr CARD_BUF = $8100 ; 512 bytes, up to $82FF - - -; External entry points: -; - m65_sdcard_init -; - m65_sdcard_readsector - - - -m65_sdcard_init: - - ; Initialize most important variables - - lda #$00 - sta CARD_IS_SDHC - - lda #SD_SECBUF_0 - sta CARD_BUFPNT+0 - lda #SD_SECBUF_1 - sta CARD_BUFPNT+1 - lda #SD_SECBUF_2 - sta CARD_BUFPNT+2 - lda #SD_SECBUF_3 - sta CARD_BUFPNT+3 - - ; Reset the card - - jsr m65_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 m65_sdcard_read - bcc m65_sdcard_init_operable - - ; XXX if we are here, mark card as not operable and quit - -m65_sdcard_init_operable: - - ; 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 m65_sdcard_read - - lda SD_CTL - beq m65_sdcard_init_sdsc - - ; FALLTROUGH - -m65_sdcard_init_sdhc: - - lda #$80 - sta CARD_IS_SDHC - - bra m65_sdcard_init_getsize - -m65_sdcard_init_sdsc: - - lda #$00 - sta CARD_IS_SDHC - lda #$40 ; use byte addressing - sta SD_CTL - - ; FALLTROUGH - -m65_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) - - lda #$00 - sta CARD_SECNUM+0 - sta CARD_SECNUM+1 - sta CARD_SECNUM+2 - sta CARD_SECNUM+3 - - ; step = 16*2048 - - sta TMP_STEP+0 - sta TMP_STEP+2 - sta TMP_STEP+3 - lda #$08 - sta TMP_STEP+1 - - ; XXX finish the implementation - - - - - - - - - -; ------------------------------------- - - - - - - - -m65_sdcard_readsector: ; XXX reads sector CARD_SECNUM - - ; Set read address, depending on card type - - bit CARD_IS_SDHC - bpl m65_sdcard_readsector_sdsc - -m65_sdcard_readsector_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 - - bra m65_sdcard_readsector_read - -m65_sdcard_readsector_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 m65_sdcard_readsector_fail ; branch if sector number too large for SD card - lda CARD_SECNUM+3 - bne m65_sdcard_readsector_fail ; branch if sector number too large for SD card - - ; FALLTROUGH - -m65_sdcard_readsector_read: - - ; Set number of retries - - lda #$0A - sta TMP_RETRIES - - ; FALLTROUGH - -m65_sdcard_readsector_try_loop: - - ; Wait till card is ready - - jsr m65_sdcard_readsector_wait - bcs m65_sdcard_readsector_fail - - ; Read command - - lda #$02 - sta SD_CTL - - ; Wait for command completion - - jsr m65_sdcard_readsector_wait - bcs m65_sdcard_readsector_fail - - - lda SD_CTL - and #$67 - bne m65_sdcard_readsector_copy_data - - jsr m65_sdcard_reset - dec TMP_RETRIES - bne m65_sdcard_readsector_try_loop - - ; FALLTROUGH - -m65_sdcard_readsector_fail: - - sec - rts - -m65_sdcard_readsector_copy_data: - - ; XXX this should be a separate routine - ; XXX use DMAgic for this - - phz - phx - - ldx #$00 - ldz #$00 - -@RL1: - 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 @RL1 - - ; Restore registers and quit - - plx - plz - - clc - rts - - - - - - - - - -; ------------------------------------- - - -m65_sdcard_readsector_wait: - - ; Wait till card is ready - - 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 m65_sdcard_readsector_wait_fail - tax - and #$40 - bne m65_sdcard_readsector_wait_fail - txa - and #$03 - bne m65_sdcard_readsector_wait - - clc - rts - -m65_sdcard_readsector_wait_fail: - - sec - rts - - - - - -; ------------------------------------- - - - - - -m65_sdcard_read: - - ; Trigger read - - lda #$02 - sta SD_CTL - - ; Wait for result - - ldx #90 -@1: - jsr m65_sdcard_wait_16000_usec - lda SD_CTL - and #$03 - beq @2 - dex - bne @1 - - ; Read failed - - sec - rts -@2: - ;; Success - - clc - rts - - - -; ------------------------------------- - - - -m65_sdcard_reset: - - ldx #$40 - stx SD_CTL - ldy #$00 - sty SD_CTL - iny ; $01 - sty SD_CTL - - ; Wait till SD card resets -@3: - lda SD_CTL - and #$03 - bne @3 - - ; For SDHC card set appropriate mode - - bit CARD_IS_SDHC - bpl @4 - inx ; $41 - stx SD_CTL -@4: - rts - - - -; ------------------------------------- - - -m65_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 -@w1: - cmp VIC_RASTER - beq @w1 - lda VIC_RASTER - dex - bne @w1 - - pla - plx - - rts diff --git a/src/dos_m65/sdcard/sdcard_init.s b/src/dos_m65/sdcard/sdcard_init.s new file mode 100644 index 00000000..c67fdc08 --- /dev/null +++ b/src/dos_m65/sdcard/sdcard_init.s @@ -0,0 +1,136 @@ + +; +; 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_BUFPNT+0 + lda #SD_SECBUF_1 + sta CARD_BUFPNT+1 + lda #SD_SECBUF_2 + sta CARD_BUFPNT+2 + lda #SD_SECBUF_3 + sta CARD_BUFPNT+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 + bcc sdcard_init_operable + + ; XXX if we are here, mark card as not operable and quit + +sdcard_init_operable: + + ; 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 #$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) + + lda #$00 + sta CARD_SECNUM+0 + sta CARD_SECNUM+1 + sta CARD_SECNUM+2 + sta CARD_SECNUM+3 + + ; step = 16*2048 + + sta CARD_TMP_STEP+0 + sta CARD_TMP_STEP+2 + sta CARD_TMP_STEP+3 + lda #$08 + sta CARD_TMP_STEP+1 + + ; XXX finish the implementation + + + + +; +; Helper routines +; + + +sdcard_init_read: + + ; Trigger read + + lda #$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 new file mode 100644 index 00000000..1f20ae9b --- /dev/null +++ b/src/dos_m65/sdcard/sdcard_readsector.s @@ -0,0 +1,154 @@ + +; +; 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, depending on card type + + bit CARD_IS_SDHC + bpl sdcard_readsector_sdsc + +sdcard_readsector_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 + + bra sdcard_readsector_read + +sdcard_readsector_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_readsector_fail ; branch if sector number too large for SD card + lda CARD_SECNUM+3 + bne sdcard_readsector_fail ; branch if sector number too large for SD card + + ; 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_readsector_wait + bcs sdcard_readsector_fail + + ; Read command + + lda #$02 + sta SD_CTL + + ; Wait for command completion + + jsr sdcard_readsector_wait + 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 this should be a separate routine + ; 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 + +sdcard_readsector_wait: + + ; Wait till card is ready + + 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_readsector_wait_fail + tax + and #$40 + bne sdcard_readsector_wait_fail + txa + and #$03 + bne sdcard_readsector_wait + + clc + rts + +sdcard_readsector_wait_fail: + + sec + rts diff --git a/src/dos_m65/sdcard/sdcard_reset.s b/src/dos_m65/sdcard/sdcard_reset.s new file mode 100644 index 00000000..29b22610 --- /dev/null +++ b/src/dos_m65/sdcard/sdcard_reset.s @@ -0,0 +1,32 @@ + +; +; Resets the SD card +; + +; Based on https://github.com/MEGA65/mega65-libc/blob/master/cc65/src/sdcard.c + + + +sdcard_reset: + + ldx #$40 + stx SD_CTL + ldy #$00 + sty SD_CTL + iny ; $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 + inx ; $41 + stx SD_CTL +@2: + rts diff --git a/src/dos_m65/sdcard/sdcard_wait.s b/src/dos_m65/sdcard/sdcard_wait.s new file mode 100644 index 00000000..59f89cb7 --- /dev/null +++ b/src/dos_m65/sdcard/sdcard_wait.s @@ -0,0 +1,26 @@ + + + +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