diff --git a/AppleIISd.vcxproj b/AppleIISd.vcxproj
index 27e226a..a15ae28 100644
--- a/AppleIISd.vcxproj
+++ b/AppleIISd.vcxproj
@@ -11,9 +11,9 @@
-
-
+
+
{9EA7EC3D-1771-420F-932F-231A35ED1200}
@@ -50,14 +50,12 @@
C:\cc65\lib
- $(MAKE_HOME)\make -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)" OPTIONS=mapfile,listing
+ $(MAKE_HOME)\make OPTIONS=mapfile,listing
$(ProjectDir)\src
- $(MAKE_HOME)\make clean -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)"
-$(MAKE_HOME)\make -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)/$(ProjectName)" OPTIONS=mapfile,listing
-rmdir /S /Q "$(ProjectDir)obj"
-rmdir /S /Q "$(SolutionDir)Debug"
- $(SolutionDir)$(Configuration)\
- $(MAKE_HOME)\make clean -C "$(ProjectDir)\" PROGRAM="$(ProjectDir)$(Configuration)\$(ProjectName)"
+ $(MAKE_HOME)\make clean
+$(MAKE_HOME)\make OPTIONS=mapfile,listing
+ $(SolutionDir)\
+ $(MAKE_HOME)\make clean
@@ -85,6 +83,7 @@ rmdir /S /Q "$(SolutionDir)Release"
C:\cc65\lib
+ $(SolutionDir)$\
diff --git a/AppleIISd.vcxproj.filters b/AppleIISd.vcxproj.filters
new file mode 100644
index 0000000..bbd9f28
--- /dev/null
+++ b/AppleIISd.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+
+ src
+
+
+ src
+
+
+
+
+ {d301b76d-0aac-4430-a25a-193e6e572e60}
+
+
+
\ No newline at end of file
diff --git a/makefile b/makefile
index f86a993..f4298fe 100644
--- a/makefile
+++ b/makefile
@@ -13,7 +13,7 @@ TARGETS := apple2enh
# Name of the final, single-file executable.
# Default: name of the current dir with target name appended
-PROGRAM := appleiisd
+PROGRAM := AppleIISd
# Path(s) to additional libraries required for linking the program
# Use only if you don't want to place copies of the libraries in SRCDIR
@@ -23,7 +23,7 @@ LIBS :=
# Custom linker configuration file
# Use only if you don't want to place it in SRCDIR
# Default: none
-CONFIG := appleiisd.cfg
+CONFIG :=
# Additional C compiler flags and options.
# Default: none
@@ -39,7 +39,7 @@ LDFLAGS =
# Path to the directory containing C and ASM sources.
# Default: src
-SRCDIR := .
+SRCDIR :=
# Path to the directory where object files are to be stored (inside respective target subdirectories).
# Default: obj
diff --git a/appleiisd.cfg b/src/AppleIISd.cfg
similarity index 100%
rename from appleiisd.cfg
rename to src/AppleIISd.cfg
diff --git a/AppleIISd.s b/src/AppleIISd.s
similarity index 95%
rename from AppleIISd.s
rename to src/AppleIISd.s
index bff9ee1..5b659b5 100644
--- a/AppleIISd.s
+++ b/src/AppleIISd.s
@@ -1,887 +1,887 @@
-;*******************************
-;
-; Apple][Sd Firmware
-; Version 0.8
-;
-; (c) Florian Reitz, 2017
-;
-; X register usually contains SLOT16
-; Y register is used for counting or SLOT
-;
-;*******************************
-
-;DEBUG := 0
-
-; Memory defines
-
-SLOT16 := $2B ; $s0 -> slot * 16
-SLOT := $3D ; $0s
-CMDLO := $40
-CMDHI := $41
-
-DCMD := $42 ; Command code
-BUFFER := $44 ; Buffer address
-BLOCK := $46 ; Block number
-
-CURSLOT := $07F8 ; $Cs
-DATA := $C080
-CTRL := DATA+1
-DIV := DATA+2
-SS := DATA+3
-R30 := $0478
-R31 := $04F8
-R32 := $0578
-R33 := $05F8
-
-; Constants
-
-DUMMY = $FF
-FRX = $10 ; CTRL register
-ECE = $04
-SS0 = $01 ; SS register
-SDHC = $10
-WP = $20
-CD = $40
-INITED = $80
-
-
-; signature bytes
-
- .segment "SLOTROM"
- LDX #$20
- LDX #$00
- LDX #$03
- LDX #$01 ; neither Smartport nor 5.25
-
-; find slot nr
-
- .ifdef DEBUG
- LDA #$04
- STA SLOT
- LDA #$C4
- STA CURSLOT
- LDA #$40
-
- .else
- PHP
- SEI
- LDA #$60 ; opcode for RTS
- STA SLOT
- JSR SLOT
- TSX
- LDA $0100,X
- STA CURSLOT ; $Cs
- AND #$0F
- PLP
- STA SLOT ; $0s
- ASL A
- ASL A
- ASL A
- ASL A
- .endif
-
- STA SLOT16 ; $s0
- TAX ; X holds now SLOT16
- BIT $CFFF
- JSR CARDDET
- BCC @INIT
- LDA #$2F ; no card inserted
- RTS
-
-@INIT: JSR INIT
-
-
-;*******************************
-;
-; Install SD card driver
-;
-;*******************************
-
- .ifdef DEBUG
-
-; see if slot has a driver already
-
- LDX $BF31 ; get devcnt
-INSTALL: LDA $BF32,X ; get a devnum
- AND #$70 ; isolate slot
- CMP SLOT16 ; slot?
- BEQ @INSOUT ; yes, skip it
- DEX
- BPL INSTALL ; keep up the search
-
-; restore the devnum to the list
-
- LDX $BF31 ; get devcnt again
- CPX #$0D ; device table full?
- BNE @INST2
-
- JSR $FF3A ; bell
- JMP @INSOUT ; do something!
-
-@INST2: LDA $BF32-1,X ; move all entries down
- STA $BF32,X ; to make room at front
- DEX ; for a new entry
- BNE @INST2
- LDA #$04 ; ProFile type device
- ORA SLOT16
- STA $BF32 ; slot, drive 1 at top of list
- INC $BF31 ; update devcnt
-
-; now insert the device driver vector
-
- LDA SLOT
- ASL
- TAX
- LDA #DRIVER
- STA $BF11,X
-@INSOUT: RTS
-
-
-;*******************************
-;
-; Boot from SD card
-;
-;*******************************
-
- .else
-
- .if 0
-BOOT: BEQ @DRAW ; check for error
- RTS
-
-@DRAW: LDY #0 ; display copyright message
-@DRAW1: LDA TEXT,Y
- BEQ @BOOT1 ; check for NULL
- ORA #$80
- STA $07D0,Y ; put on last line
- INY
- BPL @DRAW1
- .endif
-
-@BOOT1: LDA #$01
- STA DCMD ; load command
- LDX SLOT16
- STX $43 ; slot number
- LDA #$08
- STA BUFFER+1 ; buffer hi
- STZ BUFFER ; buffer lo
- STZ BLOCK+1 ; block hi
- STZ BLOCK ; block lo
- BIT $CFFF
- JSR READ ; call driver
-
- LDA #$01
- STA DCMD ; load command
- LDX SLOT16
- STX $43 ; slot number
- LDA #$0A
- STA BUFFER+1 ; buffer hi
- STZ BUFFER ; buffer lo
- STZ BLOCK+1 ; block hi
- LDA #$01
- STA BLOCK ; block lo
- BIT $CFFF
- JSR READ ; call driver
- LDX SLOT16
- JMP $801 ; goto bootloader
-
- .endif
-
-
-;*******************************
-;
-; Jump table
-;
-;*******************************
-
-DRIVER: CLD
-
-@SAVEZP: PHA ; make room for retval
- LDA SLOT16 ; save all ZP locations
- PHA
- LDA SLOT
- PHA
- LDA CMDLO
- PHA
- LDA CMDHI
- PHA
-
- .ifdef DEBUG
- LDA #$04
- STA SLOT
- LDA #$C4
- STA CURSLOT
- LDA #$40
-
- .else
- PHP
- SEI
- LDA #$60 ; opcode for RTS
- STA SLOT
- JSR SLOT
- TSX
- LDA $0100,X
- STA CURSLOT ; $Cs
- AND #$0F
- PLP
- STA SLOT ; $0s
- ASL A
- ASL A
- ASL A
- ASL A
- .endif
-
- STA SLOT16 ; $s0
- TAX ; X holds now SLOT16
- BIT $CFFF
- JSR CARDDET
- BCC @INITED
- LDA #$2F ; no card inserted
- BRA @RESTZP
-
-@INITED: LDA #INITED ; check for init
- BIT SS,X
- BEQ @INIT
-
-@CMD: LDA DCMD ; get command
- BEQ @STATUS ; branch if cmd is 0
- CMP #1
- BEQ @READ
- CMP #2
- BEQ @WRITE
- .ifdef DEBUG
- CMP #$FF
- BEQ @TEST
- .endif
- LDA #1 ; unknown command
- SEC
- BRA @RESTZP
-
-@STATUS: JSR STATUS
- BRA @RESTZP
-@READ: JSR READ
- BRA @RESTZP
-@WRITE: JSR WRITE
- BRA @RESTZP
- .ifdef DEBUG
-@TEST: JSR TEST ; do device test
- BRA @RESTZP
- .endif
-
-@INIT: JSR INIT
- BCC @CMD ; init ok
-
-@RESTZP: TSX
- STA $105,X ; save retval on stack
- PLA ; restore all ZP locations
- STA CMDHI
- PLA
- STA CMDLO
- PLA
- STA SLOT
- PLA
- STA SLOT16
- PLA ; get retval
- RTS
-
-
-; Signature bytes
-
- .segment "SLOTID"
- .dbyt $FFFF ; 65535 blocks
- .byt $97 ; Status bits
- .byt CMD0
- STA CMDHI
- JSR SDCMD
- JSR GETR1 ; get response
- CMP #$01
- BNE @ERROR1 ; error!
-
- LDA #CMD8
- STA CMDHI
- JSR SDCMD
- JSR GETR3
- CMP #$01
- BNE @SDV1 ; may be SD Ver. 1
-
-; check for $01aa match!
-@SDV2: LDA #CMD55
- STA CMDHI
- JSR SDCMD
- JSR GETR1
- LDA #ACMD4140
- STA CMDHI
- JSR SDCMD
- JSR GETR1
- CMP #$01
- BEQ @SDV2 ; wait for ready
- CMP #0
- BNE @ERROR1 ; error!
-; send CMD58
-; SD Ver. 2 initialized!
- LDA SS,X
- ORA #SDHC
- STA SS,X
- JMP @BLOCKSZ
-
-@ERROR1: JMP @IOERROR ; needed for far jump
-
-@SDV1: LDA #CMD55
- STA CMDHI
- JSR SDCMD ; ignore response
- LDA #ACMD410
- STA CMDHI
- JSR SDCMD
- JSR GETR1
- CMP #$01
- BEQ @SDV1 ; wait for ready
- CMP #0
- BNE @MMC ; may be MMC card
-; SD Ver. 1 initialized!
- JMP @BLOCKSZ
-
-@MMC: LDA #CMD1
- STA CMDHI
-@LOOP1: JSR SDCMD
- JSR GETR1
- CMP #$01
- BEQ @LOOP1 ; wait for ready
- CMP #0
- BNE @IOERROR ; error!
-; MMC Ver. 3 initialized!
-
-@BLOCKSZ: LDA #CMD16
- STA CMDHI
- JSR SDCMD
- JSR GETR1
- CMP #0
- BNE @IOERROR ; error!
-
-@END: LDA SS,X
- ORA #INITED ; initialized
- STA SS,X
- LDA CTRL,X
- ORA #ECE ; enable 7MHz
- STA CTRL,X
- CLC ; all ok
- LDY #0
- BCC @END1
-
-@IOERROR: SEC
- LDY #$27 ; init error
-@END1: LDA SS,X ; set CS high
- ORA #SS0
- STA SS,X
- LDA #0 ; set div to 2
- STA DIV,X
- TYA ; retval in A
- RTS
-
-
-;*******************************
-;
-; Send SD command
-; Call with command in CMDHI and CMDLO
-;
-;*******************************
-
-SDCMD: PHY
- LDY #0
-@LOOP: LDA (CMDLO),Y
- STA DATA,X
-@WAIT: BIT CTRL,X ; TC is in N
- BPL @WAIT
- INY
- CPY #6
- BCC @LOOP
- PLY
- RTS
-
-
-;*******************************
-;
-; Get R1
-; R1 is in A
-;
-;*******************************
-
-GETR1: LDA #DUMMY
- STA DATA,X
-@WAIT: BIT CTRL,X
- BPL @WAIT
- LDA DATA,X ; get response
- BIT #$80
- BNE GETR1 ; wait for MSB=0
- PHA
- LDA #DUMMY
- STA DATA,X ; send another dummy
- PLA ; restore R1
- RTS
-
-;*******************************
-;
-; Get R3
-; R1 is in A
-; R3 is in scratchpad ram
-;
-;*******************************
-
-GETR3: JSR GETR1 ; get R1 first
- PHA ; save R1
- PHY ; save Y
- LDY #04 ; load counter
-@LOOP: LDA #DUMMY ; send dummy
- STA DATA,X
-@WAIT: BIT CTRL,X
- BPL @WAIT
- LDA DATA,X
- PHA
- DEY
- BNE @LOOP ; do 4 times
- LDY SLOT
- PLA
- STA R33,Y ; save R3
- PLA
- STA R32,Y
- PLA
- STA R31,Y
- PLA
- STA R30,Y
- PLY ; restore Y
- LDA #DUMMY
- STA DATA,X ; send another dummy
- PLA ; restore R1
- RTS
-
-
-;*******************************
-;
-; Calculate block address
-; Unit number is in $43 DSSS0000
-; Block no is in $46-47
-; Address is in R30-R33
-;
-;*******************************
-
-GETBLOCK: PHX ; save X
- PHY ; save Y
- TXA
- TAY ; SLOT16 is now in Y
- LDX SLOT
- LDA BLOCK ; store block num
- STA R33,X ; in R30-R33
- LDA BLOCK+1
- STA R32,X
- LDA #0
- STA R31,X
- STA R30,X
-
- LDA #$80 ; drive number
- AND $43
- BEQ @SDHC ; D1
- LDA #1 ; D2
- STA R31,X
-
-@SDHC: LDA #SDHC
- AND SS,Y ; if card is SDHC,
- BNE @END ; use block addressing
-
- LDY #9 ; ASL can't be used with Y
-@LOOP: ASL R33,X ; mul block num
- ROL R32,X ; by 512 to get
- ROL R31,X ; real address
- ROL R30,X
- DEY
- BNE @LOOP
-
- @END: PLY ; restore Y
- PLX ; restore X
- RTS
-
-
-;*******************************
-;
-; Send SD command
-; Cmd is in A
-;
-;*******************************
-
-COMMAND: PHY ; save Y
- LDY SLOT
- STA DATA,X ; send command
- LDA R30,Y ; get arg from R30 on
- STA DATA,X
- LDA R31,Y
- STA DATA,X
- LDA R32,Y
- STA DATA,X
- LDA R33,Y
- STA DATA,X
- LDA #DUMMY
- STA DATA,X ; dummy crc
- JSR GETR1
- PLY ; restore Y
- RTS
-
-
-;*******************************
-;
-; Check for card detect
-;
-; C Clear - card in slot
-; Set - no card in slot
-;
-;*******************************
-
-CARDDET: PHA
- LDA #CD ; 0: card in
- BIT SS,X ; 1: card out
- CLC
- BEQ @DONE ; card is in
- SEC ; card is out
-@DONE: PLA
- RTS
-
-
-;*******************************
-;
-; Check for write protect
-;
-; C Clear - card not protected
-; Set - card write protected
-;
-;*******************************
-
-WRPROT: PHA
- LDA #WP ; 0: write enabled
- BIT SS,X ; 1: write disabled
- CLC
- BEQ @DONE
- SEC
-@DONE: PLA
- RTS
-
-
-;*******************************
-;
-; Status request
-; $43 Unit number DSSS000
-; $44-45 Unused
-; $46-47 Unused
-;
-; C Clear - No error
-; Set - Error
-; A $00 - No error
-; $2B - Card write protected
-; $2F - No card inserted
-; X - Blocks avail (low byte)
-; Y - Blocks avail (high byte)
-;
-;*******************************
-
-STATUS: LDA #0 ; no error
- JSR WRPROT
- BCC @DONE
- LDA #$2B ; card write protected
-
-@DONE: LDX #$FF ; 32 MB partition
- LDY #$FF
- RTS
-
-
-;*******************************
-;
-; Read 512 byte block
-; $43 Unit number DSSS0000
-; $44-45 Address (LO/HI) of buffer
-; $46-47 Block number (LO/HI)
-;
-; C Clear - No error
-; Set - Error
-; A $00 - No error
-; $27 - Bad block number
-;
-;*******************************
-
-READ: JSR GETBLOCK ; calc block address
-
- LDA SS,X ; enable /CS
- AND #<~SS0
- STA SS,X
- LDA #$51 ; send CMD17
- JSR COMMAND ; send command
- CMP #0
- BNE @ERROR ; check for error
-
-@GETTOK: LDA #DUMMY ; get data token
- STA DATA,X
- LDA DATA,X ; get response
- CMP #$FE
- BNE @GETTOK ; wait for $FE
-
- LDA CTRL,X ; enable FRX
- ORA #FRX
- STA CTRL,X
- LDA #DUMMY
- STA DATA,X
-
- LDY #0
-@LOOP1: LDA DATA,X ; read data from card
- STA (BUFFER),Y
- INY
- BNE @LOOP1
- INC BUFFER+1 ; inc msb on page boundary
-@LOOP2: LDA DATA,X
- STA (BUFFER),Y
- INY
- BNE @LOOP2
- DEC BUFFER+1
-
-@CRC: LDA DATA,X ; read two bytes crc
- LDA DATA,X ; and ignore
- LDA DATA,X ; read a dummy byte
-
- LDA CTRL,X ; disable FRX
- AND #<~FRX
- STA CTRL,X
- CLC ; no error
- LDA #0
-
-@DONE: PHP
- PHA
- LDA SS,X
- ORA #SS0
- STA SS,X ; disable /CS
- PLA
- PLP
- RTS
-
-@ERROR: SEC ; an error occured
- LDA #$27
- BRA @DONE
-
-
-;*******************************
-;
-; Write 512 byte block
-; $43 Unit number DSSS0000
-; $44-45 Address (LO/HI) of buffer
-; $46-47 Block number (LO/HI)
-;
-; C Clear - No error
-; Set - Error
-; A $00 - No error
-; $27 - I/O error or bad block number
-; $2B - Card write protected
-;
-;*******************************
-
-WRITE: JSR WRPROT
- BCS @WPERROR ; card write protected
-
- JSR GETBLOCK ; calc block address
-
- LDA SS,X ; enable /CS
- AND #<~SS0
- STA SS,X
- LDA #$58 ; send CMD24
- JSR COMMAND ; send command
- CMP #0
- BNE @IOERROR ; check for error
-
- LDA #DUMMY
- STA DATA,X ; send dummy
- LDA #$FE
- STA DATA,X ; send data token
-
- LDY #0
-@LOOP1: LDA (BUFFER),Y
- STA DATA,X
- INY
- BNE @LOOP1
- INC BUFFER+1
-@LOOP2: LDA (BUFFER),Y
- STA DATA,X
- INY
- BNE @LOOP2
- DEC BUFFER+1
-
-@CRC: LDA #DUMMY
- STA DATA,X ; send 2 dummy crc bytes
- STA DATA,X
-
- STA DATA,X ; get data response
- LDA DATA,X
- AND #$1F
- CMP #$05
- BNE @IOERROR ; check for write error
- CLC ; no error
- LDA #0
-
-@DONE: PHP
- PHA
-@WAIT: LDA #DUMMY
- STA DATA,X ; wait for write cycle
- LDA DATA,X ; to complete
- BEQ @WAIT
-
- LDA SS,X ; disable /CS
- ORA #SS0
- STA SS,X
- PLA
- PLP
- RTS
-
-@IOERROR: SEC ; an error occured
- LDA #$27
- BRA @DONE
-
-@WPERROR: SEC
- LDA #$2B
- BRA @DONE
-
-
-
-;*******************************
-;
-; Test routine
-;
-;*******************************
-
- .ifdef DEBUG
-TEST: LDA SLOT16
- PHA
- LDA SLOT
- PHA
-
-; get buffer
- LDA #2 ; get 512 byte buffer
- JSR $BEF5 ; call GETBUFR
- BCS @ERROR
- STA BUFFER+1
- STZ BUFFER
- PLA
- STA SLOT
- PLA
- STA SLOT16
-
-; fill buffer
- LDY #0
-@LOOP: TYA
- STA (BUFFER),Y
- INY
- BNE @LOOP
- INC BUFFER+1
-@LOOP1: TYA
- STA (BUFFER),Y
- INY
- BNE @LOOP1
- DEC BUFFER+1
-
- STZ BLOCK ; block number
- STZ BLOCK+1
- LDX SLOT16
-
-; write to card
- JSR WRITE
- BCS @ERROR
-
-; read from card
- JSR READ
- BCS @ERROR
-
-; check for errors
- LDY #0
-@LOOP2: TYA
- CMP (BUFFER),Y
- BNE @ERRCMP ; error in buffer
- INY
- BNE @LOOP2
- INC BUFFER+1
-@LOOP3: TYA
- CMP (BUFFER),Y
- BNE @ERRCMP
- INY
- BNE @LOOP3
- DEC BUFFER+1
-
-; free buffer
- JSR $BEF8 ; call FREEBUFR
- CLC
- LDA #0
- RTS
-
-@ERROR: BRK
-@ERRCMP: BRK
- .endif
-
-
-TEXT: .asciiz "Apple][Sd v0.8 (c)2017 Florian Reitz"
-
-CMD0: .byt $40, $00, $00
- .byt $00, $00, $95
-CMD1: .byt $41, $00, $00
- .byt $00, $00, $F9
-CMD8: .byt $48, $00, $00
- .byt $01, $AA, $87
-CMD16: .byt $50, $00, $00
- .byt $02, $00, $FF
-CMD55: .byt $77, $00, $00
- .byt $00, $00, $65
-ACMD4140: .byt $69, $40, $00
- .byt $00, $00, $77
-ACMD410: .byt $69, $00, $00
- .byt $00, $00, $FF
-
+;*******************************
+;
+; Apple][Sd Firmware
+; Version 0.8
+;
+; (c) Florian Reitz, 2017
+;
+; X register usually contains SLOT16
+; Y register is used for counting or SLOT
+;
+;*******************************
+
+;DEBUG := 0
+
+; Memory defines
+
+SLOT16 := $2B ; $s0 -> slot * 16
+SLOT := $3D ; $0s
+CMDLO := $40
+CMDHI := $41
+
+DCMD := $42 ; Command code
+BUFFER := $44 ; Buffer address
+BLOCK := $46 ; Block number
+
+CURSLOT := $07F8 ; $Cs
+DATA := $C080
+CTRL := DATA+1
+DIV := DATA+2
+SS := DATA+3
+R30 := $0478
+R31 := $04F8
+R32 := $0578
+R33 := $05F8
+
+; Constants
+
+DUMMY = $FF
+FRX = $10 ; CTRL register
+ECE = $04
+SS0 = $01 ; SS register
+SDHC = $10
+WP = $20
+CD = $40
+INITED = $80
+
+
+; signature bytes
+
+ .segment "SLOTROM"
+ LDX #$20
+ LDX #$00
+ LDX #$03
+ LDX #$01 ; neither Smartport nor 5.25
+
+; find slot nr
+
+ .ifdef DEBUG
+ LDA #$04
+ STA SLOT
+ LDA #$C4
+ STA CURSLOT
+ LDA #$40
+
+ .else
+ PHP
+ SEI
+ LDA #$60 ; opcode for RTS
+ STA SLOT
+ JSR SLOT
+ TSX
+ LDA $0100,X
+ STA CURSLOT ; $Cs
+ AND #$0F
+ PLP
+ STA SLOT ; $0s
+ ASL A
+ ASL A
+ ASL A
+ ASL A
+ .endif
+
+ STA SLOT16 ; $s0
+ TAX ; X holds now SLOT16
+ BIT $CFFF
+ JSR CARDDET
+ BCC @INIT
+ LDA #$2F ; no card inserted
+ RTS
+
+@INIT: JSR INIT
+
+
+;*******************************
+;
+; Install SD card driver
+;
+;*******************************
+
+ .ifdef DEBUG
+
+; see if slot has a driver already
+
+ LDX $BF31 ; get devcnt
+INSTALL: LDA $BF32,X ; get a devnum
+ AND #$70 ; isolate slot
+ CMP SLOT16 ; slot?
+ BEQ @INSOUT ; yes, skip it
+ DEX
+ BPL INSTALL ; keep up the search
+
+; restore the devnum to the list
+
+ LDX $BF31 ; get devcnt again
+ CPX #$0D ; device table full?
+ BNE @INST2
+
+ JSR $FF3A ; bell
+ JMP @INSOUT ; do something!
+
+@INST2: LDA $BF32-1,X ; move all entries down
+ STA $BF32,X ; to make room at front
+ DEX ; for a new entry
+ BNE @INST2
+ LDA #$04 ; ProFile type device
+ ORA SLOT16
+ STA $BF32 ; slot, drive 1 at top of list
+ INC $BF31 ; update devcnt
+
+; now insert the device driver vector
+
+ LDA SLOT
+ ASL
+ TAX
+ LDA #DRIVER
+ STA $BF11,X
+@INSOUT: RTS
+
+
+;*******************************
+;
+; Boot from SD card
+;
+;*******************************
+
+ .else
+
+ .if 0
+BOOT: BEQ @DRAW ; check for error
+ RTS
+
+@DRAW: LDY #0 ; display copyright message
+@DRAW1: LDA TEXT,Y
+ BEQ @BOOT1 ; check for NULL
+ ORA #$80
+ STA $07D0,Y ; put on last line
+ INY
+ BPL @DRAW1
+ .endif
+
+@BOOT1: LDA #$01
+ STA DCMD ; load command
+ LDX SLOT16
+ STX $43 ; slot number
+ LDA #$08
+ STA BUFFER+1 ; buffer hi
+ STZ BUFFER ; buffer lo
+ STZ BLOCK+1 ; block hi
+ STZ BLOCK ; block lo
+ BIT $CFFF
+ JSR READ ; call driver
+
+ LDA #$01
+ STA DCMD ; load command
+ LDX SLOT16
+ STX $43 ; slot number
+ LDA #$0A
+ STA BUFFER+1 ; buffer hi
+ STZ BUFFER ; buffer lo
+ STZ BLOCK+1 ; block hi
+ LDA #$01
+ STA BLOCK ; block lo
+ BIT $CFFF
+ JSR READ ; call driver
+ LDX SLOT16
+ JMP $801 ; goto bootloader
+
+ .endif
+
+
+;*******************************
+;
+; Jump table
+;
+;*******************************
+
+DRIVER: CLD
+
+@SAVEZP: PHA ; make room for retval
+ LDA SLOT16 ; save all ZP locations
+ PHA
+ LDA SLOT
+ PHA
+ LDA CMDLO
+ PHA
+ LDA CMDHI
+ PHA
+
+ .ifdef DEBUG
+ LDA #$04
+ STA SLOT
+ LDA #$C4
+ STA CURSLOT
+ LDA #$40
+
+ .else
+ PHP
+ SEI
+ LDA #$60 ; opcode for RTS
+ STA SLOT
+ JSR SLOT
+ TSX
+ LDA $0100,X
+ STA CURSLOT ; $Cs
+ AND #$0F
+ PLP
+ STA SLOT ; $0s
+ ASL A
+ ASL A
+ ASL A
+ ASL A
+ .endif
+
+ STA SLOT16 ; $s0
+ TAX ; X holds now SLOT16
+ BIT $CFFF
+ JSR CARDDET
+ BCC @INITED
+ LDA #$2F ; no card inserted
+ BRA @RESTZP
+
+@INITED: LDA #INITED ; check for init
+ BIT SS,X
+ BEQ @INIT
+
+@CMD: LDA DCMD ; get command
+ BEQ @STATUS ; branch if cmd is 0
+ CMP #1
+ BEQ @READ
+ CMP #2
+ BEQ @WRITE
+ .ifdef DEBUG
+ CMP #$FF
+ BEQ @TEST
+ .endif
+ LDA #1 ; unknown command
+ SEC
+ BRA @RESTZP
+
+@STATUS: JSR STATUS
+ BRA @RESTZP
+@READ: JSR READ
+ BRA @RESTZP
+@WRITE: JSR WRITE
+ BRA @RESTZP
+ .ifdef DEBUG
+@TEST: JSR TEST ; do device test
+ BRA @RESTZP
+ .endif
+
+@INIT: JSR INIT
+ BCC @CMD ; init ok
+
+@RESTZP: TSX
+ STA $105,X ; save retval on stack
+ PLA ; restore all ZP locations
+ STA CMDHI
+ PLA
+ STA CMDLO
+ PLA
+ STA SLOT
+ PLA
+ STA SLOT16
+ PLA ; get retval
+ RTS
+
+
+; Signature bytes
+
+ .segment "SLOTID"
+ .dbyt $FFFF ; 65535 blocks
+ .byt $97 ; Status bits
+ .byt CMD0
+ STA CMDHI
+ JSR SDCMD
+ JSR GETR1 ; get response
+ CMP #$01
+ BNE @ERROR1 ; error!
+
+ LDA #CMD8
+ STA CMDHI
+ JSR SDCMD
+ JSR GETR3
+ CMP #$01
+ BNE @SDV1 ; may be SD Ver. 1
+
+; check for $01aa match!
+@SDV2: LDA #CMD55
+ STA CMDHI
+ JSR SDCMD
+ JSR GETR1
+ LDA #ACMD4140
+ STA CMDHI
+ JSR SDCMD
+ JSR GETR1
+ CMP #$01
+ BEQ @SDV2 ; wait for ready
+ CMP #0
+ BNE @ERROR1 ; error!
+; send CMD58
+; SD Ver. 2 initialized!
+ LDA SS,X
+ ORA #SDHC
+ STA SS,X
+ JMP @BLOCKSZ
+
+@ERROR1: JMP @IOERROR ; needed for far jump
+
+@SDV1: LDA #CMD55
+ STA CMDHI
+ JSR SDCMD ; ignore response
+ LDA #ACMD410
+ STA CMDHI
+ JSR SDCMD
+ JSR GETR1
+ CMP #$01
+ BEQ @SDV1 ; wait for ready
+ CMP #0
+ BNE @MMC ; may be MMC card
+; SD Ver. 1 initialized!
+ JMP @BLOCKSZ
+
+@MMC: LDA #CMD1
+ STA CMDHI
+@LOOP1: JSR SDCMD
+ JSR GETR1
+ CMP #$01
+ BEQ @LOOP1 ; wait for ready
+ CMP #0
+ BNE @IOERROR ; error!
+; MMC Ver. 3 initialized!
+
+@BLOCKSZ: LDA #CMD16
+ STA CMDHI
+ JSR SDCMD
+ JSR GETR1
+ CMP #0
+ BNE @IOERROR ; error!
+
+@END: LDA SS,X
+ ORA #INITED ; initialized
+ STA SS,X
+ LDA CTRL,X
+ ORA #ECE ; enable 7MHz
+ STA CTRL,X
+ CLC ; all ok
+ LDY #0
+ BCC @END1
+
+@IOERROR: SEC
+ LDY #$27 ; init error
+@END1: LDA SS,X ; set CS high
+ ORA #SS0
+ STA SS,X
+ LDA #0 ; set div to 2
+ STA DIV,X
+ TYA ; retval in A
+ RTS
+
+
+;*******************************
+;
+; Send SD command
+; Call with command in CMDHI and CMDLO
+;
+;*******************************
+
+SDCMD: PHY
+ LDY #0
+@LOOP: LDA (CMDLO),Y
+ STA DATA,X
+@WAIT: BIT CTRL,X ; TC is in N
+ BPL @WAIT
+ INY
+ CPY #6
+ BCC @LOOP
+ PLY
+ RTS
+
+
+;*******************************
+;
+; Get R1
+; R1 is in A
+;
+;*******************************
+
+GETR1: LDA #DUMMY
+ STA DATA,X
+@WAIT: BIT CTRL,X
+ BPL @WAIT
+ LDA DATA,X ; get response
+ BIT #$80
+ BNE GETR1 ; wait for MSB=0
+ PHA
+ LDA #DUMMY
+ STA DATA,X ; send another dummy
+ PLA ; restore R1
+ RTS
+
+;*******************************
+;
+; Get R3
+; R1 is in A
+; R3 is in scratchpad ram
+;
+;*******************************
+
+GETR3: JSR GETR1 ; get R1 first
+ PHA ; save R1
+ PHY ; save Y
+ LDY #04 ; load counter
+@LOOP: LDA #DUMMY ; send dummy
+ STA DATA,X
+@WAIT: BIT CTRL,X
+ BPL @WAIT
+ LDA DATA,X
+ PHA
+ DEY
+ BNE @LOOP ; do 4 times
+ LDY SLOT
+ PLA
+ STA R33,Y ; save R3
+ PLA
+ STA R32,Y
+ PLA
+ STA R31,Y
+ PLA
+ STA R30,Y
+ PLY ; restore Y
+ LDA #DUMMY
+ STA DATA,X ; send another dummy
+ PLA ; restore R1
+ RTS
+
+
+;*******************************
+;
+; Calculate block address
+; Unit number is in $43 DSSS0000
+; Block no is in $46-47
+; Address is in R30-R33
+;
+;*******************************
+
+GETBLOCK: PHX ; save X
+ PHY ; save Y
+ TXA
+ TAY ; SLOT16 is now in Y
+ LDX SLOT
+ LDA BLOCK ; store block num
+ STA R33,X ; in R30-R33
+ LDA BLOCK+1
+ STA R32,X
+ LDA #0
+ STA R31,X
+ STA R30,X
+
+ LDA #$80 ; drive number
+ AND $43
+ BEQ @SDHC ; D1
+ LDA #1 ; D2
+ STA R31,X
+
+@SDHC: LDA #SDHC
+ AND SS,Y ; if card is SDHC,
+ BNE @END ; use block addressing
+
+ LDY #9 ; ASL can't be used with Y
+@LOOP: ASL R33,X ; mul block num
+ ROL R32,X ; by 512 to get
+ ROL R31,X ; real address
+ ROL R30,X
+ DEY
+ BNE @LOOP
+
+ @END: PLY ; restore Y
+ PLX ; restore X
+ RTS
+
+
+;*******************************
+;
+; Send SD command
+; Cmd is in A
+;
+;*******************************
+
+COMMAND: PHY ; save Y
+ LDY SLOT
+ STA DATA,X ; send command
+ LDA R30,Y ; get arg from R30 on
+ STA DATA,X
+ LDA R31,Y
+ STA DATA,X
+ LDA R32,Y
+ STA DATA,X
+ LDA R33,Y
+ STA DATA,X
+ LDA #DUMMY
+ STA DATA,X ; dummy crc
+ JSR GETR1
+ PLY ; restore Y
+ RTS
+
+
+;*******************************
+;
+; Check for card detect
+;
+; C Clear - card in slot
+; Set - no card in slot
+;
+;*******************************
+
+CARDDET: PHA
+ LDA #CD ; 0: card in
+ BIT SS,X ; 1: card out
+ CLC
+ BEQ @DONE ; card is in
+ SEC ; card is out
+@DONE: PLA
+ RTS
+
+
+;*******************************
+;
+; Check for write protect
+;
+; C Clear - card not protected
+; Set - card write protected
+;
+;*******************************
+
+WRPROT: PHA
+ LDA #WP ; 0: write enabled
+ BIT SS,X ; 1: write disabled
+ CLC
+ BEQ @DONE
+ SEC
+@DONE: PLA
+ RTS
+
+
+;*******************************
+;
+; Status request
+; $43 Unit number DSSS000
+; $44-45 Unused
+; $46-47 Unused
+;
+; C Clear - No error
+; Set - Error
+; A $00 - No error
+; $2B - Card write protected
+; $2F - No card inserted
+; X - Blocks avail (low byte)
+; Y - Blocks avail (high byte)
+;
+;*******************************
+
+STATUS: LDA #0 ; no error
+ JSR WRPROT
+ BCC @DONE
+ LDA #$2B ; card write protected
+
+@DONE: LDX #$FF ; 32 MB partition
+ LDY #$FF
+ RTS
+
+
+;*******************************
+;
+; Read 512 byte block
+; $43 Unit number DSSS0000
+; $44-45 Address (LO/HI) of buffer
+; $46-47 Block number (LO/HI)
+;
+; C Clear - No error
+; Set - Error
+; A $00 - No error
+; $27 - Bad block number
+;
+;*******************************
+
+READ: JSR GETBLOCK ; calc block address
+
+ LDA SS,X ; enable /CS
+ AND #<~SS0
+ STA SS,X
+ LDA #$51 ; send CMD17
+ JSR COMMAND ; send command
+ CMP #0
+ BNE @ERROR ; check for error
+
+@GETTOK: LDA #DUMMY ; get data token
+ STA DATA,X
+ LDA DATA,X ; get response
+ CMP #$FE
+ BNE @GETTOK ; wait for $FE
+
+ LDA CTRL,X ; enable FRX
+ ORA #FRX
+ STA CTRL,X
+ LDA #DUMMY
+ STA DATA,X
+
+ LDY #0
+@LOOP1: LDA DATA,X ; read data from card
+ STA (BUFFER),Y
+ INY
+ BNE @LOOP1
+ INC BUFFER+1 ; inc msb on page boundary
+@LOOP2: LDA DATA,X
+ STA (BUFFER),Y
+ INY
+ BNE @LOOP2
+ DEC BUFFER+1
+
+@CRC: LDA DATA,X ; read two bytes crc
+ LDA DATA,X ; and ignore
+ LDA DATA,X ; read a dummy byte
+
+ LDA CTRL,X ; disable FRX
+ AND #<~FRX
+ STA CTRL,X
+ CLC ; no error
+ LDA #0
+
+@DONE: PHP
+ PHA
+ LDA SS,X
+ ORA #SS0
+ STA SS,X ; disable /CS
+ PLA
+ PLP
+ RTS
+
+@ERROR: SEC ; an error occured
+ LDA #$27
+ BRA @DONE
+
+
+;*******************************
+;
+; Write 512 byte block
+; $43 Unit number DSSS0000
+; $44-45 Address (LO/HI) of buffer
+; $46-47 Block number (LO/HI)
+;
+; C Clear - No error
+; Set - Error
+; A $00 - No error
+; $27 - I/O error or bad block number
+; $2B - Card write protected
+;
+;*******************************
+
+WRITE: JSR WRPROT
+ BCS @WPERROR ; card write protected
+
+ JSR GETBLOCK ; calc block address
+
+ LDA SS,X ; enable /CS
+ AND #<~SS0
+ STA SS,X
+ LDA #$58 ; send CMD24
+ JSR COMMAND ; send command
+ CMP #0
+ BNE @IOERROR ; check for error
+
+ LDA #DUMMY
+ STA DATA,X ; send dummy
+ LDA #$FE
+ STA DATA,X ; send data token
+
+ LDY #0
+@LOOP1: LDA (BUFFER),Y
+ STA DATA,X
+ INY
+ BNE @LOOP1
+ INC BUFFER+1
+@LOOP2: LDA (BUFFER),Y
+ STA DATA,X
+ INY
+ BNE @LOOP2
+ DEC BUFFER+1
+
+@CRC: LDA #DUMMY
+ STA DATA,X ; send 2 dummy crc bytes
+ STA DATA,X
+
+ STA DATA,X ; get data response
+ LDA DATA,X
+ AND #$1F
+ CMP #$05
+ BNE @IOERROR ; check for write error
+ CLC ; no error
+ LDA #0
+
+@DONE: PHP
+ PHA
+@WAIT: LDA #DUMMY
+ STA DATA,X ; wait for write cycle
+ LDA DATA,X ; to complete
+ BEQ @WAIT
+
+ LDA SS,X ; disable /CS
+ ORA #SS0
+ STA SS,X
+ PLA
+ PLP
+ RTS
+
+@IOERROR: SEC ; an error occured
+ LDA #$27
+ BRA @DONE
+
+@WPERROR: SEC
+ LDA #$2B
+ BRA @DONE
+
+
+
+;*******************************
+;
+; Test routine
+;
+;*******************************
+
+ .ifdef DEBUG
+TEST: LDA SLOT16
+ PHA
+ LDA SLOT
+ PHA
+
+; get buffer
+ LDA #2 ; get 512 byte buffer
+ JSR $BEF5 ; call GETBUFR
+ BCS @ERROR
+ STA BUFFER+1
+ STZ BUFFER
+ PLA
+ STA SLOT
+ PLA
+ STA SLOT16
+
+; fill buffer
+ LDY #0
+@LOOP: TYA
+ STA (BUFFER),Y
+ INY
+ BNE @LOOP
+ INC BUFFER+1
+@LOOP1: TYA
+ STA (BUFFER),Y
+ INY
+ BNE @LOOP1
+ DEC BUFFER+1
+
+ STZ BLOCK ; block number
+ STZ BLOCK+1
+ LDX SLOT16
+
+; write to card
+ JSR WRITE
+ BCS @ERROR
+
+; read from card
+ JSR READ
+ BCS @ERROR
+
+; check for errors
+ LDY #0
+@LOOP2: TYA
+ CMP (BUFFER),Y
+ BNE @ERRCMP ; error in buffer
+ INY
+ BNE @LOOP2
+ INC BUFFER+1
+@LOOP3: TYA
+ CMP (BUFFER),Y
+ BNE @ERRCMP
+ INY
+ BNE @LOOP3
+ DEC BUFFER+1
+
+; free buffer
+ JSR $BEF8 ; call FREEBUFR
+ CLC
+ LDA #0
+ RTS
+
+@ERROR: BRK
+@ERRCMP: BRK
+ .endif
+
+
+TEXT: .asciiz "Apple][Sd v0.8 (c)2017 Florian Reitz"
+
+CMD0: .byt $40, $00, $00
+ .byt $00, $00, $95
+CMD1: .byt $41, $00, $00
+ .byt $00, $00, $F9
+CMD8: .byt $48, $00, $00
+ .byt $01, $AA, $87
+CMD16: .byt $50, $00, $00
+ .byt $02, $00, $FF
+CMD55: .byt $77, $00, $00
+ .byt $00, $00, $65
+ACMD4140: .byt $69, $40, $00
+ .byt $00, $00, $77
+ACMD410: .byt $69, $00, $00
+ .byt $00, $00, $FF
+