diff --git a/AppleIISd.bin b/AppleIISd.bin index cf167ab..7fd6750 100644 Binary files a/AppleIISd.bin and b/AppleIISd.bin differ diff --git a/AppleIISd.vcxproj b/AppleIISd.vcxproj index b3f344d..7b893e5 100644 --- a/AppleIISd.vcxproj +++ b/AppleIISd.vcxproj @@ -15,7 +15,10 @@ + + + {9EA7EC3D-1771-420F-932F-231A35ED1200} diff --git a/AppleIISd.vcxproj.filters b/AppleIISd.vcxproj.filters index 2f91e44..5c8a181 100644 --- a/AppleIISd.vcxproj.filters +++ b/AppleIISd.vcxproj.filters @@ -10,6 +10,15 @@ + + src + + + src + + + src + diff --git a/src/AppleIISd.inc b/src/AppleIISd.inc new file mode 100644 index 0000000..1492ace --- /dev/null +++ b/src/AppleIISd.inc @@ -0,0 +1,45 @@ +;******************************* +; +; Apple][Sd Firmware +; Version 1.1 +; Defines +; +; (c) Florian Reitz, 2017 +; +; X register usually contains SLOT16 +; Y register is used for counting or SLOT +; +;******************************* + +; 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 + +R30 := $0478 +R31 := $04F8 +R32 := $0578 +R33 := $05F8 +CURSLOT := $07F8 ; $Cs +OAPPLE := $C061 ; open apple key +DATA := $C080 +CTRL := DATA+1 +DIV := DATA+2 +SS := DATA+3 + +; Constants + +DUMMY = $FF +FRX = $10 ; CTRL register +ECE = $04 +SS0 = $01 ; SS register +SDHC = $10 +WP = $20 +CD = $40 +INITED = $80 diff --git a/src/AppleIISd.s b/src/AppleIISd.s index f1cc9ed..9e3c3a2 100644 --- a/src/AppleIISd.s +++ b/src/AppleIISd.s @@ -2,6 +2,7 @@ ; ; Apple][Sd Firmware ; Version 1.1 +; Main source ; ; (c) Florian Reitz, 2017 ; @@ -10,43 +11,42 @@ ; ;******************************* -.define DEBUG 0 - -; Memory defines +.import GETR1 +.import GETR3 +.import SDCMD +.import CARDDET +.import STATUS +.import READ +.import WRITE -SLOT16 := $2B ; $s0 -> slot * 16 -SLOT := $3D ; $0s -CMDLO := $40 -CMDHI := $41 - -DCMD := $42 ; Command code -BUFFER := $44 ; Buffer address -BLOCK := $46 ; Block number - -R30 := $0478 -R31 := $04F8 -R32 := $0578 -R33 := $05F8 -CURSLOT := $07F8 ; $Cs -OAPPLE := $C061 ; open apple key -DATA := $C080 -CTRL := DATA+1 -DIV := DATA+2 -SS := DATA+3 - -; Constants - -DUMMY = $FF -FRX = $10 ; CTRL register -ECE = $04 -SS0 = $01 ; SS register -SDHC = $10 -WP = $20 -CD = $40 -INITED = $80 +.include "AppleIISd.inc" -; signature bytes +;******************************* +; +; Signature bytes +; +; 65535 blocks +; Removable media +; Non-interruptable +; 2 drives +; Read, write and status allowed +; +;******************************* + + .segment "SLOTID" + .dbyt $FFFF ; 65535 blocks + .byt $97 ; Status bits + .byt DRIVER - STA $BF11,X -@INSOUT: RTS - - ;******************************* ; ; Boot from SD card ; ;******************************* - .else -;@BOOT: CMP #0 -; BNE @NEXTSLOT ; init not successful +;@BOOT: CMP #0 +; BNE @NEXTSLOT ; init not successful @BOOT: LDA #$01 STA DCMD ; load command LDX SLOT16 @@ -190,7 +131,6 @@ INITED = $80 JSR READ ; call driver LDX SLOT16 JMP $801 ; goto bootloader - .endif ;******************************* @@ -210,15 +150,6 @@ DRIVER: CLD PHA LDA CMDHI PHA - - .if DEBUG - LDA #$04 - STA SLOT - LDA #$C4 - STA CURSLOT - LDA #$40 - - .else PHP SEI LDA #$60 ; opcode for RTS @@ -234,7 +165,6 @@ DRIVER: CLD ASL A ASL A ASL A - .endif STA SLOT16 ; $s0 TAX ; X holds now SLOT16 @@ -254,10 +184,6 @@ DRIVER: CLD BEQ @READ CMP #2 BEQ @WRITE - .if DEBUG - CMP #$FF - BEQ @TEST - .endif LDA #1 ; unknown command SEC BRA @RESTZP @@ -268,10 +194,6 @@ DRIVER: CLD BRA @RESTZP @WRITE: JSR WRITE BRA @RESTZP - .if DEBUG -@TEST: JSR TEST ; do device test - BRA @RESTZP - .endif @INIT: JSR INIT BCC @CMD ; init ok @@ -290,24 +212,6 @@ DRIVER: CLD RTS -;******************************* -; -; Signature bytes -; -; 65535 blocks -; Removable media -; Non-interruptable -; 2 drives -; Read, write and status allowed -; -;******************************* - - .segment "SLOTID" - .dbyt $FFFF ; 65535 blocks - .byt $97 ; Status bits - .byt CMD8 STA CMDHI JSR SDCMD - JSR GETR3 ; R7 is also 1+4 bytes + JSR GETR3 ; R7 is also 1+4 bytes CMP #$01 BNE @SDV1 ; may be SD Ver. 1 - LDY SLOT ; check for $aa in R33 - LDA R33,Y - CMP #$AA - BNE @ERROR1 ; error! + LDY SLOT ; check for $aa in R33 + LDA R33,Y + CMP #$AA + BNE @ERROR1 ; error! @SDV2: LDA #ACMD4140 STA CMDHI @@ -381,20 +285,20 @@ INIT: LDA #$03 ; set SPI mode 3 BNE @ERROR1 ; error! ; SD Ver. 2 initialized! - LDA #CMD58 - STA CMDHI - JSR SDCMD - JSR GETR3 - CMP #0 - BNE @ERROR1 ; error! - LDY SLOT - LDA R30,Y - AND #$40 ; check CCS - BEQ @BLOCKSZ - - LDA SS,X ; card is SDHC + LDA #CMD58 + STA CMDHI + JSR SDCMD + JSR GETR3 + CMP #0 + BNE @ERROR1 ; error! + LDY SLOT + LDA R30,Y + AND #$40 ; check CCS + BEQ @BLOCKSZ + + LDA SS,X ; card is SDHC ORA #SDHC STA SS,X JMP @END @@ -461,445 +365,6 @@ INIT: LDA #$03 ; set SPI mode 3 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 or R7 -; 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 - JMP @WAIT ; first byte is already there -@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 ; R30 is MSB - 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 -; -;******************************* - - .if 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 v1.1 (c)2017 Florian Reitz" CMD0: .byt $40, $00, $00 @@ -911,11 +376,10 @@ CMD8: .byt $48, $00, $00 CMD16: .byt $50, $00, $00 .byt $02, $00, $FF CMD55: .byt $77, $00, $00 - .byt $00, $00, $FF -CMD58: .byt $7A, $00, $00 + .byt $00, $00, $FF +CMD58: .byt $7A, $00, $00 .byt $00, $00, $FF ACMD4140: .byt $69, $40, $00 .byt $00, $00, $77 ACMD410: .byt $69, $00, $00 .byt $00, $00, $FF - diff --git a/src/Helper.s b/src/Helper.s new file mode 100644 index 0000000..4f7061c --- /dev/null +++ b/src/Helper.s @@ -0,0 +1,208 @@ +;******************************* +; +; Apple][Sd Firmware +; Version 1.1 +; Helper functions +; +; (c) Florian Reitz, 2017 +; +; X register usually contains SLOT16 +; Y register is used for counting or SLOT +; +;******************************* + +.export COMMAND +.export SDCMD +.export GETBLOCK +.export CARDDET +.export WRPROT +.export GETR1 +.export GETR3 + +.include "AppleIISd.inc" +.segment "EXTROM" + + +;******************************* +; +; 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 or R7 +; 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 + JMP @WAIT ; first byte is already there +@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 ; R30 is MSB + 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 diff --git a/src/ProDOS.s b/src/ProDOS.s new file mode 100644 index 0000000..44f68ed --- /dev/null +++ b/src/ProDOS.s @@ -0,0 +1,205 @@ +;******************************* +; +; Apple][Sd Firmware +; Version 1.1 +; ProDOS functions +; +; (c) Florian Reitz, 2017 +; +; X register usually contains SLOT16 +; Y register is used for counting or SLOT +; +;******************************* + +.export STATUS +.export READ +.export WRITE + +.import COMMAND +.import SDCMD +.import GETBLOCK +.import WRPROT +.import GETR1 +.import GETR3 + +.include "AppleIISd.inc" +.segment "EXTROM" + + +;******************************* +; +; 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