Permalink
Cannot retrieve contributors at this time
1655 lines (1218 sloc)
32.9 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;========================================================================================== | |
| ; | |
| ; UNOFFICIAL SNES POWERPAK FIRMWARE V3.10 (CODENAME: "MUFASA") | |
| ; (c) 2019 by ManuLöwe (https://manuloewe.de/) | |
| ; | |
| ; *** MAIN CODE SECTION: CF INTERFACE *** | |
| ; Code in this file based on v1.0X code written by: | |
| ; - bunnyboy (SNES PowerPak creator), (c) 2009 | |
| ; | |
| ;========================================================================================== | |
| .INDEX 16 | |
| ; ************************ Begin CF interaction ************************ | |
| AccessCFcard: | |
| ;CardReset: ; this used to be a subroutine | |
| lda #%00000000 | |
| sta CARDLBA3 ; select card 0 | |
| lda #%00000110 ; do card sw reset | |
| sta CARDDEVICE ; in device ctl reg | |
| wai | |
| wai | |
| lda #%00000010 | |
| sta CARDDEVICE ; clear reset | |
| wai | |
| wai ; end of former subroutine | |
| wai | |
| jsr SpriteMessageError ; show preliminary error message (removed upon successful card access) | |
| StateCardNotInserted: ; wait until card inserted, show no card message | |
| lda CARDSTATUS | |
| sta errorCode | |
| and #%11110000 ; open bus = $A0 | |
| cmp #$A0 | |
| bne @StateCardInserted | |
| SetTextPos 21, 1 | |
| PrintString "CF card not found.\n Error code: $" | |
| PrintHexNum errorCode | |
| jsr PrintRomVersion | |
| jsr ShowConsoleVersion | |
| jsr ShowMainGFX ; show logo | |
| jmp Forever | |
| @StateCardInserted: | |
| StateCardBusy: ; wait until card not busy, show card busy message | |
| lda CARDSTATUS | |
| sta errorCode | |
| bpl @StateCardBusyDone ; MSB clear --> card not busy | |
| wai | |
| SetTextPos 21, 1 | |
| PrintString "CF card busy. \n Error code: $" | |
| PrintHexNum errorCode | |
| bra StateCardBusy | |
| @StateCardBusyDone: | |
| StateCardReady: ; wait until card ready, show card not ready message | |
| lda CARDSTATUS | |
| sta errorCode | |
| and #%01010000 | |
| cmp #%01010000 ; ready = $50 | |
| beq @StateCardReadyDone | |
| wai | |
| SetTextPos 21, 1 | |
| PrintString "CF card not ready.\n Error code: $" | |
| PrintHexNum errorCode | |
| bra StateCardReady | |
| @StateCardReadyDone: | |
| ; -------------------------- read card, check format | |
| SetTextPos 21, 1 | |
| PrintString "Reading CF card ..." | |
| lda #%00000001 ; set DMA off flag for now (this is later overwritten by the actual user setting) | |
| tsb DP_UserSettings | |
| ; stz sourceSector ; it's not necessary to clear sourceSector at this point as WRAM was zero-filled upon boot | |
| ; stz sourceSector+1 | |
| ; stz sourceSector+2 | |
| ; stz sourceSector+3 | |
| ldx #sectorBuffer1 | |
| stx destLo | |
| stz destBank | |
| lda #kWRAM | |
| sta DP_DataDestination | |
| jsr CardReadSector ; read sector 0 | |
| Accu16 | |
| lda sectorBuffer1+$1FE ; last word (FAT signature) check, should be $AA55 | |
| cmp #$AA55 | |
| beq + | |
| Accu8 | |
| jmp CardFormatError | |
| + ldx #$0000 ; x = partition index 0, 16, 32, 48 | |
| CardFormatCheckLoop: | |
| Accu8 | |
| lda #$01 ; assume FAT32 for now | |
| sta fat32Enabled | |
| lda sectorBuffer1+$1C2, x ; read partition type code | |
| cmp #$0B ; 0Bh = FAT32 | |
| beq CardGoodFormat | |
| cmp #$0C ; 0Ch = FAT32 with LBA1 13h Extensions | |
| beq CardGoodFormat | |
| stz fat32Enabled ; byte isn't 0Bh or 0Ch --> partition is not FAT32 | |
| cmp #$06 ; 06h = FAT16, larger than 32MB | |
| beq CardGoodFormat | |
| cmp #$04 ; 04h = FAT16, smaller than 32MB | |
| beq CardGoodFormat | |
| cmp #$0E ; 0Eh = FAT16 with LBA1 13h Extensions | |
| beq CardGoodFormat | |
| Accu16 | |
| txa ; increment index to next partition entry | |
| clc | |
| adc #16 | |
| tax | |
| cmp #64 ; all 4 partition entries checked? | |
| bne CardFormatCheckLoop | |
| Accu8 | |
| jmp CardFormatError ; no usable partition type code found --> error | |
| CardGoodFormat: ; FAT16/FAT32 partition found | |
| stx partitionIndex | |
| ClearLine 21 ; hide "Reading CF card ..." | |
| ClearLine 22 ; hide possible error code (from CF busy/not ready message) | |
| jsr ClearSpriteText ; remove preliminary error message | |
| jsr PrintCardFS ; show CF card filesystem type | |
| ldx partitionIndex | |
| ldy #$0000 | |
| CardCopyPartitionLBABegin: ; copy partitionLBABegin from offset 454 | |
| lda sectorBuffer1+$1C6, x | |
| sta sourceSector, y | |
| sta partitionLBABegin, y | |
| inx | |
| iny | |
| cpy #$0004 | |
| bne CardCopyPartitionLBABegin | |
| ldx #sectorBuffer1 | |
| stx destLo | |
| stz destBank | |
| lda #kWRAM | |
| sta DP_DataDestination | |
| jsr CardReadSector ; read FAT16/FAT32 Volume ID sector (partition boot record) | |
| lda sectorBuffer1+$0D ; copy FAT16/FAT32 sectorsPerCluster from offset 13 | |
| sta sectorsPerCluster | |
| lda sectorBuffer1+$0E ; copy FAT16/FAT32 reservedSectors from offset 14 | |
| sta reservedSectors | |
| lda sectorBuffer1+$0F | |
| sta reservedSectors+1 | |
| ldx #$0000 | |
| CardCopySectorsPerFat: ; copy FAT32 sectorsPerFat from offset 36 | |
| lda sectorBuffer1+$24, x | |
| sta sectorsPerFat, x | |
| inx | |
| cpx #$0004 | |
| bne CardCopySectorsPerFat | |
| ldx #$0000 | |
| CardCopyRootDirCluster32: ; copy FAT32 rootDirCluster from offset 44 | |
| lda sectorBuffer1+$2C, x | |
| sta rootDirCluster, x | |
| inx | |
| cpx #$0004 | |
| bne CardCopyRootDirCluster32 | |
| stz fat16RootSectors ; FAT32 no entry limit in root directory | |
| lda fat32Enabled | |
| cmp #$01 | |
| beq CardCopyFatBeginLBA ; when FAT32, leave alone | |
| ;;;SPECIAL FAT16 handling | |
| CardCopyRootDirCluster16: | |
| stz rootDirCluster | |
| stz rootDirCluster+1 ; when FAT16, rootDirCluster = 0000 (root dir is not in cluster nums) | |
| stz rootDirCluster+2 | |
| stz rootDirCluster+3 | |
| lda sectorBuffer1+$16 | |
| sta sectorsPerFat ; FAT16 copy sectorsPerFat from offset 22 | |
| lda sectorBuffer1+$17 | |
| sta sectorsPerFat+1 | |
| stz sectorsPerFat+2 | |
| stz sectorsPerFat+3 ; FAT16 sectors per fat = 16 bits, in different place than FAT32 | |
| CardCopyRootDirEntries16: ; copy max root directory entries from offset 17 | |
| lda sectorBuffer1+$11 | |
| sta fat16RootSectors | |
| lda sectorBuffer1+$12 | |
| sta fat16RootSectors+1 | |
| ; clc | |
| ; lsr fat16RootSectors | |
| ; lsr fat16RootSectors ; FAT16 rootSectors = (max root entries * 32) / 512 = fat16RootSectors/16 ASR x4 | |
| ; lsr fat16RootSectors | |
| ; lsr fat16RootSectors | |
| lda #$20 | |
| sta fat16RootSectors ; FAT16 root dir fixed at 512 entries = 32 sectors | |
| CardCopyFatBeginLBA: | |
| Accu16 | |
| clc ; fatBeginLBA(4) = partitionLBABegin(4) + reservedSectors(2) | |
| lda reservedSectors | |
| adc partitionLBABegin | |
| sta fatBeginLBA | |
| lda partitionLBABegin+2 | |
| adc #$0000 | |
| sta fatBeginLBA+2 | |
| ;CardCopyClusterBeginLBA: | |
| lda sectorsPerFat | |
| sta clusterBeginLBA | |
| lda sectorsPerFat+2 | |
| sta clusterBeginLBA+2 | |
| clc | |
| asl clusterBeginLBA ; clusterBeginLBA(4) = fatBeginLBA(4) + (2 * sectorPerFat(4)) | |
| rol clusterBeginLBA+2 | |
| Accu8 | |
| clc ; FAT16 = 32 sectors FAT32 = 0 sectors | |
| lda clusterBeginLBA ; clusterBeginLBA(4) = clusterBeginLBA(4) + fat16RootSectors(1) | |
| adc fat16RootSectors | |
| sta clusterBeginLBA | |
| lda clusterBeginLBA+1 | |
| adc #$00 | |
| sta clusterBeginLBA+1 | |
| Accu16 | |
| lda clusterBeginLBA+2 | |
| adc #$0000 | |
| sta clusterBeginLBA+2 | |
| clc | |
| lda clusterBeginLBA | |
| adc fatBeginLBA | |
| sta clusterBeginLBA | |
| lda clusterBeginLBA+2 | |
| adc fatBeginLBA+2 | |
| sta clusterBeginLBA+2 | |
| lda rootDirCluster | |
| sta sourceCluster | |
| lda rootDirCluster+2 | |
| sta sourceCluster+2 | |
| Accu8 | |
| ; PrintString "\n" | |
| ; PrintHexNum sectorsPerCluster | |
| ; PrintString "\n" | |
| .IFDEF DEBUG | |
| PrintString "fat16 != " | |
| PrintHexNum fat32Enabled | |
| PrintString " RootSectors $" | |
| PrintHexNum fat16RootSectors | |
| PrintString "\n" | |
| PrintString "sectorsPerFat $" | |
| PrintHexNum sectorsPerFat+3 | |
| PrintHexNum sectorsPerFat+2 | |
| PrintHexNum sectorsPerFat+1 | |
| PrintHexNum sectorsPerFat+0 | |
| PrintString "\n" | |
| PrintString "partitionLBABegin $" | |
| PrintHexNum partitionLBABegin+3 | |
| PrintHexNum partitionLBABegin+2 | |
| PrintHexNum partitionLBABegin+1 | |
| PrintHexNum partitionLBABegin+0 | |
| PrintString "\n" | |
| PrintString "reservedSectors $" | |
| PrintHexNum reservedSectors+1 | |
| PrintHexNum reservedSectors+0 | |
| PrintString "\n" | |
| PrintString "fatBeginLBA $" | |
| PrintHexNum fatBeginLBA+3 | |
| PrintHexNum fatBeginLBA+2 | |
| PrintHexNum fatBeginLBA+1 | |
| PrintHexNum fatBeginLBA+0 | |
| PrintString "\n" | |
| PrintString "rootDirCluster $" | |
| PrintHexNum rootDirCluster+3 | |
| PrintHexNum rootDirCluster+2 | |
| PrintHexNum rootDirCluster+1 | |
| PrintHexNum rootDirCluster+0 | |
| PrintString "\n" | |
| .ENDIF | |
| rts | |
| ; ************************* CF error handling ************************** | |
| CardFormatError: | |
| jsr PrintRomVersion | |
| ClearLine 21 | |
| ClearLine 22 | |
| SetTextPos 21, 1 | |
| PrintString "Card format error: FAT16/FAT32 expected!" | |
| PrintString "\n Type code: $" | |
| PrintHexNum sectorBuffer1+$1C2 ; partition type code | |
| PrintString " | Last word ($AA55): $" | |
| PrintHexNum sectorBuffer1+$1FF ; high byte of signature word | |
| PrintHexNum sectorBuffer1+$1FE ; low byte of signature word | |
| jmp Forever | |
| CardWaitNotBusy: | |
| @CardWaitNotBusyLoop: ; wait for not busy | |
| lda CARDSTATUS ; card status read | |
| ; sta errorCode | |
| bpl @CardWaitNotBusyDone ; MSB = card busy flag | |
| ; SetTextPos 12, 0 | |
| ; PrintString " Error $" | |
| ; PrintHexNum errorCode | |
| ; PrintString " - CF card busy " | |
| bra @CardWaitNotBusyLoop | |
| @CardWaitNotBusyDone: | |
| rts | |
| CardWaitReady: | |
| @CardWaitReadyLoop: ; wait until card ready | |
| lda CARDSTATUS | |
| ; sta errorCode | |
| and #%01010000 | |
| cmp #%01010000 | |
| beq @CardWaitReadyDone | |
| ; SetTextPos 12, 0 | |
| ; PrintString " Error $" | |
| ; PrintHexNum errorCode | |
| ; PrintString " - CF not ready " | |
| bra @CardWaitReadyLoop | |
| @CardWaitReadyDone: | |
| rts | |
| CardWaitDataReq: ; wait for not busy, ready, datareq, no error | |
| @CardWaitDataReqLoop: | |
| lda CARDSTATUS | |
| ; sta errorCode | |
| and #%01011000 | |
| cmp #%01011000 | |
| beq @CardWaitDataReqDone | |
| ; SetTextPos 12, 0 | |
| ; PrintString " Error $" | |
| ; PrintHexNum errorCode | |
| ; PrintString " - CF no data req " | |
| bra @CardWaitDataReqLoop | |
| @CardWaitDataReqDone: | |
| rts | |
| /* | |
| CardTESTCheckError: | |
| SetTextPos 22, 0 | |
| PrintString " " | |
| wai | |
| sei ; disable NMI & IRQ | |
| stz REG_NMITIMEN | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| lda CARDSTATUS ; get card status, check for general error | |
| sta errorCode | |
| and #%00000001 | |
| bne CardError | |
| lda REG_RDNMI ; clear NMI flag | |
| lda #$81 | |
| sta REG_NMITIMEN ; re-enable VBlank NMI | |
| cli | |
| SetTextPos 22, 0 | |
| PrintString "OK" | |
| rts | |
| */ | |
| CardCheckError: | |
| lda CARDSTATUS ; get card status, check for general error | |
| sta errorCode | |
| and #%00000001 | |
| ; bne CardError ; CAVEAT: THIS MYSTERIOUSLY DOES NOT WORK!!! | |
| cmp #%00000001 | |
| beq @CardError | |
| rts | |
| @CardError: | |
| ClearLine 21 | |
| ClearLine 22 | |
| ClearLine 23 | |
| SetTextPos 21, 1 | |
| ldy #errorCode | |
| PrintString "Error $%x - CF card status" | |
| lda CARDERROR | |
| sta errorCode | |
| ldy #errorCode | |
| PrintString "\n Error $%x - CF card error" | |
| lda CARDSECTORCOUNTREAD | |
| sta errorCode | |
| ldy #errorCode | |
| PrintString "\n CSCR=$%x" | |
| lda CARDLBA0READ | |
| sta errorCode | |
| ldy #errorCode | |
| PrintString " | LBA0=$%x" | |
| lda CARDLBA1READ | |
| sta errorCode | |
| ldy #errorCode | |
| PrintString " | LBA1=$%x" | |
| lda CARDLBA2READ | |
| sta errorCode | |
| ldy #errorCode | |
| PrintString " | LBA2=$%x" | |
| lda CARDLBA3READ | |
| sta errorCode | |
| ldy #errorCode | |
| PrintString " | LBA3=$%x" | |
| jmp Forever | |
| ; ************************* Read from CF card ************************** | |
| CardLoadLBA: | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| jsr CardCheckError | |
| lda #$01 | |
| sta CARDSECTORCOUNT | |
| jsr CardWaitNotBusy ; LAST check busy/ready/error after each command | |
| jsr CardWaitReady | |
| ; jsr CardCheckError | |
| lda sourceSector | |
| sta CARDLBA0 | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| ; jsr CardCheckError | |
| lda sourceSector+1 | |
| sta CARDLBA1 | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| ; jsr CardCheckError | |
| lda sourceSector+2 | |
| sta CARDLBA2 | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| ; jsr CardCheckError | |
| lda sourceSector+3 ; load LBA number | |
| and #%00001111 | |
| ora #%11100000 | |
| sta sourceSector+3 | |
| sta CARDLBA3 | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| jsr CardCheckError | |
| rts | |
| CardReadSector: | |
| sei ; disable NMI & IRQ | |
| stz REG_NMITIMEN | |
| jsr CardLoadLBA | |
| lda #$20 | |
| sta CARDCOMMAND ; send card read sector command | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| jsr CardCheckError | |
| jsr CardWaitDataReq | |
| lda DP_DataDestination ; read data destination | |
| Accu16 | |
| and #$00FF ; remove garbage in Accu B | |
| asl a ; use DP_DataDestination as a jump table index | |
| tax | |
| Accu8 | |
| jmp (@PTR_kDest, x) | |
| @PTR_kDest: | |
| .DW @CRS_toFPGA | |
| .DW @CRS_toSDRAM | |
| .DW @CRS_toSDRAMnoDMA | |
| .DW @CRS_toWRAM | |
| .DW @CRS_toWRAMnoDMA | |
| @CRS_toFPGA: | |
| ldx #512 ; transfer 512 bytes | |
| - lda CARDDATAREAD ; read data byte | |
| sta FPGADATAWRITE ; write to FPGA | |
| dex | |
| bne - | |
| jmp @CRS_Done | |
| @CRS_toSDRAM: | |
| DMA_WaitHblank $08, CARDDATAREADbank, CARDDATAREADhigh, CARDDATAREADlow, DMAPORT, 512 | |
| bra @CRS_Done | |
| @CRS_toSDRAMnoDMA: | |
| ldx #512 ; transfer 512 bytes | |
| - lda CARDDATAREAD ; read data byte | |
| sta DMAREADDATA ; write to SDRAM | |
| dex | |
| bne - | |
| bra @CRS_Done | |
| @CRS_toWRAM: | |
| lda DP_UserSettings | |
| and #%00000001 ; check for DMA flag | |
| bne @CRS_toWRAMnoDMA ; flag set --> don't use DMA | |
| ldx destLo | |
| stx REG_WMADDL ; set WRAM destination address | |
| lda destBank | |
| sta REG_WMADDH | |
| DMA_WaitHblank $08, CARDDATAREADbank, CARDDATAREADhigh, CARDDATAREADlow, $80, 512 | |
| bra @CRS_Done | |
| @CRS_toWRAMnoDMA: ; read 512 bytes into WRAM | |
| ldx #512 | |
| ldy #$0000 | |
| - lda CARDDATAREAD | |
| sta [destLo], y | |
| iny | |
| dex | |
| bne - | |
| ; PrintHexNum bankCounter | |
| ; PrintString "CardReadBytesDone\n" | |
| @CRS_Done: | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| jsr CardCheckError | |
| ; lda CARDSECTORCOUNTREAD | |
| ; sta errorCode | |
| ; bne CardReadSectorFailed ; LAST make sure sectors = 0 | |
| ;CardReadSectorPassed: | |
| ; jsr CardWaitNotBusy ; LAST check for busy before error | |
| ; jsr CardWaitReady | |
| ; jsr CardCheckError | |
| lda REG_RDNMI ; clear NMI flag, this is necessary to prevent occasional graphics glitches (see Fullsnes, 4210h/RDNMI) | |
| lda #$81 | |
| sta REG_NMITIMEN ; re-enable VBlank NMI | |
| cli | |
| rts | |
| ;CardReadSectorFailed: | |
| ; ClearLine 19 | |
| ; ClearLine 20 | |
| ; SetTextPos 19, 1 | |
| ; PrintString "Error CF sectors left = " | |
| ; PrintHexNum errorCode | |
| ; SetTextPos 20, 1 | |
| ; lda CARDERROR | |
| ; sta errorCode | |
| ; PrintString "Error $" | |
| ; PrintHexNum errorCode | |
| ; PrintString " - CF card error" | |
| ;CardReadSectorFailedForever: | |
| ; jmp Forever | |
| CardReadGameFill: | |
| Accu16 | |
| stz gameSize | |
| lda gameName.Cluster ; set source cluster | |
| sta sourceCluster | |
| lda gameName.Cluster+2 | |
| sta sourceCluster+2 | |
| Accu8 | |
| stz sectorCounter | |
| stz bankCounter | |
| jsr ClusterToLBA ; sourceCluster -> first sourceSector | |
| bit fixheader ; check for "assume copier header" flag | |
| bpl @ReadSector | |
| bra @NextSector ; sector=0 and header present --> skip that sector | |
| .ACCU 16 | |
| @Reiterate: | |
| lda gameName.Cluster ; set source cluster (again) | |
| sta sourceCluster | |
| lda gameName.Cluster+2 | |
| sta sourceCluster+2 | |
| Accu8 | |
| stz sectorCounter | |
| stz bankCounter | |
| jsr ClusterToLBA ; sourceCluster -> first sourceSector | |
| @ReadSector: | |
| lda #kSDRAM ; read sectors to SDRAM (self-reminder: this needs to be declared every iteration as DP_DataDestination is destroyed in a sub-sub routine of IncrementSectorNum [namely NextCluster]) | |
| sta DP_DataDestination | |
| jsr CardReadSector | |
| Accu16 | |
| inc gameSize ; keep track of game size, skipping header sector | |
| Accu8 | |
| @NextSector: | |
| IncrementSectorNum | |
| inc destHi | |
| inc destHi | |
| inc bankCounter | |
| bra @ReadSector | |
| __ lda gameSize+1 | |
| cmp #$04 ; read file again until $400 sectors = 512KB have been copied | |
| bcc + ; (probably in order to "improve" support for smaller ROMs ??) | |
| rts | |
| + Accu16 | |
| jmp @Reiterate | |
| .ACCU 8 | |
| CardReadFile: ; sourceCluster already set | |
| stz gameSize | |
| stz gameSize+1 | |
| jsr ClusterToLBA ; sourceCluster -> first sourceSector | |
| @CardReadFileLoop: | |
| ; PrintHexNum sourceSector+3 | |
| ; PrintHexNum sourceSector+2 | |
| ; PrintHexNum sourceSector+1 | |
| ; PrintHexNum sourceSector+0 | |
| ; PrintString "." | |
| Accu16 | |
| inc gameSize ; keep track of file size | |
| Accu8 | |
| lda #kSDRAM | |
| sta DP_DataDestination | |
| jsr CardReadSector | |
| IncrementSectorNum | |
| inc destHi ; dest = dest + 512 | |
| inc destHi | |
| inc bankCounter | |
| bra @CardReadFileLoop | |
| __ rts | |
| CardWriteFile: ; sourceCluster already set | |
| stz sectorCounter | |
| stz bankCounter | |
| jsr ClusterToLBA ; sourceCluster -> first sourceSector | |
| @CardWriteFileLoop: | |
| jsr CardWriteSector | |
| IncrementSectorNum | |
| inc sourceHi ; source = source + 512 | |
| inc sourceHi | |
| inc bankCounter | |
| bra @CardWriteFileLoop | |
| __ rts | |
| CardWriteSector: | |
| sei ; disable NMI & IRQ | |
| stz REG_NMITIMEN | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| jsr CardCheckError | |
| jsr CardLoadLBA | |
| jsr CardWaitNotBusy | |
| jsr CardWaitReady | |
| jsr CardCheckError | |
| lda #$30 | |
| sta CARDCOMMAND ; send card write sector command | |
| nop | |
| nop | |
| jsr CardCheckError | |
| jsr CardWaitDataReq | |
| lda DP_DataSource ; read data source | |
| Accu16 | |
| and #$00FF ; remove garbage in Accu B | |
| asl a ; use DP_DataSource as a jump table index | |
| tax | |
| Accu8 | |
| jmp (@PTR_kSource, x) | |
| @PTR_kSource: | |
| .DW $0000 ; dummy bytes (no transfers from FPGA) | |
| .DW @CWS_fromSDRAM | |
| .DW @CWS_fromSDRAM | |
| .DW @CWS_fromWRAM | |
| .DW @CWS_fromWRAM | |
| @CWS_fromSDRAM: ; write 512 bytes onto CF card | |
| ldx #512 | |
| - lda DMAREADDATA | |
| sta CARDDATAWRITE | |
| dex | |
| bne - | |
| bra @CWS_Done | |
| @CWS_fromWRAM: ; write 512 bytes onto CF card | |
| ldx #512 | |
| ldy #$0000 | |
| - lda [sourceLo], y | |
| sta CARDDATAWRITE | |
| iny | |
| dex | |
| bne - | |
| @CWS_Done: | |
| jsr CardCheckError | |
| lda REG_RDNMI ; clear NMI flag // ADDED for v3.00 | |
| lda #$81 | |
| sta REG_NMITIMEN ; re-enable VBlank NMI | |
| cli | |
| rts | |
| ; cluster->lba lba_addr(4) = clusterBeginLBA(4) + (cluster_number(2)-2 * sectorsPerCluster(1)) | |
| ClusterToLBA: | |
| Accu16 | |
| sec | |
| lda sourceCluster | |
| sbc #$0002 | |
| sta sourceSector | |
| lda sourceCluster+2 | |
| sbc #$0000 | |
| sta sourceSector+2 ; sourceSector = sourceCluster - 2 | |
| Accu8 | |
| lda sectorsPerCluster | |
| sta source256 | |
| lsr source256 | |
| beq + ; handle 1 sector per cluster | |
| @ClusterToLBALoop: | |
| Accu16 | |
| asl sourceSector | |
| rol sourceSector+2 ; sourceSector = sourceSector * sectorsPerCluster | |
| Accu8 | |
| lsr source256 | |
| bne @ClusterToLBALoop | |
| + Accu16 | |
| clc | |
| lda sourceSector | |
| adc clusterBeginLBA | |
| sta sourceSector | |
| lda sourceSector+2 | |
| adc clusterBeginLBA+2 | |
| sta sourceSector+2 ; sourceSector = sourceSector(4) + clusterBeginLBA(4) | |
| Accu8 | |
| rts | |
| ; ********************* Load dir from CF to buffer ********************* | |
| ; Loads the contents of a directory and stores relevant files in the | |
| ; selected buffer (WRAM/SDRAM). CLDConfigFlags are reset upon RTS. | |
| ; destLo/Hi = WRAM destination address for sector being read. | |
| ; sourceEntryLo/Hi = address of FAT entry within current sector buffer. | |
| ; destEntryLo/Hi/Bank = WRAM address where to put file entry (name + | |
| ; cluster). | |
| CardLoadDir: | |
| ldx #sectorBuffer1 | |
| stx destLo ; sourceSector1 = where to put sector, where to read entry | |
| stx sourceEntryLo | |
| stz destBank ; bank $00 = lower 8K of WRAM | |
| stz sourceEntryBank ; ditto | |
| lda #$7F ; start at WRAM offset $7F0000 | |
| sta destEntryBank | |
| stz destEntryHi | |
| stz destEntryLo | |
| lda #$00 ; start at SDRAM offset $000000 | |
| sta DMAWRITELO | |
| sta DMAWRITEHI | |
| sta DMAWRITEBANK | |
| Accu16 | |
| stz filesInDir | |
| stz temp | |
| stz selectedEntry | |
| Accu8 | |
| stz sectorCounter | |
| jsr ClusterToLBA ; sourceCluster -> first sourceSector | |
| Accu16 | |
| lda fat32Enabled | |
| and #$0001 | |
| bne @CLD_ReadSector ; FAT32 detected, go to read sector | |
| lda sourceCluster ; FAT16 check if trying to load root dir | |
| cmp rootDirCluster | |
| bne @CLD_ReadSector | |
| lda sourceCluster+2 | |
| cmp rootDirCluster+2 | |
| bne @CLD_ReadSector | |
| Accu8 | |
| sec | |
| lda clusterBeginLBA ; FAT16 sourceSector = root dir first sector => clusterLBABegin(4) - fat16RootSectors(1) | |
| sbc fat16RootSectors | |
| sta sourceSector | |
| lda clusterBeginLBA+1 | |
| sbc #$00 | |
| sta sourceSector+1 | |
| Accu16 | |
| lda clusterBeginLBA+2 | |
| sbc #$0000 | |
| sta sourceSector+2 | |
| @CLD_ReadSector: | |
| Accu8 | |
| lda #kWRAM | |
| sta DP_DataDestination | |
| jsr CardReadSector ; put into dest | |
| jsr CLD_ClearEntryName ; clear tempEntry, reset lfnFound | |
| CardLoadDirLoop: | |
| ; -------------------------- check for last entry | |
| ldy #$0000 | |
| lda [sourceEntryLo], y ; if name[0] = 0x00, no more entries | |
| bne @CLD_EntryNotLast | |
| jmp @CLD_LastEntryFound | |
| @CLD_EntryNotLast: | |
| ; -------------------------- check for unused entry | |
| ldy #$0000 | |
| lda [sourceEntryLo], y | |
| cmp #$E5 ; if name[0] = 0xE5, entry unused, skip | |
| bne @CLD_EntryNotUnused | |
| stz lfnFound | |
| jmp @CLD_NextEntry | |
| @CLD_EntryNotUnused: | |
| ; -------------------------- check for LFN entry | |
| ldy #$000B | |
| lda [sourceEntryLo], y ; if flag = %00001111, long file name entry found | |
| and #$0F | |
| cmp #$0F | |
| bne @CLD_EntryNotLFN | |
| ldy #$0000 ; check first byte of LFN entry = ordinal field | |
| lda [sourceEntryLo], y | |
| and #%10111111 ; mask off "last entry" bit | |
| cmp #$0A ; if index = 1...9, load name | |
| bcc @CLD_EntryPrepareLoadLFN | |
| jsr CLD_ClearEntryName ; if index >= 10, skip entry (reminder: index = 0 doesn't seem to exist ??) | |
| jmp @CLD_NextEntry | |
| @CLD_EntryPrepareLoadLFN: | |
| sta REG_M7A ; PPU multiplication | |
| stz REG_M7A | |
| lda #$0D ; LFNs consist of 13 unicode characters | |
| sta REG_M7B | |
| Accu16 | |
| lda REG_MPYL ; read result | |
| sec | |
| sbc #$000D ; subtract 13 to make up for missing index 0 | |
| tax ; transfer to X register | |
| Accu8 | |
| jsr CLD_LoadLFN ; load LFN entry, store characters to tempEntry | |
| jmp @CLD_NextEntry | |
| @CLD_EntryNotLFN: | |
| ; -------------------------- check for volume ID entry | |
| ldy #$000B | |
| lda [sourceEntryLo], y ; if flag = volume id, skip | |
| and #$08 | |
| cmp #$08 | |
| bne @CLD_EntryNotVolumeID | |
| jsr CLD_ClearEntryName | |
| jmp @CLD_NextEntry | |
| @CLD_EntryNotVolumeID: | |
| ; -------------------------- short file name found, perform additional checks | |
| ; -------------------------- check for hidden entry | |
| ldy #$000B | |
| lda [sourceEntryLo], y | |
| and #$02 ; if flag = 0x02, hidden, mark as such | |
| beq @CLD_EntryHiddenCheckDone | |
| tsb tempEntry.Flags ; save "hidden" flag | |
| @CLD_EntryHiddenCheckDone: | |
| ; -------------------------- check for directory entry | |
| ldy #$000B | |
| lda [sourceEntryLo], y ; if flag = directory, load entry | |
| and #$10 | |
| beq @CLD_EntryNotDirectory | |
| lda #$01 | |
| tsb tempEntry.Flags ; save "dir" flag | |
| Accu16 | |
| bra @CLD_ProcessMatchingEntry | |
| @CLD_EntryNotDirectory: | |
| ; -------------------------- check for entry extension | |
| ldx extNum ; check if entry matches any extension wanted, | |
| dex ; backwards from the Nth (= $NNNN-1) to the 1st (= $0000) extension | |
| @CLD_CheckExtLoop: | |
| ldy #$0008 | |
| lda [sourceEntryLo], y | |
| cmp extMatch1, x | |
| bne + | |
| iny | |
| lda [sourceEntryLo], y | |
| cmp extMatch2, x | |
| bne + | |
| iny | |
| lda [sourceEntryLo], y | |
| cmp extMatch3, x | |
| beq @CLD_EntryExtensionMatch ; extension matches | |
| + dex ; otherwise, try next extension indicated | |
| bpl @CLD_CheckExtLoop | |
| jsr CLD_ClearEntryName ; extension doesn't match, skip entry | |
| jmp @CLD_NextEntry | |
| @CLD_EntryExtensionMatch: | |
| ; -------------------------- check file size | |
| Accu16 | |
| ldy #$001E | |
| lda [sourceEntryLo], y ; upper 16 bit of file size | |
| bne @CLD_FileSizeNotZero | |
| ldy #$001C | |
| lda [sourceEntryLo], y ; lower 16 bit of file size | |
| bne @CLD_FileSizeNotZero | |
| Accu8 | |
| jsr CLD_ClearEntryName ; file size = 0, skip entry | |
| jmp @CLD_NextEntry | |
| .ACCU 16 | |
| @CLD_FileSizeNotZero: | |
| ldy #$001C ; check lower 16 bit of file size for copier header | |
| lda [sourceEntryLo], y | |
| and #$03FF ; from FullSNES: "IF (filesize AND 3FFh)=200h THEN HeaderPresent=True" | |
| cmp #$0200 | |
| bne @CLD_ProcessMatchingEntry | |
| lda #$0080 ; copier header (apparently) present, set "copier header present" flag | |
| tsb tempEntry.Flags ; upper 8 bits (1st byte of tempEntry.Cluster) not affected | |
| ; -------------------------- load long/short dir or entry with matching ext. and size not zero | |
| @CLD_ProcessMatchingEntry: | |
| inc filesInDir ; increment file counter | |
| Accu8 | |
| lda lfnFound | |
| cmp #$01 | |
| beq @CLD_PrepareSaveEntry | |
| ldy #$0000 ; if lfnFound = 0, copy short file name only | |
| - lda [sourceEntryLo], y | |
| sta tempEntry, y | |
| iny | |
| cpy #$0008 | |
| bne - | |
| lda tempEntry.Flags | |
| and #%00000001 ; check for "dir" flag | |
| bne @CLD_PrepareSaveEntry | |
| lda #'.' ; if not directory, copy short file name extension | |
| sta tempEntry+$8 | |
| ldy #$0008 | |
| lda [sourceEntryLo], y | |
| sta tempEntry+$9 | |
| iny | |
| lda [sourceEntryLo], y | |
| sta tempEntry+$A | |
| iny | |
| lda [sourceEntryLo], y | |
| sta tempEntry+$B | |
| @CLD_PrepareSaveEntry: | |
| Accu16 | |
| ldy #$001A | |
| lda [sourceEntryLo], y ; copy cluster (32 bit) to last 4 bytes of entry | |
| sta tempEntry.Cluster | |
| ldy #$0014 | |
| lda [sourceEntryLo], y | |
| sta tempEntry.Cluster+2 | |
| Accu8 | |
| ldy #$0000 ; reset Y for upcoming loop | |
| lda CLDConfigFlags ; check for selected buffer | |
| and #%00000001 | |
| bne @CLD_UseSDRAMbuffer | |
| jsr CLD_SaveEntryToWRAM | |
| Accu16 | |
| lda filesInDir ; check if file counter has reached 512 | |
| cmp #$0200 | |
| bcc @CLD_WRAMcontinue | |
| Accu8 ; if so, A = 8 bit | |
| jmp @CLD_LastEntryFound ; ... and don't process any more entries | |
| @CLD_WRAMcontinue: | |
| Accu8 ; otherwise, A = 8 bit, and continue | |
| jsr CLD_ClearEntryName | |
| bra @CLD_NextEntry | |
| @CLD_UseSDRAMbuffer: | |
| lda CLDConfigFlags ; check if hidden files/folders are to be skipped | |
| and #%00000010 | |
| beq @CLD_SaveEntryToSDRAM | |
| lda tempEntry.Flags | |
| and #%00000010 ; yes, check for "hidden" flag | |
| beq @CLD_SaveEntryToSDRAM | |
| Accu16 | |
| dec filesInDir ; hidden dir/file found, decrement file counter ... | |
| bra @CLD_SDRAMcontinue ; ... and jump out | |
| .ACCU 8 | |
| @CLD_SaveEntryToSDRAM: | |
| lda tempEntry, y ; save entry to SDRAM | |
| sta DMAREADDATA | |
| iny | |
| cpy #$0080 | |
| bne @CLD_SaveEntryToSDRAM | |
| Accu16 | |
| lda filesInDir | |
| cmp #$FFFF ; check if file counter has reached 65535 | |
| bcc @CLD_SDRAMcontinue | |
| Accu8 ; if so, A = 8 bit | |
| jmp @CLD_LastEntryFound ; ... and don't process any more entries | |
| @CLD_SDRAMcontinue: | |
| Accu8 ; otherwise, A = 8 bit, and continue | |
| jsr CLD_ClearEntryName | |
| ; -------------------------- finally, increment to next entry, and loop | |
| @CLD_NextEntry: | |
| Accu16 | |
| clc ; increment entry source address | |
| lda sourceEntryLo ; sourceEntry += 32 in 0200-0400 | |
| adc #$0020 | |
| sta sourceEntryLo | |
| Accu8 | |
| lda sourceEntryHi ; if source overflows, get next sector | |
| cmp #>sectorBuffer1+$02 ; LAST CHANGE | |
| beq @CLD_NextSector | |
| jmp CardLoadDirLoop | |
| ; -------------------------- if necessary, increment source sector | |
| @CLD_NextSector: | |
| Accu16 | |
| clc | |
| lda sourceSector | |
| adc #$0001 | |
| sta sourceSector ; go to next sector num | |
| lda sourceSector+2 | |
| adc #$0000 | |
| sta sourceSector+2 | |
| lda fat32Enabled ; if FAT32, increment sector | |
| and #$0001 | |
| bne @CLD_SectorIncrement | |
| lda sourceCluster ; FAT16 check if trying to load root dir | |
| cmp rootDirCluster | |
| bne @CLD_SectorIncrement | |
| lda sourceCluster+2 | |
| cmp rootDirCluster+2 | |
| bne @CLD_SectorIncrement | |
| Accu8 | |
| inc sectorCounter ; FAT16 root dir all sequential sectors | |
| lda sectorCounter | |
| cmp fat16RootSectors ; if sectorCounter = fat16RootSectors, jump out | |
| beq @CLD_LastEntryFound | |
| bra @CLD_LoadNextSector ; FAT16 skip cluster lookup when max root sectors not reached | |
| @CLD_SectorIncrement: | |
| Accu8 | |
| inc sectorCounter ; one more sector | |
| lda sectorCounter | |
| cmp sectorsPerCluster ; make sure cluster isn't overflowing | |
| bne @CLD_LoadNextSector | |
| jsr NextCluster ; move to next cluster | |
| Accu16 | |
| ; check for last sector | |
| ; FAT32 last cluster = 0x0FFFFFFF | |
| ; FAT16 last cluster = 0x0000FFFF | |
| lda fat32Enabled ; check for FAT32 | |
| and #$0001 | |
| bne @CLD_LastClusterMaskFAT32 | |
| stz temp+2 ; if FAT16, high word = $0000 | |
| bra @CLD_LastClusterMaskDone | |
| @CLD_LastClusterMaskFAT32: | |
| lda #$0FFF ; if FAT32, high word = $0FFF | |
| sta temp+2 | |
| @CLD_LastClusterMaskDone: ; if cluster = last cluster, jump to last entry found | |
| lda sourceCluster | |
| cmp #$FFFF ; low word = $FFFF (FAT16/32) | |
| bne @CLD_NextSectorNum | |
| lda sourceCluster+2 | |
| cmp temp+2 | |
| bne @CLD_NextSectorNum | |
| Accu8 | |
| bra @CLD_LastEntryFound ; last cluster, jump out | |
| @CLD_NextSectorNum: | |
| Accu8 | |
| jsr ClusterToLBA ; sourceCluster -> first sourceSector | |
| stz sectorCounter ; reset sector counter | |
| @CLD_LoadNextSector: | |
| ldx #sectorBuffer1 | |
| stx destLo ; reset sector dest | |
| stx sourceEntryLo ; reset entry source | |
| stz destBank | |
| stz sourceEntryBank | |
| lda #kWRAM | |
| sta DP_DataDestination | |
| jsr CardReadSector | |
| jmp CardLoadDirLoop | |
| @CLD_LastEntryFound: | |
| stz CLDConfigFlags ; reset CardLoadDir config flags | |
| rts | |
| ; -------------------------- CardLoadDir subroutine: load LFN entry | |
| CLD_LoadLFN: | |
| ldy #$0001 | |
| @CLD_LoadLFNLoop1: | |
| lda [sourceEntryLo], y ; copy unicode chars 1-5 from offsets $01, $03, $05, $07, $09 | |
| cmp #$FF | |
| beq + | |
| sta tempEntry, x | |
| + inx | |
| iny | |
| iny | |
| cpy #$000B | |
| bne @CLD_LoadLFNLoop1 | |
| ldy #$000E | |
| @CLD_LoadLFNLoop2: | |
| lda [sourceEntryLo], y ; copy unicode chars 6-11 from offsets $0E, $10, $12, $14, $16, $18 | |
| cmp #$FF | |
| beq + | |
| sta tempEntry, x | |
| + inx | |
| iny | |
| iny | |
| cpy #$001A | |
| bne @CLD_LoadLFNLoop2 | |
| ldy #$001C | |
| @CLD_LoadLFNLoop3: | |
| lda [sourceEntryLo], y ; copy unicode chars 12-13 from offsets $1C, $1E | |
| cmp #$FF | |
| beq + | |
| sta tempEntry, x | |
| + inx | |
| iny | |
| iny | |
| cpy #$0020 | |
| bne @CLD_LoadLFNLoop3 | |
| lda #$01 | |
| sta lfnFound | |
| rts | |
| ; -------------------------- CardLoadDir subroutine: save entry to WRAM buffer | |
| CLD_SaveEntryToWRAM: | |
| Accu16 | |
| - lda tempEntry, y ; Y was reset before | |
| sta [destEntryLo], y | |
| iny | |
| iny | |
| cpy #$0080 | |
| bne - | |
| clc | |
| lda destEntryLo ; destEntryHiLo += 128 | |
| adc #$0080 | |
| sta destEntryLo | |
| Accu8 | |
| rts | |
| ; -------------------------- CardLoadDir subroutine: reset tempEntry & LFN variables | |
| CLD_ClearEntryName: | |
| stz lfnFound | |
| Accu16 | |
| lda #$0000 | |
| ldy #$0000 | |
| - sta tempEntry, y | |
| iny | |
| iny | |
| cpy #$0080 | |
| bne - | |
| Accu8 | |
| rts | |
| ; **************************** Next cluster **************************** | |
| ; Load FAT entry for sourceCluster, store next cluster number into | |
| ; sourceSector. | |
| NextCluster: | |
| Accu16 | |
| asl sourceCluster ; FAT16: offset = clusternum << 1 | |
| rol sourceCluster+2 ; mask = 00 00 ff ff | |
| lda fat32Enabled | |
| and #$0001 | |
| beq @NextClusterSectorNum | |
| asl sourceCluster ; FAT32: offset = clutsernum << 2 || cluster 2 << 2 = 8 | |
| rol sourceCluster+2 ; mask = 0f ff ff ff | |
| @NextClusterSectorNum: ; FAT sector num = fatBeginLBA + (offset / 512) || cluster = $2f8 | |
| lda sourceCluster+1 ; first, divide by 256 by shifting sourceCluster 8 bits right, | |
| sta sourceSector+0 ; and store to sourceSector | |
| Accu8 | |
| lda sourceCluster+3 | |
| sta sourceSector+2 | |
| stz sourceSector+3 ; division by 256 done || sector = 02 | |
| Accu16 | |
| lsr sourceSector+2 ; next, shift sourceSector 1 more bit right (div. by 512) || sector = 01 | |
| ror sourceSector+0 | |
| clc | |
| lda sourceSector ; add fatBeginLBA || sector = 60 = $c000 | |
| adc fatBeginLBA | |
| sta sourceSector | |
| lda sourceSector+2 | |
| adc fatBeginLBA+2 | |
| sta sourceSector+2 | |
| Accu8 | |
| ldx #sectorBuffer1 ; load FAT sector | |
| stx destLo | |
| stz destBank | |
| lda #kWRAM | |
| sta DP_DataDestination | |
| jsr CardReadSector | |
| ; offset = offset % 512 -- offset of FAT entry within loaded sector 0-511 | |
| lda sourceCluster+1 | |
| and #%00000001 | |
| sta sourceCluster+1 ; cluster+1=0 | |
| lda #<sectorBuffer1 ; next cluster = [sector], offset | |
| sta sourceLo | |
| stz sourceBank | |
| ; sourceHi = sectorBuffer1(high) or sectorBuffer1(high)+1 for which 256 byte block to look in | |
| lda #>sectorBuffer1 | |
| adc sourceCluster+1 | |
| sta sourceHi | |
| lda sourceCluster | |
| sta temp+2 | |
| stz temp+3 | |
| ldy temp+2 | |
| ldx #$0000 | |
| @NextClusterLoop: | |
| lda [sourceLo], y | |
| sta sourceCluster, x | |
| iny | |
| inx | |
| cpx #$0004 | |
| bne @NextClusterLoop | |
| lda sourceCluster+3 ; FAT32 mask off top 4 bits | |
| and #$0F | |
| sta sourceCluster+3 | |
| lda fat32Enabled | |
| cmp #$01 | |
| beq @NextClusterDone ; no more mask for FAT32 | |
| stz sourceCluster+3 ; FAT16 mask | |
| stz sourceCluster+2 | |
| @NextClusterDone: | |
| rts | |
| ; ************************** Get next sector *************************** | |
| LoadNextSectorNum: ; get next sector, use sectorCounter to check if next cluster needed | |
| Accu16 | |
| clc | |
| lda sourceSector | |
| adc #$0001 | |
| sta sourceSector ; go to next sector num | |
| lda sourceSector+2 | |
| adc #$0000 | |
| sta sourceSector+2 | |
| Accu8 | |
| inc sectorCounter ; one more sector | |
| lda sectorCounter | |
| cmp sectorsPerCluster ; are we there yet? | |
| bne + | |
| stz sectorCounter ; yes, next cluster needed | |
| jsr NextCluster ; get cluster num into sourceCluster from FAT table | |
| .IFDEF DEBUG | |
| PrintString "cluster=" | |
| PrintString sourceCluster+3 | |
| PrintString sourceCluster+2 | |
| PrintString sourceCluster+1 | |
| PrintString sourceCluster+0 | |
| PrintString "\n" | |
| .ENDIF | |
| jsr ClusterToLBA ; get sector num into sourceSector | |
| .IFDEF DEBUG | |
| PrintString "sector=" | |
| PrintHexNum sourceSector+3 | |
| PrintHexNum sourceSector+2 | |
| PrintHexNum sourceSector+1 | |
| PrintHexNum sourceSector+0 | |
| PrintString "\n" | |
| DelayFor 172 | |
| .ENDIF | |
| + rts | |
| .ENDASM | |
| ; ************************* WIP file creation ************************** | |
| GotoSRMTest: | |
| jsr HideButtonSprites | |
| jsr HideLogoSprites | |
| jsr PrintClearScreen | |
| SetTextPos 0, 0 | |
| PrintString "sectorsPerFat $" | |
| PrintHexNum sectorsPerFat+3 | |
| PrintHexNum sectorsPerFat+2 | |
| PrintHexNum sectorsPerFat+1 | |
| PrintHexNum sectorsPerFat+0 | |
| PrintString "\n" | |
| PrintString "fatBeginLBA $" | |
| PrintHexNum fatBeginLBA+3 | |
| PrintHexNum fatBeginLBA+2 | |
| PrintHexNum fatBeginLBA+1 | |
| PrintHexNum fatBeginLBA+0 | |
| PrintString "\n\nSearching for free sector within FAT ...\nSector no. $" | |
| Accu16 | |
| lda fatBeginLBA ; first FAT sector --> sourceSector for sector reading | |
| sta sourceSector | |
| lda fatBeginLBA+2 | |
| sta sourceSector+2 | |
| Accu8 | |
| FindFreeSector: | |
| lda #$E0 ; mask off upper 3 bits (set in CardLoadLBA, reason unknown ??) | |
| trb sourceSector+3 | |
| SetTextPos 4, 6 | |
| PrintHexNum sourceSector+3 | |
| PrintHexNum sourceSector+2 | |
| PrintHexNum sourceSector+1 | |
| PrintHexNum sourceSector+0 | |
| lda #kWRAM ; set WRAM as destination | |
| sta DP_DataDestination | |
| ldx #sectorBuffer1 | |
| stx destLo | |
| stz destBank | |
| jsr CardReadSector ; read FAT sector to WRAM | |
| Accu16 | |
| ldx #$0000 | |
| - lda sectorBuffer1, x | |
| bne @SectorNotEmpty | |
| inx | |
| inx | |
| cpx #512 | |
| bne - | |
| Accu8 | |
| PrintString "\nEmpty sector found!" | |
| jmp Forever | |
| ; jmp FindFreeSector | |
| @SectorNotEmpty: | |
| Accu16 | |
| inc sourceSector | |
| lda sourceSector | |
| cmp #$21CB ; fatBeginLBA + sectorsPerFat on 4GB Sandisk card | |
| beq + | |
| Accu8 | |
| jmp FindFreeSector | |
| + Accu8 | |
| PrintSpriteText 19, 2, "Error!", 4 | |
| jmp Forever | |
| .ASM | |
| ; ******************************** EOF ********************************* |