

;=== Include MemoryMap, VectorTable, HeaderInfo ===
.INCLUDE "loaderinc.inc"


;=== Global Variables ===



.INCLUDE "variables.asm"

;=== Include Library Routines & Macros ===
.INCLUDE "InitSNES.asm"
.INCLUDE "LoadGraphics.asm"
.INCLUDE "2Input.asm"
.INCLUDE "QuickSetup.asm"
.INCLUDE "Sprites.asm"



;==============================================================================
; main
;==============================================================================

.BANK 0 SLOT 0
.ORG 0
.SECTION "MainCode"

LoadRomVersion:
  SetCursorPos 11, 0
  PrintString "        Boot ROM  v1.03b1       "   
  rts


Main:
  InitializeSNES  
  SEP #$20     ; 8 bit Accumulator, 16 bit X/Y
  REP #$10

  ldy #$0000
JumpTableLoop
  lda JumpTableStart, y
  sta jumpTable, y
  iny
  cpy #$0080           ;;128 bytes = 64 functions
  bne JumpTableLoop


  jmp JumpTableEnd

JumpTableStart:
  ;add ram jumptable
.DW CardReadSector             
.DW CardWriteSector             
.DW ForeverLoader               
.DW CardReset                  
.DW CardWaitNotBusy            
.DW CardWaitReady              
.DW CardWaitDataReq            
.DW CardCheckError             
.DW CardLoadLBA                
.DW CardReadBytesNoDMA  
.DW CardReadBytesToWRAM 
.DW CardReadBytesToFPGA 
.DW CardReadBytesToSDRAM
.DW CardReadBytesToSDRAMNoDMA
.DW CardReadFile
.DW CardWriteFile
.DW CardWriteBytesFromWRAM
.DW CardWriteBytesFromSDRAM
.DW CardLoadModule             
.DW CardLoadDirClearEntryName  
.DW CardLoadDir                
.DW ClusterToLBA               
.DW NextCluster        
.DW DirPrintDir        
.DW DirPrintEntry              
.DW DirGetEntry                
.DW DirFindEntry 
.DW NextDir           
.DW PrintFJump
.DW PrintInt8_noload
.DW PrintHex8_noload
.DW PrintClearLine
.DW PrintClearScreen
.DW DoScrolling
.DW ScrollUp
.DW ScrollDown
.DW LoadNextSectorNum
.DW CardLoadFPGA
.DW ClearFindEntry             
.DW GameGeniePrint             
.DW GameGenieClear             
.DW GameGenieDecode            
.DW GameGenieGetOffset         
.DW GameGenieNextChar          
.DW GameGeniePrevChar          
.DW GameGenieCharStore  
.DW GameGenieWriteCode       
.DW LoadLogo
.DW LoadRomVersion
.DW MemCheck
.DW CopyROMInfo
.DW CopyBanks
.DW PrintBanks
.DW LogScreen
.DW SWCHeaderCheck
.DW GD3HeaderCheck
JumpTableEnd:



  JSR SpriteInit  ;setup the sprite buffer


  SEP #$20     ; 8 bit Accumulator, 16 bit X/Y
  REP #$10

  jsr QuickSetup  ; set VRAM, the video mode, background and character pointers, 
        ; and turn on the screen

  SEP #$20     ; 8 bit Accumulator, 16 bit X/Y
  REP #$10


  jsr JoyInit    ;setup joypads and enable NMI

  SEP #$20     ; 8 bit Accumulator, 16 bit X/Y
  REP #$10

  jump jLoadLogo
  jump jLoadRomVersion

        
;  LDA #%10001111  
;  STA $2100  ;force VBlank, also setting brightness to 0


  lda #$00
  sta gameCluster
  sta gameCluster+1  
  sta gameCluster+2
  sta gameCluster+3  
  sta saveCluster
  sta saveCluster+1  
  sta saveCluster+2  
  sta saveCluster+3  
  

  
  
  jump jCardReset
  wai
;For:
;  jmp For

;  ClearLine 5
;  ClearLine 6
;  ClearLine 7;
;  SetCursorPos 5, 1

;  lda CONFIGREADSTATUS   ;open bus = $20  want $Ax
;  sta errorCode;
;  PrintString "FPGA status="
;  PrintHexNum errorCode;
;  PrintString "\n"
 ; lda errorCode
 ; and #$F0
 ; cmp #$A0
 ; bne fpgaNOTconfigured

;fpgaISconfigured:
;  PrintString "fpgaISconfigured\n"
 ; jmp StateProgramFPGADone

;fpgaNOTconfigured:
;StateProgramFPGA:
;  PrintString "StateProgramFPGA\n"
 ; lda #$01
  ;;sta FPGAPROGRAMWRITE
  ;lda #$00
  ;sta FPGAPROGRAMWRITE   ;;SEND PROGRAM SIGNAL TO FPGA
  ;lda #$01
  ;sta FPGAPROGRAMWRITE

;;FPGA = $60D1 bytes
  ;ldy #$6100
  ;ldx #$0000
;StateProgramFPGALoop:
 ; lda.l TopLevel, x
 ; sta FPGADATAWRITE 
 ; inx
 ; dey
 ; bne StateProgramFPGALoop  
;  PrintString "StateProgramFPGADone\n"
;StateProgramFPGADone:

  
  
  
StateCardNotInserted:   ; wait until card inserted, put no card message on screen
  lda.l CARDSTATUS
  sta errorCode
  and #%11110000   ;;;open bus = A0
  cmp #$A0
  beq StateCardNotInsertedLoop
  jmp StateCardNotInsertedDone

StateCardNotInsertedLoop
  wai
  wai
  wai
  SetCursorPos 12, 0
  PrintString " Error $"
  PrintHexNum errorCode
  PrintString " - CF card not found  "

ShowConsoleVersion:  
  SetCursorPos 13,0
  lda $4210   ;;CPU version
  and #$0F
  sta temp
  lda $213E   ;;PPU1 version
  and #$0F
  sta temp+1
  lda $213F   ;;PPU2 version
  and #$0F
  sta temp+2

  PrintString "    CPU="
  PrintHexNum temp
  PrintString "  PPU1="
  PrintHexNum temp+1
  PrintString " PPU2="
  PrintHexNum temp+2
NoCard:
  jmp NoCard
StateCardNotInsertedDone:



StateCardBusy:          ; wait until card not busy, put card busy message on screen
  lda CARDSTATUS
  sta errorCode
  and #%10000000
  cmp #%10000000           ;;;busy = 80
  bne StateCardBusyDone
  wai
  SetCursorPos 12, 0
  PrintString "    Error $"
  PrintHexNum errorCode
  PrintString " - CF card busy    "
  jmp StateCardBusy
StateCardBusyDone:


StateCardReady:         ; wait until card ready, put card not ready message on screen
  lda CARDSTATUS
  sta errorCode
  and #%01010000
  cmp #%01010000           ;;ready = 50
  beq StateCardReadyDone
  wai
  SetCursorPos 12, 0
  PrintString " Error $"
  PrintHexNum errorCode
  PrintString " - CF card not ready  "
  jmp StateCardReady
StateCardReadyDone:

  SetCursorPos 12, 0
  PrintString "         CF Card Booted         "

  lda #$01        ;;not using dma
  sta dontUseDMA



;;;;
;; set some features
;  jump jCardWaitNotBusy
;  jump jCardWaitReady
;  jump jCardCheckError

;  SetCursorPos 12, 0
;  PrintString " card ready     "

;;select disk 0
;  lda #%00000000
;  sta CARDLBA3             ;select card 0

;  SetCursorPos 12, 0
;  PrintString " card 0 selected"

;; send feature = 01 - 8 bit transfers
;  lda #$01
;  sta CARDERROR
;  lda #$EF
;  sta CARDCOMMAND
  
;  SetCursorPos 12, 0
;  PrintString " feature written"

;  jump jCardCheckError

 
 
;  lda #$10
;  sta temp+5      ;;try copying 16 times
;StateCardBooted:
;  lda temp+5
;  sta temp+6
;StateCardBootedWait:
;  dec temp+6
;  bne StateCardBootedWait  ;;try to shift by some clocks
;  stz sourceSector
;  stz sourceSector+1
;  stz sourceSector+2
;  stz sourceSector+3
;  lda #<sectorBuffer1
;  sta destLo
;  lda #>sectorBuffer1
;  sta destHi
;  stz destBank
;  lda #kDestWRAM
;  sta destType
;  stz sectorBuffer1+$1FE
;  stz sectorBuffer1+$1FF
;  jump jCardReadSector      ;read sector 0 to internal ram
;  lda sectorBuffer1+$1FE
;  cmp #$55
;  bne DMAError              ;last word check  should be $55AA
;  lda sectorBuffer1+$1FF
;  cmp #$AA
;  bne DMAError              ;last word check  should be $55AA
;  dec temp+5
;  bne StateCardBooted
;  jmp CardFormatCheck
;DMAError:
;  lda #$01
;  sta dontUseDMA
;  ClearLine 3
;  SetCursorPos 3, 1
;  PrintString "DMA OFF\n"


  stz sourceSector
  stz sourceSector+1
  stz sourceSector+2
  stz sourceSector+3
  lda #<sectorBuffer1
  sta destLo
  lda #>sectorBuffer1
  sta destHi
  lda #$00
  sta destBank
  lda #kDestWRAM          ;;try with DMA on
  sta destType


  jump jCardReadSector      ;read sector 0 to internal ram

  lda sectorBuffer1+$1FE    ;last word check  should be $55AA
  cmp #$55
  beq CardFormatCheck
;  jmp CardFormatError       
CardFormatCheck:
  lda sectorBuffer1+$1FF
  cmp #$AA
  bne CardFormatErrorJump
  
  
  
  
  
  
  
  ldy #$0000   ;;y = partition number  0-3
  ldx #$0000   ;;x = partition index   0, 16, 32, 48
CardFormatCheckLoop:
  lda #$01
  sta fat32Enabled
  lda sectorBuffer1+$1C2, x                 ;format  fat32 = 0x0B   FAT32
  cmp #$0B
  beq CardGoodFormat
  lda sectorBuffer1+$1C2, x                 ;format  fat32 = 0x0C   FAT32 LBA
  cmp #$0C
  beq CardGoodFormat
  
  
  lda #$00
  sta fat32Enabled
  lda sectorBuffer1+$1C2, x                ;format  fat16 = 0x06  larger than 32MB
  cmp #$06
  beq CardGoodFormat
  lda sectorBuffer1+$1C2, x                ;format  fat16 = 0x04  smaller than 32MB
  cmp #$04
  beq CardGoodFormat
  lda sectorBuffer1+$1C2, x                ;format  fat16 = 0x0E  with LBA
  cmp #$0E
  beq CardGoodFormat
  
  inx
  inx
  inx
  inx

  inx
  inx
  inx
  inx

  inx
  inx
  inx
  inx

  inx
  inx
  inx
  inx
  
  iny
  cpy #$0004
  bne CardFormatCheckLoop
  
CardFormatErrorJump:
  jmp CardFormatError
  


CardGoodFormat:            ;fat32/fat16 partition found  
  stx partitionIndex

  SetCursorPos 12, 0
  PrintString "         FAT32/16 found         "

  ldx partitionIndex
  ldy #$0000
CardCopyPartitionLBABegin:        ;copy partitionLBABegin from offset 455
  lda sectorBuffer1+$1C6, x
  sta sourceSector, y
  sta partitionLBABegin, y
  inx
  iny
  cpy #$0004
  bne CardCopyPartitionLBABegin





  
  lda #<sectorBuffer1
  sta destLo
  lda #>sectorBuffer1
  sta destHi
  stz destBank
  lda #kDestWRAM
  sta destType
  jump jCardReadSector              ;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
  
  lda #$00
  sta 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:
  clc                       ;fatBeginLBA(4) = partitionLBABegin(4) + reservedSectors(2)
  lda reservedSectors
  adc partitionLBABegin
  sta fatBeginLBA
  lda reservedSectors+1
  adc partitionLBABegin+1
  sta fatBeginLBA+1
  lda partitionLBABegin+2
  adc #$00
  sta fatBeginLBA+2
  lda partitionLBABegin+3
  adc #$00
  sta fatBeginLBA+3

CardCopyClusterBeginLBA:
  lda sectorsPerFat
  sta clusterBeginLBA
  lda sectorsPerFat+1
  sta clusterBeginLBA+1
  lda sectorsPerFat+2
  sta clusterBeginLBA+2
  lda sectorsPerFat+3
  sta clusterBeginLBA+3
  
  clc
  asl clusterBeginLBA          ;clusterBeginLBA(4) = fatBeginLBA(4) + (2 * sectorPerFat(4))
  rol clusterBeginLBA+1       
  rol clusterBeginLBA+2 
  rol clusterBeginLBA+3 


  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
  lda clusterBeginLBA+2
  adc #$00
  sta clusterBeginLBA+2
  lda clusterBeginLBA+3
  adc #$00
  sta clusterBeginLBA+3
  
  
  clc                         
  lda clusterBeginLBA
  adc fatBeginLBA
  sta clusterBeginLBA
  lda clusterBeginLBA+1
  adc fatBeginLBA+1
  sta clusterBeginLBA+1  
  lda clusterBeginLBA+2
  adc fatBeginLBA+2
  sta clusterBeginLBA+2  
  lda clusterBeginLBA+3
  adc fatBeginLBA+3
  sta clusterBeginLBA+3    


  lda rootDirCluster
  sta sourceCluster
  lda rootDirCluster+1
  sta sourceCluster+1
  lda rootDirCluster+2
  sta sourceCluster+2
  lda rootDirCluster+3
  sta sourceCluster+3
    
 ; 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

  jump jCardLoadDir        ; root dir

  lda #'P'
  sta findEntry
  lda #'O'
  sta findEntry+1
  lda #'W'
  sta findEntry+2
  lda #'E'
  sta findEntry+3
  lda #'R'
  sta findEntry+4
  lda #'P'
  sta findEntry+5
  lda #'A'
  sta findEntry+6
  lda #'K'
  sta findEntry+7
  
  jump jDirFindEntry         ;"POWERPAK" dir into tempEntry

  lda tempEntry+$1C
  sta baseDirCluster
  lda tempEntry+$1D
  sta baseDirCluster+1
  lda tempEntry+$1E
  sta baseDirCluster+2
  lda tempEntry+$1F
  sta baseDirCluster+3
  ;;;; powerpak dir found   write base cluster

.ifdef DEBUG
  PrintString "baseDirCluster $"
  PrintHexNum baseDirCluster+3
  PrintHexNum baseDirCluster+2
  PrintHexNum baseDirCluster+1
  PrintHexNum baseDirCluster+0
  PrintString "\n"
.endif







  ;;load CONFIG.TXT file
  lda #'T'
  sta exMatch1
  sta exMatch1+1
  sta exMatch1+2
  sta exMatch1+3
  lda #'X'
  sta exMatch2
  sta exMatch2+1
  sta exMatch2+2
  sta exMatch2+3
  lda #'T'
  sta exMatch3
  sta exMatch3+1
  sta exMatch3+2
  sta exMatch3+3

  lda baseDirCluster   ;;powerpak dir start
  sta sourceCluster
  lda baseDirCluster+1
  sta sourceCluster+1
  lda baseDirCluster+2
  sta sourceCluster+2
  lda baseDirCluster+3
  sta sourceCluster+3


  jump jClearFindEntry
  lda #'C'
  sta findEntry+0
  lda #'O'
  sta findEntry+1
  lda #'N'
  sta findEntry+2
  lda #'F'
  sta findEntry+3
  lda #'I'
  sta findEntry+4
  lda #'G'
  sta findEntry+5

  jump jCardLoadDir    ; powerpak dir
  
  jump jDirFindEntry        ;;get first cluster
  lda tempEntry+$1C
  sta sourceCluster
  lda tempEntry+$1D
  sta sourceCluster+1
  lda tempEntry+$1E
  sta sourceCluster+2
  lda tempEntry+$1F
  sta sourceCluster+3

  lda #<sectorBuffer1
  sta destLo
  lda #>sectorBuffer1
  sta destHi                   ;;put into sector ram
  stz destBank
  stz sectorCounter
  stz bankCounter
  jump jClusterToLBA            ;sourceCluster -> first sourceSector
  lda #kDestWRAM
  sta destType
  jump jCardReadSector          ;sector -> wram

  ldy #$0000
LoadDMAConfigLoop:              ;;look for DMA=0  DMA=1
  lda sectorBuffer1, y
  cmp #'D'
  beq LoadDMAConfigLoopFound
LoadDMAConfigLoopNext:
  iny 
  cpy #$FF
  beq LoadDMAConfigDone
  jmp LoadDMAConfigLoop


LoadDMAConfigLoopFound:
  iny
  lda sectorBuffer1, y
  cmp #'M'
  bne LoadDMAConfigLoopNext
  iny
  lda sectorBuffer1, y
  cmp #'A'
  bne LoadDMAConfigLoopNext
  iny
  lda sectorBuffer1, y
  cmp #'='
  bne LoadDMAConfigLoopNext

LoadDMAConfigLoopRecord:
  iny
  lda sectorBuffer1, y
  cmp #'0'
  beq LoadDMAConfigDone
  lda #$00
  sta dontUseDMA
LoadDMAConfigDone:
  


LoaderLoadModuleDone:  
  wai
  ClearLine 19

  jump jClearFindEntry
  lda #'S'
  sta findEntry
  lda #'I'
  sta findEntry+1
  SetCursorPos 13, 1
  jump jCardLoadModule      ;load intro module




ForeverLoader:
  lda #$81
  sta $4200  ;;turn on nmi
ForeverLoop:
  wai  ;wait for next frame
  jmp ForeverLoop




LoadLogo:
  lda #$5A          ;;X
  sta SpriteBuf1+16
  lda #$10          ;;Y
  sta SpriteBuf1+17
  lda #$04          ;;tile num
  sta SpriteBuf1+18
  lda #$00
  sta SpriteBuf1+19 ;;vhoopppc Vert Horiz priOrity Palette Charmsb

  lda #$7A          ;;X
  sta SpriteBuf1+20
  lda #$10          ;;Y
  sta SpriteBuf1+21
  lda #$08          ;;tile num
  sta SpriteBuf1+22
  lda #$00
  sta SpriteBuf1+23 ;;vhoopppc Vert Horiz priOrity Palette Charmsb

  lda #$5A          ;;X
  sta SpriteBuf1+24
  lda #$30          ;;Y
  sta SpriteBuf1+25
  lda #$44          ;;tile num
  sta SpriteBuf1+26
  lda #$00
  sta SpriteBuf1+27 ;;vhoopppc Vert Horiz priOrity Palette Charmsb
  
  lda #$7A          ;;X
  sta SpriteBuf1+28
  lda #$30          ;;Y
  sta SpriteBuf1+29
  lda #$48          ;;tile num
  sta SpriteBuf1+30
  lda #$00
  sta SpriteBuf1+31 ;;vhoopppc Vert Horiz priOrity Palette Charmsb
  
  lda #$AA
  sta SpriteBuf2+1  ;;32x32 sprites
  SetCursorPos 9, 0
  PrintString "         SNES POWERPAK          "  
  rts
  
  
  






CardFormatError:
  ClearLine 19
  ClearLine 20
  ClearLine 21
  SetCursorPos 19, 1
  PrintString "Card Format Error"
  PrintString "\n Use FAT16 or FAT32"
  PrintString "\n1C2(fm)="
  lda sectorBuffer1+$1C2                ;card last word read
  sta errorCode
  PrintHexNum errorCode
  PrintString " 1FE(55)="
  lda sectorBuffer1+$1FE                ;card last word read
  sta errorCode
  PrintHexNum errorCode
  PrintString " 1FF(AA)="
  lda sectorBuffer1+$1FF                ;card last word read
  sta errorCode
  PrintHexNum errorCode
  jump jForever







CardReset:
  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
  rts










CardWaitNotBusy:
CardWaitNotBusyLoop:           ;wait for not busy
  lda CARDSTATUS           ;card status read
  sta errorCode
  and #%10000000
  cmp #%10000000           ;check busy bit
  bne CardWaitNotBusyDone
;  SetCursorPos 12, 0
;  PrintString "    Error $"
;  PrintHexNum errorCode
;  PrintString " - CF card busy    "
  jmp CardWaitNotBusyLoop
CardWaitNotBusyDone:
  rts


CardWaitReady:
CardWaitReadyLoop:            ; wait until card ready
  lda CARDSTATUS
  sta errorCode
  and #%01010000
  cmp #%01010000
  beq CardWaitReadyDone
;  SetCursorPos 12, 0
;  PrintString "    Error $"
;  PrintHexNum errorCode
;  PrintString " - CF not ready    "
  jmp CardWaitReadyLoop
CardWaitReadyDone:
  rts


CardWaitDataReq:           ;wait for not busy, ready, datareq, no error
CardWaitDataReqLoop:
  lda CARDSTATUS
  sta errorCode
  and #%01011000
  cmp #%01011000
  beq CardWaitDataReqDone
;  SetCursorPos 12, 0
;  PrintString "    Error $"
;  PrintHexNum errorCode
;  PrintString " - CF no data req    "
  jmp CardWaitDataReqLoop
CardWaitDataReqDone:
  rts



CardCheckError:
  lda CARDSTATUS           ; get card status, check for general error
  sta errorCode
  and #%00000001
  cmp #%00000001
  beq CardError
  rts  
CardError:
  ClearLine 19
  ClearLine 20
  SetCursorPos 19, 1
  PrintString "Error $"
  PrintHexNum errorCode
  PrintString " - CF card status"
  SetCursorPos 20, 1
  lda CARDERROR
  sta errorCode
  PrintString "Error $"
  PrintHexNum errorCode
  PrintString " - CF card error"
  
;.IFDEF DEBUG
  lda CARDSECTORCOUNTREAD
  sta errorCode
  PrintString "\n  c=$"
  PrintHexNum errorCode

  lda CARDLBA0READ
  sta errorCode
  PrintString " 0=$"
  PrintHexNum errorCode

  lda CARDLBA1READ
  sta errorCode
  PrintString " 1=$"
  PrintHexNum errorCode

  lda CARDLBA2READ
  sta errorCode
  PrintString " 2=$"
  PrintHexNum errorCode

  lda CARDLBA3READ
  sta errorCode
  PrintString " 3=$"
  PrintHexNum errorCode
  PrintString "\n"  
;.ENDIF
CardErrorForever:
  jump jForever














CardLoadLBA:
  jump jCardWaitNotBusy
  jump jCardWaitReady
  jump jCardCheckError
  
  lda #$01
  sta CARDSECTORCOUNT
  jump jCardWaitNotBusy   ;;LAST check busy/ready/error after each command
  jump jCardWaitReady
 ; jump jCardCheckError  

  lda sourceSector
  sta CARDLBA0
  jump jCardWaitNotBusy
  jump jCardWaitReady
  ;jump jCardCheckError

  lda sourceSector+1
  sta CARDLBA1    
  jump jCardWaitNotBusy
  jump jCardWaitReady
  ;jump jCardCheckError

  lda sourceSector+2
  sta CARDLBA2
  jump jCardWaitNotBusy
  jump jCardWaitReady
  ;jump jCardCheckError

  lda sourceSector+3        ;load lba number
  and #%00001111
  ora #%11100000
  sta sourceSector+3
  sta CARDLBA3
  jump jCardWaitNotBusy
  jump jCardWaitReady
  jump jCardCheckError

  rts
  
  
  
  




CardReadSector:
  lda #$00
  sta $4200    ;;turn OFF NMI
  
  jump jCardLoadLBA

  lda #$00
  sta sourceBytes16
  lda #$02
  sta sourceBytes16+1
  
  ;jump jCardWaitNotBusy
  ;jump jCardWaitReady
  ;jump jCardCheckError
  
  lda #$20
  sta CARDCOMMAND           ;send card read sector command

  jump jCardWaitNotBusy
  jump jCardWaitReady
  jump jCardCheckError

  jump jCardWaitDataReq
  

CardReadSectorToWRAM:   ;;CF to WRAM
  lda destType
  cmp #kDestWRAM
  bne CardReadSectorToWRAMDone
  
  lda dontUseDMA
  beq CardReadSectorToWRAMJump     ;;if dontusedma=1, no dma
  jump jCardReadBytesNoDMA
  jmp CardReadSectorCheckDone
  
CardReadSectorToWRAMJump:
  jump jCardReadBytesToWRAM        ;;CF to WRAM - DMA
  jmp CardReadSectorCheckDone
CardReadSectorToWRAMDone:

CardReadSectorToFPGA:              ;;CF to FPGA - cant use DMA
  lda destType
  cmp #kDestFPGA
  bne CardReadSectorToFPGADone
  jump jCardReadBytesToFPGA
  jmp CardReadSectorCheckDone
CardReadSectorToFPGADone:

CardReadSectorToSDRAM:             ;;CF to SDRAM - DMA, no inc
  lda destType
  cmp #kDestSDRAM
  bne CardReadSectorToSDRAMDone
  jump jCardReadBytesToSDRAM
  jmp CardReadSectorCheckDone
CardReadSectorToSDRAMDone:


CardReadSectorToSDRAMNoDMA:             ;;CF to SDRAM - NO DMA
  lda destType
  cmp #kDestSDRAMNoDMA
  bne CardReadSectorToSDRAMNoDMADone
  jump jCardReadBytesToSDRAMNoDMA
  jmp CardReadSectorCheckDone
CardReadSectorToSDRAMNoDMADone:

    
  jump jCardReadBytesNoDMA         ;;CF to somewhere, no DMA
    
CardReadSectorCheckDone:

  jump jCardWaitNotBusy
  jump jCardWaitReady
  jump jCardCheckError
  
;  lda CARDSECTORCOUNTREAD
;  sta errorCode
;  bne CardReadSectorFailed        ;;LAST make sure sectors = 0
CardReadSectorPassed:
  ;jump jCardWaitNotBusy             ;;LAST check for busy before error
  ;jump jCardWaitReady
  ;jump jCardCheckError
  lda $4210    ;clear NMI Flag
  lda #$81
  sta $4200    ;;turn ON NMI

CardReadSectorDone:
  rts  
  
  
CardReadSectorFailed:
  ClearLine 19
  ClearLine 20
  SetCursorPos 19, 1
  PrintString "Error CF sectors left = "
  PrintHexNum errorCode
  SetCursorPos 20, 1
  lda CARDERROR
  sta errorCode
  PrintString "Error $"
  PrintHexNum errorCode
  PrintString " - CF card error"
CardReadSectorFailedForever:
  jump jForever
  






CardReadBytesNoDMA:         ;read source256*sourceBytes bytes into ram
  ldx sourceBytes16
  ldy #$0000
CardReadBytesNoDMALoop:
  lda CARDDATAREAD
;  sta $000200, y
  sta [destLo], y    
  iny
  dex
  bne CardReadBytesNoDMALoop
 ; PrintHexNum bankCounter
;  PrintString "CardReadBytesDone\n"
  rts





CardReadBytesToFPGA:           ;no DMA
  ldx sourceBytes16
CardReadBytesToFPGALoop:
  lda CARDDATAREAD            ;;READ DATA BYTE
  sta FPGADATAWRITE           ;;WRITE TO FPGA
  dex
  bne CardReadBytesToFPGALoop
  rts
  




CardReadBytesToWRAM:         ;use DMA, no increment source or dest

  lda #$08
  sta $4300   ;;no source increment
  
  lda #$80
  sta $4301   ;;dest = wram $2180
  
  lda #CARDDATAREADlow
  sta $4302
  lda #CARDDATAREADhigh
  sta $4303
  lda #CARDDATAREADbank
  sta $4304   ;;source = CARDDATAREAD

  ldx sourceBytes16
  stx $4305   ;;size = sourceBytes16

  ldx destLo
  stx $2181
;  lda destLo+1
;  sta $2182
  lda #$00
  sta $2183  ;;load the RAM dest address
  
  lda #$01
  sta $420B   ;Initiate transfer using channel 1
  rts
  
  
  
  
  
  
  
  
  
  
  
  
  
  
CardReadBytesToSDRAMNoDMA:
  ldx sourceBytes16
CardReadBytesToSDRAMLoop:
  lda CARDDATAREAD  ;;READ DATA BYTE
  sta $0021FF     ;;WRITE TO sdram       ;;;SEE IF A021FF WORKS
  dex
  bne CardReadBytesToSDRAMLoop
  rts


  ;;TEST THIS ONE
CardReadBytesToSDRAM:
  lda #$08
  sta $4300   ;;no source increment
  
  lda #$FF
  sta $4301   ;;dest = sdram $21FF
  
  lda #CARDDATAREADlow
  sta $4302
  lda #CARDDATAREADhigh
  sta $4303
  lda #CARDDATAREADbank
  sta $4304   ;;source = CARDDATAREAD
  
  ldx sourceBytes16
  stx $4305   ;;size = sourceBytes16
  
  lda #$01
  sta $420B   ;Initiate transfer using channel 1
  rts
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
LoadNextSectorNumDebug:     ;get next sector, use sectorCounter to check if next cluster needed
  clc
  lda sourceSector  
  adc #$01
  sta sourceSector                   ;go to next sector num
  lda sourceSector+1
  adc #$00
  sta sourceSector+1
  lda sourceSector+2
  adc #$00
  sta sourceSector+2
  lda sourceSector+3
  adc #$00
  sta sourceSector+3
  
  clc
  lda sectorCounter                   ;one more sector
  adc #$01
  sta sectorCounter
  cmp sectorsPerCluster
  beq LoadNextClusterNumDebug
  rts
  
LoadNextClusterNumDebug:
  lda #$00
  sta sectorCounter
  jump jNextCluster                      ;get cluster num into sourceCluster from FAT table
  
;  PrintString "cluster="
;  PrintString sourceCluster+3
;  PrintString sourceCluster+2
;  PrintString sourceCluster+1
;  PrintString sourceCluster+0
;  PrintString "\n"
  
  jump jClusterToLBA                     ;get sector num into sourceSector
;  PrintString "sector="
;  PrintHexNum sourceSector+3
;  PrintHexNum sourceSector+2
;  PrintHexNum sourceSector+1
;  PrintHexNum sourceSector+0
;  PrintString "\n"

;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai
;  wai

  

  rts
  
  
  
  
CardReadFile:                 ;;sourceCluster already set  
  lda #$00
  sta gameSize
  sta gameSize+1
  jump jClusterToLBA            ;sourceCluster -> first sourceSector

CardReadFileLoop:
;  PrintHexNum sourceSector+3
;  PrintHexNum sourceSector+2
;  PrintHexNum sourceSector+1
;  PrintHexNum sourceSector+0
;  PrintString "."
  clc
  lda gameSize
  adc #$01
  sta gameSize
  lda gameSize+1
  adc #$00
  sta gameSize+1            ;;keep track of game size


  lda #kDestSDRAM
  sta destType
  jump jCardReadSector

  lda destHi
  pha
  lda destLo
  pha
  jsr LoadNextSectorNumDebug
  pla 
  sta destLo
  pla 
  sta destHi

CardReadFileLastSectorCheck:  
  lda #$0F
  sta temp
  lda #$FF
  sta temp+1                            ;;FAT32 last cluster = 0x0FFFFFFF
  sta temp+2
  sta temp+3

  lda fat32Enabled
  cmp #$01
  beq CardReadFileLastSectorCheck2        ;;if FAT32, last cluster mask done
  
  lda #$00
  sta temp
  sta temp+1                             ;;FAT16 last cluster = 0x0000FFFF
  
CardReadFileLastSectorCheck2:
  ;check if cluster = last cluster
  ; if match, jmp to last entry found
  lda temp
  cmp sourceCluster+3
  bne CardReadFileNextSector
  lda temp+1
  cmp sourceCluster+2
  bne CardReadFileNextSector
  lda temp+2
  cmp sourceCluster+1
  bne CardReadFileNextSector
  lda temp+3
  cmp sourceCluster+0
  bne CardReadFileNextSector
  jmp CardReadFileDone

CardReadFileNextSector:
  inc destHi
  inc destHi
  inc bankCounter
  lda bankCounter
;  cmp #$00                 ;;only load 256x512=128KB for modules
;  beq CardReadFileDone

  jmp CardReadFileLoop

CardReadFileDone:
  rts




  
  
  
  
  
  
  
CardWriteFile:                 ;;sourceCluster already set
  stz sectorCounter
  stz bankCounter
  lda #kDestWRAM
  sta destType
  
  jump jClusterToLBA            ;sourceCluster -> first sourceSector

CardWriteFileLoop:
  jump jCardWriteSector          ;sector -> code ram

  lda destHi
  pha
  lda destLo
  pha
  jump jLoadNextSectorNum
  pla 
  sta destLo
  pla 
  sta destHi

CardWriteFileLastSectorCheck:  
  lda #$0F
  sta temp
  lda #$FF
  sta temp+1                            ;;FAT32 last cluster = 0x0FFFFFFF
  sta temp+2
  sta temp+3

  lda fat32Enabled
  cmp #$01
  beq CardWriteFileLastSectorCheck2        ;;if FAT32, last cluster mask done
  
  lda #$00
  sta temp
  sta temp+1                             ;;FAT16 last cluster = 0x0000FFFF
  
CardWriteFileLastSectorCheck2:
  ;check if cluster = last cluster
  ; if match, jmp to last entry found
  lda temp
  cmp sourceCluster+3
  bne CardWriteFileNextSector
  lda temp+1
  cmp sourceCluster+2
  bne CardWriteFileNextSector
  lda temp+2
  cmp sourceCluster+1
  bne CardWriteFileNextSector
  lda temp+3
  cmp sourceCluster+0
  bne CardWriteFileNextSector
  jmp CardWriteFileDone

CardWriteFileNextSector:
  inc sourceHi
  inc sourceHi
  inc bankCounter
;  lda bankCounter
;  cmp #$00                 ;;only load 256x512=128KB for modules
;  beq CardWriteFileDone
  jmp CardWriteFileLoop

CardWriteFileDone:
  rts
  
  





CardWriteSector:
  jump jCardWaitNotBusy
  jump jCardWaitReady
  jump jCardCheckError
  jump jCardLoadLBA

  lda #$00
  sta sourceBytes16
  lda #$02
  sta sourceBytes16+1
  
  jump jCardWaitNotBusy
  jump jCardWaitReady
  jump jCardCheckError
  
  lda #$30
  sta CARDCOMMAND           ;send card write sector command
  nop
  nop

  jump jCardCheckError
  jump jCardWaitDataReq
  
CardWriteSectorSDRAM:
  lda sourceType
  cmp #kSourceSDRAM
  bne CardWriteSectorNotSDRAM
  jump jCardWriteBytesFromSDRAM
CardWriteSectorNotSDRAM:

CardWriteSectorWRAM:
  lda sourceType
  cmp #kSourceWRAM
  bne CardWriteSectorNotWRAM
  jump jCardWriteBytesFromWRAM
CardWriteSectorNotWRAM:

  jump jCardCheckError
  
CardWriteSectorDone:
  rts  



CardWriteBytesFromWRAM:         ;write source256*sourceBytes bytes into CF card
  ldx sourceBytes16
  ldy #$0000
CardWriteBytesWRAMLoop:
  lda [sourceLo], y
  sta CARDDATAWRITE
  iny
  dex
  bne CardWriteBytesWRAMLoop
  rts


CardWriteBytesFromSDRAM:         ;write source256*sourceBytes bytes into CF card
  ldx sourceBytes16
CardWriteBytesSDRAMLoop:
  lda $21FF
  sta CARDDATAWRITE            ;;FIXME CHANGE TO USE DMA FROM SDRAM TO CF
  dex
  bne CardWriteBytesSDRAMLoop
  rts




ClusterToLBA:              ;  cluster->lba     lba_addr(4) = clusterBeginLBA(4) + (cluster_number(2)-2 * sectorsPerCluster(1))
  sec
  lda sourceCluster
  sbc #$02
  sta sourceSector
  lda sourceCluster+1
  sbc #$00
  sta sourceSector+1
  lda sourceCluster+2
  sbc #$00
  sta sourceSector+2        ;sourceSector = sourceCluster - 2
  lda sourceCluster+3
  sbc #$00
  sta sourceSector+3
  
  lda sectorsPerCluster
  sta source256
  
  clc
  lsr source256
  lda source256
  cmp #$00
  beq ClusterToLBAAddClusterBeginLBA   ;handle 1 sector per cluster

ClusterToLBALoop:
  clc
  asl sourceSector
  rol sourceSector+1
  rol sourceSector+2         ;sourceSector = sourceSector * sectorsPerCluster
  rol sourceSector+3
  clc
  lsr source256
  lda source256
  cmp #$00
  bne ClusterToLBALoop
  
ClusterToLBAAddClusterBeginLBA:  
  clc
  lda sourceSector
  adc clusterBeginLBA
  sta sourceSector
  lda sourceSector+1
  adc clusterBeginLBA+1       ;sourceSector = sourceSector(4) + clusterBeginLBA(4)
  sta sourceSector+1
  lda sourceSector+2
  adc clusterBeginLBA+2
  sta sourceSector+2  
  lda sourceSector+3
  adc clusterBeginLBA+3
  sta sourceSector+3
 
ClusterToLBADone:
  rts










CardLoadDirClearEntryName:
  lda #$00
  sta lfnFound
  ldy #$0000
  lda #$00
CardLoadDirClearEntryNameLoop:            ;clear entry name    //CHANGE ME 128 BYTES
  sta tempEntry, y
  iny
  cpy #$0020
  bne CardLoadDirClearEntryNameLoop
  rts






;dest = sector dest  0200
;sourceEntry = where to get entry in 0200-0400, when overflow, load next sector
;destBank =  which bank to select in prg ram
;destEntry = where to put entry in prg ram 6000-7FFF, when overflow, increment bank
CardLoadDir:  
  lda #>sectorBuffer1
  sta destHi                   ; sourceSector1 = where to put sector, where to read entry
  sta sourceEntryHi
  lda #<sectorBuffer1
  sta destLo
  sta sourceEntryLo
  stz destBank
  stz sourceEntryBank
  
  
  stz destEntryHi
  stz destEntryLo
  lda #$7F
  sta destEntryBank            ;$7F0000 - where to put entry


  stz filesInDir
  stz filesInDir+1
  stz sectorCounter
  stz temp
  stz temp+1
  stz selectedEntry
  stz selectedEntry+1
  stz lfnFound
    
  jump jClusterToLBA            ; sourceCluster -> first sourceSector
  
  lda fat32Enabled
  cmp #$01
  beq CardLoadDirReadSector   ; FAT32 go to read sector
  
  lda sourceCluster            ;FAT16  check if trying to load root dir
  cmp rootDirCluster
  bne CardLoadDirReadSector
  lda sourceCluster+1
  cmp rootDirCluster+1
  bne CardLoadDirReadSector
  lda sourceCluster+2
  cmp rootDirCluster+2
  bne CardLoadDirReadSector 
  lda sourceCluster+3
  cmp rootDirCluster+3
  bne CardLoadDirReadSector  
  

  sec
  lda clusterBeginLBA
  sbc fat16RootSectors          ; FAT16 sourceSector = root dir first sector =>  clusterLBABegin(4) - fat16RootSectors(1)
  sta sourceSector
  lda clusterBeginLBA+1
  sbc #$00
  sta sourceSector+1
  lda clusterBeginLBA+2
  sbc #$00
  sta sourceSector+2  
  lda clusterBeginLBA+3
  sbc #$00
  sta sourceSector+3
  
  
      
CardLoadDirReadSector:  
  lda #kDestWRAM
  sta destType
  jump jCardReadSector          ; put into dest
  jump jCardLoadDirClearEntryName   ;clear entry name

CardLoadDirLoop:
  ldy #$0000
  lda [sourceEntryLo], y            ; if name[0] = 0x00, no more entries
  cmp #$00
  beq CardLoadDirLastEntryFound
  jmp CardLoadDirCheckUnused
    
CardLoadDirLastEntryFound:
  rts

CardLoadDirCheckUnused:
  ldy #$0000
  lda [sourceEntryLo], y
  cmp #$E5                     ; if name[0] = 0xE5, entry unused, skip
  bne CardLoadDirCheckLongName
  lda #$00
  sta lfnFound
  jmp CardLoadDirNextEntry



CardLoadDirCheckLongName:
  ldy #$000B
  lda [sourceEntryLo], y            ; if flag = %00001111, long file name entry found
  and #$0F
  cmp #$0F
  bne CardLoadDirCheckShortName
  
  ldy #$0000
  lda [sourceEntryLo], y
  and #%10111111                 ;mask off "last entry" bit
  cmp #$01                     ; if index = 1 or 2, load name    //CHANGE ME  INDEX < 10
  beq CardLoadDirLongName1      ; else skip entry
  cmp #$02
  beq CardLoadDirLongName2
  
  jump jCardLoadDirClearEntryName
  
  jmp CardLoadDirNextEntry
  
  
      ;//CHANGE ME  USE MULTIPLY13 FUNCTION
CardLoadDirLongName1:
  ldx #$0000                     ; index 1 = chars 0-12
  jmp CardLoadDirLongName
CardLoadDirLongName2:
  ldx #$000D                     ; index 2 = chars 13-25
  jmp CardLoadDirLongName
  
  
  
CardLoadDirLongName:
  lda #$00
  sta tempEntry+$20                 ;use as char counter    //CHANGE ME
  ldy #$0001
CardLoadDirLongNameLoop1:
  lda [sourceEntryLo], y             ; loop thro 5 chars   1x3x5x7x9x
  cmp #$FF
  beq CardLoadDirLongNameLoop1FF
  sta tempEntry, x
CardLoadDirLongNameLoop1FF:
  inx
  iny
  iny
  inc tempEntry+$20                 ;use as char counter      //CHANGE ME
  lda tempEntry+$20                 ;use as char counter      //CHANGE ME
  cmp #$05
  bne CardLoadDirLongNameLoop1

  ldy #$000E
CardLoadDirLongNameLoop2:
  lda [sourceEntryLo], y             ; loop thro 6 chars   Ex10x12x14x16x18x
  cmp #$FF
  beq CardLoadDirLongNameLoop2FF  
  sta tempEntry, x
CardLoadDirLongNameLoop2FF:
  inx
  iny
  iny
  inc tempEntry+$20                 ;use as char counter      //CHANGE ME  
  lda tempEntry+$20                 ;use as char counter    //CHANGE ME
  cmp #$0B
  bne CardLoadDirLongNameLoop2
    
  ldy #$001C
CardLoadDirLongNameLoop3:
  lda [sourceEntryLo], y             ;  thro 2 chars   1Cx1Ex
  cmp #$FF
  beq CardLoadDirLongNameLoop3FF  
  sta tempEntry, x
CardLoadDirLongNameLoop3FF:
  inx
  iny
  iny
  lda [sourceEntryLo], y
  cmp #$FF
  beq CardLoadDirLongNameLoop4FF  
  sta tempEntry, x
CardLoadDirLongNameLoop4FF:

  lda #$01
  sta lfnFound
  jmp CardLoadDirNextEntry
  
CardLoadDirCheckShortName:
  ldy #$000B
  lda [sourceEntryLo], y                 ;if flag = volume id, skip
  and #$08
  cmp #$08
  bne CardLoadDirCheckHidden
  jump jCardLoadDirClearEntryName
  lda #$00
  sta lfnFound
  jmp CardLoadDirNextEntry


CardLoadDirCheckHidden:
  ldy #$000B
  lda [sourceEntryLo], y
  and #$02
  cmp #$02                                ; if flag = 0x02, hidden, skip
  bne CardLoadDirCheckDir
  lda #$00
  sta lfnFound
  jump jCardLoadDirClearEntryName           ;clear entry name  
  jmp CardLoadDirNextEntry
  
      
CardLoadDirCheckDir:
  ldy #$000B
  lda [sourceEntryLo], y                 ;if flag = directory, load entry
  and #$10
  cmp #$10
  bne CardLoadDirCheckEx1
  lda #$01
  sta tempEntry+$1B                      ;$1B = dir flag  //CHANGE ME
  jmp CardLoadDirShortName

CardLoadDirCheckEx1:
  ldx #$0000
  ldy #$0008
CardLoadDirCheckEx1Loop:
  lda [sourceEntryLo], y
  cmp exMatch1, x
  beq CardLoadDirCheckEx2
  inx
  cpx #$0004
  bne CardLoadDirCheckEx1Loop
  lda #$00
  sta lfnFound
  jump jCardLoadDirClearEntryName    
  jmp CardLoadDirNextEntry          ;if extension doesnt match, skip

CardLoadDirCheckEx2:
  ldx #$0000
  ldy #$0009
CardLoadDirCheckEx2Loop:
  lda [sourceEntryLo], y
  cmp exMatch2, x
  beq CardLoadDirCheckEx3
  inx
  cpx #$0004
  bne CardLoadDirCheckEx2Loop
  lda #$00
  sta lfnFound
  jump jCardLoadDirClearEntryName
  jmp CardLoadDirNextEntry          ;if extension doesnt match, skip

CardLoadDirCheckEx3:
  ldx #$0000
  ldy #$000A
CardLoadDirCheckEx3Loop:
  lda [sourceEntryLo], y
  cmp exMatch3, x
  beq CardLoadDirShortName
  inx
  cpx #$0004
  bne CardLoadDirCheckEx3Loop
  lda #$00
  sta lfnFound
  jump jCardLoadDirClearEntryName
  jmp CardLoadDirNextEntry          ;if extension doesnt match, skip

CardLoadDirShortName:
  clc  
  lda filesInDir                      ;filesInDir++
  adc #$01
  sta filesInDir
  lda filesInDir+1
  adc #$00
  sta filesInDir+1
  
  lda lfnFound
  cmp #$01
  beq CardLoadDirLongShortNameFound
  
CardLoadDirShortNameFound:  
  ldy #$0000
CardLoadDirShortNameLoop:            ;if lfnFound = 0, copy short name
  lda [sourceEntryLo], y
  sta tempEntry, y
  iny
  cpy #$0008
  bne CardLoadDirShortNameLoop

CardLoadDirShortFileName:  
  lda tempEntry+$1B                      ;$1B = dir flag  //CHANGE ME
  cmp #$01
  beq CardLoadDirSaveEntry

  lda #'.'
  sta tempEntry+$8
  ldy #$0008
  lda [sourceEntryLo], y    ;//copy short file name
  sta tempEntry+$9
  iny
  lda [sourceEntryLo], y
  sta tempEntry+$A
  iny
  lda [sourceEntryLo], y
  sta tempEntry+$B  
  
  jmp CardLoadDirSaveEntry
  
  
      
CardLoadDirLongShortNameFound:    
      
CardLoadDirSaveEntry:
  ldy #$001A
  lda [sourceEntryLo], y                  ;copy clusterhilo to last 4 bytes of entry   ///CHANGE ME
  sta tempEntry+$1C
  iny
  lda [sourceEntryLo], y
  sta tempEntry+$1D
  ldy #$0014
  lda [sourceEntryLo], y
  sta tempEntry+$1E
  iny
  lda [sourceEntryLo], y
  sta tempEntry+$1F
  
  
  ldy #$0000
CardLoadDirSaveEntryLoop:                 ;copy entry to prg ram   //CHANGE ME  128 bytes
  lda tempEntry, y
  sta [destEntryLo], y                
  iny
  cpy #$0020
  bne CardLoadDirSaveEntryLoop
    
  clc
  lda destEntryLo                         ;destEntry += 32   //CHANGE ME  to 128 bytes
  adc #$20
  sta destEntryLo
  lda destEntryHi
  adc #$00
  sta destEntryHi
  
;  lda destEntryHi                        ;check if destEntry is overflowing, inc bank, destEntry=6000
;  cmp #$80
;  bne CardLoadDirClearTempEntryName
;  lda #$60
;  sta destEntryHi                        ;reset to $6000
;  lda #$00
;  sta destEntryLo
;  inc destBank                           ;increment bank num

  jump jCardLoadDirClearEntryName

;CardLoadDirClearTempEntryName:
;  ldy #$0000
;  lda #$00  
;  sta lfnFound  
;CardLoadDirClearTempEntryLoop:            ;clear entry name
;  sta tempEntry, y
;  iny
;  cpy #$0020
;  bne CardLoadDirClearTempEntryLoop
    
CardLoadDirNextEntry:
  clc                                 ;increment entry source address
  lda sourceEntryLo                        ;sourceEntry += 32 in 0200-0400
  adc #$20
  sta sourceEntryLo
  lda sourceEntryHi
  adc #$00
  sta sourceEntryHi  
  
  lda sourceEntryHi                    ;if source overflows, get next sector
  cmp #>sectorBuffer1+$02   ;;LAST CHANGE
  beq CardLoadDirNextSector
  
  jmp CardLoadDirLoop
    
CardLoadDirNextSector:    
  clc
  lda sourceSector  
  adc #$01
  sta sourceSector                   ;go to next sector num
  lda sourceSector+1
  adc #$00
  sta sourceSector+1
  lda sourceSector+2
  adc #$00
  sta sourceSector+2
  lda sourceSector+3
  adc #$00
  sta sourceSector+3
  
  
  ;  if fat32, goto CardLoadDirSectorInc
  lda fat32Enabled
  cmp #$01
  beq CardLoadDirSectorInc

  
  lda sourceCluster            ;FAT16  check if trying to load root dir
  cmp rootDirCluster
  bne CardLoadDirSectorInc
  lda sourceCluster+1
  cmp rootDirCluster+1
  bne CardLoadDirSectorInc
  lda sourceCluster+2
  cmp rootDirCluster+2
  bne CardLoadDirSectorInc 
  lda sourceCluster+3
  cmp rootDirCluster+3
  bne CardLoadDirSectorInc  

  clc
  lda sectorCounter              ;FAT16 root dir all sequential sectors
  adc #$01
  sta sectorCounter

  ; if sectorCounter = fat16RootSectors
  ;        goto CardLoadDirLastEntryFound
  clc
  lda sectorCounter
  cmp fat16RootSectors
  beq CardLoadDirLastEntryFoundJmp
  jmp CardLoadDirLoadNextSector      ;FAT16 skip cluster lookup when max root sectors not reached
  

CardLoadDirLastEntryFoundJmp:
  jmp CardLoadDirLastEntryFound       ;FAT16 max root sectors reached, all root entries found
      
  
CardLoadDirSectorInc:
  clc
  lda sectorCounter                   ;one more sector
  adc #$01
  sta sectorCounter
  cmp sectorsPerCluster                ;make sure cluster isnt overflowing      
  bne CardLoadDirLoadNextSector
  
  ;;;move to next cluster
  jump jNextCluster                      ;get cluster num into sourceCluster


CardLoadDirLastEntryCheck:  
  lda #$0F
  sta temp
  lda #$FF
  sta temp+1                            ;;FAT32 last cluster = 0x0FFFFFFF
  sta temp+2
  sta temp+3

  lda fat32Enabled
  cmp #$01
  beq CardLoadDirLastEntryCheck2        ;;if FAT32, last cluster mask done
  
  lda #$00                              ;;FAT16 last cluster = 0x0000FFFF
  sta temp
  sta temp+1
  
CardLoadDirLastEntryCheck2:
  ;check if cluster = last cluster
  ; if match, jmp to last entry found
  lda temp
  cmp sourceCluster+3
  bne CardLoadDirNextSectorNum
  lda temp+1
  cmp sourceCluster+2
  bne CardLoadDirNextSectorNum
  lda temp+2
  cmp sourceCluster+1
  bne CardLoadDirNextSectorNum
  lda temp+3
  cmp sourceCluster+0
  bne CardLoadDirNextSectorNum
  
  jmp CardLoadDirLastEntryFound


CardLoadDirNextSectorNum:
  jump jClusterToLBA                     ;sourceCluster -> first sourceSector
  lda #$00
  sta sectorCounter                    ;reset sector counter

CardLoadDirLoadNextSector:
  lda #<sectorBuffer1
  sta destLo                          ;reset sector dest
  sta sourceEntryLo                   ;reset entry source
  lda #>sectorBuffer1                   
  sta destHi
  sta sourceEntryHi
  stz destBank
  stz sourceEntryBank
  lda #kDestWRAM
  sta destType
  jump jCardReadSector
  jmp CardLoadDirLoop










NextCluster:    ;load fat entry for sourceCluster, store next cluster number into sourceCluster
  ;fat16:
    ; offset = clusternum << 1
    ;mask = 00 00 ff ff
  asl sourceCluster
  rol sourceCluster+1
  rol sourceCluster+2
  rol sourceCluster+3
  ;fat32:
    ;offset = clutsernum << 2       cluster 2 << 2 = 8
    ;mask = 0f ff ff ff
  lda fat32Enabled
  cmp #$00
  beq NextClusterSectorNum
  
  asl sourceCluster
  rol sourceCluster+1
  rol sourceCluster+2
  rol sourceCluster+3    

NextClusterSectorNum:
  ;fat sector num = fatBeginLBA + (offset / 512)     cluster = $2f8
  lda sourceCluster+1
  sta sourceSector+0
  lda sourceCluster+2
  sta sourceSector+1
  lda sourceCluster+3                ;divide by 256   sector = 02
  sta sourceSector+2
  lda #$00
  sta sourceSector+3
  
  lsr sourceSector+3                   ;divide by 512   sector = 01
  ror sourceSector+2
  ror sourceSector+1        
  ror sourceSector+0    
  clc
  lda sourceSector
  adc fatBeginLBA
  sta sourceSector
  lda sourceSector+1                 ;add fatBeginLBA   sector = 60 = $c000
  adc fatBeginLBA+1
  sta sourceSector+1
  lda sourceSector+2
  adc fatBeginLBA+2
  sta sourceSector+2
  lda sourceSector+3
  adc fatBeginLBA+3
  sta sourceSector+3

  ;load fat sector
  lda #>sectorBuffer1
  sta destHi
  lda #<sectorBuffer1
  sta destLo
  stz destBank
  lda #kDestWRAM
  sta destType
  jump jCardReadSector
  
  ;offset = offset % 512    ;offset of fat entry within loaded sector 0-511
  lda sourceCluster+1
  and #%00000001
  sta sourceCluster+1    ; cluster+1=0
  
  ;next cluster = [sector], offset
  lda #<sectorBuffer1
  sta sourceLo
  stz sourceBank
  
  lda #>sectorBuffer1
  adc sourceCluster+1       ;sourceHi = sectorBuffer1(high) or sectorBuffer1(high)+1 for which 256 byte block too look in
  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
  
  lda #$00
  sta sourceCluster+3     ;fat16 mask
  sta sourceCluster+2
  
NextClusterDone:
  rts










DirPrintDir:
  ;turn off rendering
;  jsr RenderingOff
  jump jPrintClearScreen
  
  ;loop thro entries 0 to 31 or 0 to filesInDir
  lda #$00
  sta selectedEntry
  sta selectedEntry+1
  sta temp
  
  SetCursorPos 0 0
  
DirPrintDirLoop:
  inc temp                                   ; go to next print line

  jump jDirPrintEntry
 ; jsr DirPrintEntry                            ;copy dir entry to printString
 ; jsr PrintLine                                ;print to name table
    
  clc
  lda selectedEntry
  adc #$01
  sta selectedEntry
  lda selectedEntry+1                                   ;increment to next entry index
  adc #$00
  sta selectedEntry+1
  
DirPrintDir32Check:
  ;check if printY equal to 29, jump out
  lda temp
  cmp #$1D
  beq DirPrintDirLoopDone
  
DirPrintDirFileCheck:
  ;check if temp/temp+1 equal to filesInDir, jump out
  lda selectedEntry
  cmp filesInDir
  bne DirPrintDirLoop
  lda selectedEntry+1
  cmp filesInDir+1
  bne DirPrintDirLoop
    
DirPrintDirLoopDone:
  
  stz selectedEntry
  stz selectedEntry+1

  stz cursorX  
  lda #$08          
  sta cursorY            
  stz cursorYCounter      
  stz cursorYUp          
  stz cursorYDown          

  stz scrollY            
  stz scrollYCounter      
  stz scrollYUp           
  stz scrollYDown   
        
  stz speedCounter        
  stz speedScroll         

  lda #$1F
  sta insertTop
  lda #$1C
  sta insertBottom

  rts






DirPrintEntry:
  lda selectedEntry
  asl a
  asl a
  asl a
  asl a
  asl a
  sta sourceEntryLo
  
  lda selectedEntry
  lsr a
  lsr a
  lsr a
  sta sourceEntryHi
  
  lda selectedEntry+1
  asl a
  asl a
  asl a
  asl a
  asl a
  ora sourceEntryHi
  sta sourceEntryHi
  
  lda #$7F
  sta sourceEntryBank

  ldy #$0000
DirPrintEntryCopyLoop:
  lda [sourceEntryLo], y
  sta tempEntry+2, y
  iny
  cpy #$1B
  bne DirPrintEntryCopyLoop
  
  lda #' '
  sta tempEntry+$00
  sta tempEntry+$01
  sta tempEntry+$1D
  sta tempEntry+$1E
  sta tempEntry+$1F
  
  ldy #$1B
  lda [sourceEntryLo], y
  beq DirPrintEntryDone
  
  lda #'/'
  sta tempEntry+1
  
DirPrintEntryDone:
  lda #<tempEntry
  sta strPtr
  lda #>tempEntry
  sta strPtr+1
  ldy #strPtr
  PrintString "%s\n"
  rts





DirGetEntry:
  ;sourceEntryLo = selectedEntry * 32   temp << 5
  ;bank num = selectedEntry+1

  lda selectedEntry
  asl a
  asl a
  asl a
  asl a
  asl a
  sta sourceEntryLo
  
  lda selectedEntry
  lsr a
  lsr a
  lsr a
  sta sourceEntryHi
  
  lda selectedEntry+1
  asl a
  asl a
  asl a
  asl a
  asl a
  ora sourceEntryHi
  sta sourceEntryHi
  
  lda #$7F
  sta sourceEntryBank

  ldy #$0000
DirGetEntryCopyLoop:
  lda [sourceEntryLo], y
  sta tempEntry, y
  iny
  cpy #$0020
  bne DirGetEntryCopyLoop
  
  rts



  
DirFindEntry:
  lda #$00
  sta selectedEntry
  sta selectedEntry+1
  
  lda filesInDir
  bne DirFindEntryLoop
  lda filesInDir+1
  bne DirFindEntryLoop
  jmp DirFindEntryFailed
  
DirFindEntryLoop:
  jump jDirGetEntry
  ;jump jDirPrintEntry
  
  
  ;;check if entry matches, only look at first 8 chars
  ldy #$0000
DirFindEntryCharLoop:
  lda tempEntry, y
  cmp findEntry, y
  bne DirFindEntryNext
  iny
  cpy #$0008
  bne DirFindEntryCharLoop
  
  rts  ;all 8 chars match

DirFindEntryNext:
  clc
  lda selectedEntry
  adc #$01
  sta selectedEntry
  lda selectedEntry+1            ;increment to next entry index
  adc #$00
  sta selectedEntry+1
  
  lda selectedEntry 
  cmp filesInDir
  bne DirFindEntryLoop
  lda selectedEntry+1
  cmp filesInDir+1
  bne DirFindEntryLoop
  
DirFindEntryFailed:
  stz findEntry+8
  lda #<findEntry
  sta strPtr
  lda #>findEntry
  sta strPtr+1
  ldy #strPtr
  ClearLine 20
  SetCursorPos 20, 1
  PrintString "Error: %s File Not Found"
  wai
  jump jForever






CardLoadModule:
  lda #'M'
  sta exMatch1
  sta exMatch1+1
  sta exMatch1+2
  sta exMatch1+3
  lda #'A'
  sta exMatch2
  sta exMatch2+1
  sta exMatch2+2
  sta exMatch2+3
  lda #'P'
  sta exMatch3
  sta exMatch3+1
  sta exMatch3+2
  sta exMatch3+3

  lda baseDirCluster
  sta sourceCluster
  lda baseDirCluster+1
  sta sourceCluster+1
  lda baseDirCluster+2
  sta sourceCluster+2
  lda baseDirCluster+3
  sta sourceCluster+3
  
  jump jCardLoadDir    ; powerpak dir
  

  ;findEntry info already loaded

  jump jDirFindEntry        ;;get first cluster
  lda tempEntry+$1C
  sta sourceCluster
  lda tempEntry+$1D
  sta sourceCluster+1
  lda tempEntry+$1E
  sta sourceCluster+2
  lda tempEntry+$1F
  sta sourceCluster+3
 
  lda #<codeBuffer
  sta destLo
  lda #>codeBuffer
  sta destHi      ;put into code ram
  lda #$00
  sta destBank
  
  stz sectorCounter
  stz bankCounter
  jump jClusterToLBA            ;sourceCluster -> first sourceSector
;  SetCursorPos 1, 1
;  PrintString "CardLoadModuleLoop\n"

CardLoadModuleLoop:
;  SetCursorPos 14, 1
;  PrintHexNum bankCounter
;  PrintString "="
;  PrintHexNum destBank
;  PrintHexNum destHi
;  PrintHexNum destLo
;  PrintString "  "  
;  PrintHexNum sourceCluster+3
;  PrintHexNum sourceCluster+2
;  PrintHexNum sourceCluster+1
;  PrintHexNum sourceCluster+0
;  PrintString "  "  
;  PrintHexNum sourceSector+3
;  PrintHexNum sourceSector+2
;  PrintHexNum sourceSector+1
;  PrintHexNum sourceSector+0
;  PrintString "\n"

  lda #kDestWRAM
  sta destType
  jump jCardReadSector          ;sector -> code ram
 ; PrintHexNum bankCounter
 ; PrintString "read done\n"

  lda destHi
  pha
  lda destLo
  pha
  jump jLoadNextSectorNum
  pla 
  sta destLo
  pla 
  sta destHi
  

CardLoadModuleLastSectorCheck:  
  lda #$0F
  sta temp
  lda #$FF
  sta temp+1                            ;;FAT32 last cluster = 0x0FFFFFFF
  sta temp+2
  sta temp+3

  lda fat32Enabled
  cmp #$01
  beq CardLoadModuleLastSectorCheck2        ;;if FAT32, last cluster mask done
  
  lda #$00
  sta temp
  sta temp+1                             ;;FAT16 last cluster = 0x0000FFFF
  
CardLoadModuleLastSectorCheck2:
  ;check if cluster = last cluster
  ; if match, jmp to last entry found
  lda temp
  cmp sourceCluster+3
  bne CardLoadModuleNextSector
  lda temp+1
  cmp sourceCluster+2
  bne CardLoadModuleNextSector
  lda temp+2
  cmp sourceCluster+1
  bne CardLoadModuleNextSector
  lda temp+3
  cmp sourceCluster+0
  bne CardLoadModuleNextSector
  jmp CardLoadModuleDone

CardLoadModuleNextSector:
  inc destHi
  inc destHi
  inc bankCounter
  lda bankCounter
  cmp #$0A                 ;;only load 10x512=5KB for modules
  beq CardLoadModuleDone
  jmp CardLoadModuleLoop

CardLoadModuleDone:
;  PrintString "CardLoadModuleDone\n"
;  PrintHexNum destBank
;  PrintHexNum destHi
;  PrintHexNum destLo
;  PrintString "  "  
;  PrintHexNum sourceCluster+3
;  PrintHexNum sourceCluster+2
;  PrintHexNum sourceCluster+1
;  PrintHexNum sourceCluster+0
;  PrintString "\n"
  stz scrollY           
  stz scrollYCounter    
  stz scrollYUp         
  stz scrollYDown       
 ; jmp Forever  
  jml codeBuffer      ;go to module begin







LoadNextSectorNum:     ;get next sector, use sectorCounter to check if next cluster needed
  clc
  lda sourceSector  
  adc #$01
  sta sourceSector                   ;go to next sector num
  lda sourceSector+1
  adc #$00
  sta sourceSector+1
  lda sourceSector+2
  adc #$00
  sta sourceSector+2
  lda sourceSector+3
  adc #$00
  sta sourceSector+3
  
  clc
  lda sectorCounter                   ;one more sector
  adc #$01
  sta sectorCounter
  cmp sectorsPerCluster
  beq LoadNextClusterNum
  rts
  
LoadNextClusterNum:
  lda #$00
  sta sectorCounter
  jump jNextCluster                      ;get cluster num into sourceCluster from FAT table
  jump jClusterToLBA                     ;get sector num into sourceSector
  rts







NextDir:
  lda tempEntry+$1C
  sta sourceCluster
  lda tempEntry+$1D
  sta sourceCluster+1
  lda tempEntry+$1E
  sta sourceCluster+2
  lda tempEntry+$1F
  sta sourceCluster+3      ;load dir selected
  
  lda sourceCluster
  cmp #$00
  bne LoadNextDir
  lda sourceCluster+1       ;check if cluster = root dir
  cmp #$00
  bne LoadNextDir
  lda sourceCluster+2
  cmp #$00
  bne LoadNextDir
  lda sourceCluster+3
  cmp #$00
  bne LoadNextDir
  
  lda rootDirCluster
  sta sourceCluster
  lda rootDirCluster+1
  sta sourceCluster+1
  lda rootDirCluster+2
  sta sourceCluster+2
  lda rootDirCluster+3
  sta sourceCluster+3
  
  
LoadNextDir:  
  jump jPrintClearScreen
  SetCursorPos 0, 0
  jump jCardLoadDir
  jump jDirPrintDir
  rts









CardLoadFPGA:
;  PrintString "Loading FPGA\n"

  lda #$01
  sta FPGAPROGRAMWRITE   ;;SEND PROGRAM SIGNAL TO FPGA
  lda #$00
  sta FPGAPROGRAMWRITE   ;;SEND PROGRAM SIGNAL TO FPGA
  wai
  wai
  lda #$01
  sta FPGAPROGRAMWRITE   ;;SEND PROGRAM SIGNAL TO FPGA



  lda #'B'
  sta exMatch1
  sta exMatch1+1
  sta exMatch1+2
  sta exMatch1+3
  lda #'I'
  sta exMatch2
  sta exMatch2+1
  sta exMatch2+2
  sta exMatch2+3
  lda #'T'
  sta exMatch3
  sta exMatch3+1
  sta exMatch3+2
  sta exMatch3+3

  lda baseDirCluster
  sta sourceCluster
  lda baseDirCluster+1
  sta sourceCluster+1
  lda baseDirCluster+2
  sta sourceCluster+2
  lda baseDirCluster+3
  sta sourceCluster+3
  
  jump jCardLoadDir    ; powerpak dir
  

  ;findEntry info already loaded

  jump jDirFindEntry        ;;get first cluster
  lda tempEntry+$1C
  sta sourceCluster
  lda tempEntry+$1D
  sta sourceCluster+1
  lda tempEntry+$1E
  sta sourceCluster+2
  lda tempEntry+$1F
  sta sourceCluster+3
   
  stz sectorCounter
  stz bankCounter
  jump jClusterToLBA            ;sourceCluster -> first sourceSector
;  SetCursorPos 1, 1
;  PrintString "CardLoadModuleLoop\n"

  wai
  lda #$80
  sta $2100    ;;turn screen off

CardLoadFPGALoop:
;  SetCursorPos 14, 1
;  PrintHexNum bankCounter
;  PrintString "="
;  PrintHexNum destBank
;  PrintHexNum destHi
;  PrintHexNum destLo
;  PrintString "  "  
;  PrintHexNum sourceCluster+3
;  PrintHexNum sourceCluster+2
;  PrintHexNum sourceCluster+1
;  PrintHexNum sourceCluster+0
;  PrintString "  "  
;  PrintHexNum sourceSector+3
;  PrintHexNum sourceSector+2
;  PrintHexNum sourceSector+1
;  PrintHexNum sourceSector+0
;  PrintString "\n"

  lda #kDestFPGA
  sta destType
  jump jCardReadSector          ;sector -> FPGA
 ; PrintHexNum bankCounter
 ; PrintString "read done\n"

  jump jLoadNextSectorNum
  

CardLoadFPGALastSectorCheck:  
  lda #$0F
  sta temp
  lda #$FF
  sta temp+1                            ;;FAT32 last cluster = 0x0FFFFFFF
  sta temp+2
  sta temp+3

  lda fat32Enabled
  cmp #$01
  beq CardLoadFPGALastSectorCheck2        ;;if FAT32, last cluster mask done
  
  lda #$00
  sta temp
  sta temp+1                             ;;FAT16 last cluster = 0x0000FFFF
  
CardLoadFPGALastSectorCheck2:
  ;check if cluster = last cluster
  ; if match, jmp to last entry found
  lda temp
  cmp sourceCluster+3
  bne CardLoadFPGANextSector
  lda temp+1
  cmp sourceCluster+2
  bne CardLoadFPGANextSector
  lda temp+2
  cmp sourceCluster+1
  bne CardLoadFPGANextSector
  lda temp+3
  cmp sourceCluster+0
  bne CardLoadFPGANextSector
  jmp CardLoadFPGADone

CardLoadFPGANextSector:
  inc bankCounter
  lda bankCounter
  cmp #$6B                 ;;437312 bits = 54664 bytes = 107 sectors = $6B
  beq CardLoadFPGADone
  jmp CardLoadFPGALoop

CardLoadFPGADone:
;  PrintString "Loading FPGA DONE\n"
  lda #$0F
  sta $2100    ;;turn screen on
  
  rts




GameGenieClear:
  ldx #$0000
  lda #16
GameGenieClearLoop:
  sta gameGenie, y
  iny
  inx
  cpx #$0008
  bne GameGenieClearLoop
  rts




GameGenieChars:
  .db '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '_'
GameGenieDecoded:
  .db $04, $06, $0D, $0E, $02, $07, $08, $03, $0B, $05, $0C, $09, $0A, $00, $0F, $01, $00
  
GameGeniePrint:
  phy
  jsr CardLoadDirClearEntryName
  lda #$00
  sta gameGenieOffset+1
  ply

  lda gameGenie, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry
  lda #' '
  sta tempEntry+1
    
  lda gameGenie+1, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+2
  lda #' '
  sta tempEntry+3

  lda gameGenie+2, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+4
  lda #' '
  sta tempEntry+5
  
  lda gameGenie+3, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+6
  lda #' '
  sta tempEntry+7
  
  lda gameGenie+4, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+8
  lda #' '
  sta tempEntry+9
  
  lda gameGenie+5, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+10
  lda #' '
  sta tempEntry+11
  
  lda gameGenie+6, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+12
  lda #' '
  sta tempEntry+13
  
  lda gameGenie+7, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieChars, x
  sta tempEntry+14
  lda #$00
  sta tempEntry+15
 

  lda #<tempEntry
  sta strPtr
  lda #>tempEntry
  sta strPtr+1
  ldy #strPtr
  PrintString "%s"
  rts


GameGenieDecode:
  lda #$00
  sta gameGenieOffset+1
  
  lda gameGenie, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry
  
  lda gameGenie+1, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+1

  lda gameGenie+2, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+2

  lda gameGenie+3, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+3

  lda gameGenie+4, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+4

  lda gameGenie+5, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+5

  lda gameGenie+6, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+6

  lda gameGenie+7, y
  sta gameGenieOffset
  ldx gameGenieOffset
  lda.l GameGenieDecoded, x
  sta tempEntry+7

  lda tempEntry
  asl a
  asl a
  asl a
  asl a
  ora tempEntry+1
  sta gameGenieDecode, y  ;;;DATA done

  lda tempEntry+4   ;;xxxxxxAB
  asl a
  asl a
  asl a
  asl a
  asl a
  asl a
  and #$C0
  sta temp            ;;ABxxxxxx
  lda tempEntry+5     ;;xxxxCDxx
  asl a
  asl a
  and #$30
  ora temp
  sta temp            ;;ABCDxxxx
  lda tempEntry+6     ;;xxxxxxEF
  asl a
  asl a
  and #$0C            ;;xxxxEFxx
  ora temp 
  sta temp            ;;ABCDEFxx
  lda tempEntry+7     ;;xxxxGHxx
  lsr a
  lsr a
  and #$03            ;;xxxxxxGH
  ora temp
  sta temp            ;;ABCDEFGH
  sta gameGenieDecode+1, y
  
  lda tempEntry+2     ;;xxxxIJKL
  asl a
  asl a
  asl a
  asl a
  and #$F0
  sta temp            ;;IJKLxxxx
  lda tempEntry+7     ;;xxxxxxMN
  asl a
  asl a
  and #$0C            ;;xxxxMNxx
  ora temp
  sta temp            ;;IJKLMNxx
  lda tempEntry+4     ;;xxxxOPxx
  lsr a
  lsr a
  and #$03            ;;xxxxxxOP
  ora temp 
  sta temp            ;;IJKLMNOP
  sta gameGenieDecode+2, y
  
  
  
  
  lda tempEntry+3     ;;xxxxQRST
  asl a
  asl a
  asl a
  asl a
  and #$F0
  sta temp            ;;QRSTxxxx             
  lda tempEntry+5     ;;xxxxxxUV
  asl a
  asl a
  and #$0C
  ora temp            ;;xxxxUVxx
  sta temp            ;;QRSTUVxx
  lda tempEntry+6     ;;xxxxWXxx
  lsr a
  lsr a
  and #$03            ;;xxxxxxWX
  ora temp
  sta temp
  sta gameGenieDecode+3, y  ;;QRSTUVWX
  
  
  
  
  PrintString "$"
  lda gameGenieDecode+1, y
  sta temp
  PrintHexNum temp
  lda gameGenieDecode+2, y
  sta temp
  PrintHexNum temp
  lda gameGenieDecode+3, y
  sta temp
  PrintHexNum temp
  PrintString " = $"
  lda gameGenieDecode, y
  sta temp
  PrintHexNum temp
  rts


GameGenieGetOffset:
  lda cursorY
  sec
  sbc #$60
  sta temp     ;game genie 0,8,16,24,32
  lsr temp
  lda cursorX
  sec
  sbc #$40
  lsr a
  lsr a
  lsr a
  lsr a
  sta temp+1  ;char 0..7
  lda temp
  clc
  adc temp+1
  sta gameGenieOffset
  lda #$00
  sta gameGenieOffset+1
  rts
    
GameGenieNextChar:    
  jsr GameGenieGetOffset
  ldx gameGenieOffset
  
  lda gameGenie, x
  clc
  adc #$01
  sta gameGenie, x
  
  lda gameGenie, x
  cmp #$11
  bne GameGenieCharStore
  lda #$00
  sta gameGenie, x
  jmp GameGenieCharStore

GameGeniePrevChar:
  jsr GameGenieGetOffset
  ldx gameGenieOffset
  
  lda gameGenie, x
  sec
  sbc #$01
  sta gameGenie, x
 
  lda gameGenie, x
  cmp #$FF
  bne GameGenieCharStore
  lda #$10
  sta gameGenie, x
  jmp GameGenieCharStore
  
GameGenieCharStore:
  lda cursorY
  cmp #$60
  beq GameGenieCharStore0     ;game genie
  cmp #$70
  beq GameGenieCharStore1
  cmp #$80
  beq GameGenieCharStore2
  cmp #$90
  beq GameGenieCharStore3
  cmp #$A0
  beq GameGenieCharStore4

GameGenieCharStore0:
  SetCursorPos 11,9
  ldy #$0000
  jump jGameGeniePrint
  rts
GameGenieCharStore1:
  SetCursorPos 13,9
  ldy #$0008
  jump jGameGeniePrint
  rts
GameGenieCharStore2:
  SetCursorPos 15,9
  ldy #$0010
  jump jGameGeniePrint
  rts
GameGenieCharStore3:
  SetCursorPos 17,9
  ldy #$0018
  jump jGameGeniePrint
  rts
GameGenieCharStore4:
  SetCursorPos 19,9
  ldy #$0020
  jump jGameGeniePrint
  rts
  
  
  
GameGenieWriteCode:
  PrintString "GG-> "
  jump jGameGenieDecode
 ; PrintString "\n"
  
  lda gameGenie, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+1, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+2, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+3, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+4, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+5, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+6, y
  cmp #16
  beq GameGenieWriteCodeSkip
  lda gameGenie+7, y
  cmp #16
  beq GameGenieWriteCodeSkip
  jmp GameGenieWriteCodeGood

GameGenieWriteCodeSkip:
  PrintString " code unused"
  jmp GameGenieWriteCodeDone
GameGenieWriteCodeGood:

  lda gameGenieDecode, y    ;;data
  sta ggcode
  lda gameGenieDecode+1, y   ;bank
  sta ggcode+1
  lda gameGenieDecode+2, y   ;;high
  sta ggcode+2
  lda gameGenieDecode+3, y   ;;low
  sta ggcode+3

  lda #$00
  sta CONFIGWRITESRAMSIZE

  ;PrintString "$F0"
 ; lda ggcode+2
 ; sta errorCode
 ; PrintHexNum errorCode
 ; lda ggcode+3
 ; sta errorCode
 ; PrintHexNum errorCode


  ;PrintString "<=$"
  ;lda ggcode
  ;sta errorCode
  ;PrintHexNum errorCode
  
 ; jsr Delay5Sec

  lda ggcode+1  ;;GG addr = bbhhll
  and #$F0
  lsr a
  lsr a                  ;;bank index = bb >> 3  Fx->1E
  lsr a
  sta sourceLo  
;  PrintString " banknum="
;  PrintHexNum sourceLo
  lda #$00
  sta sourceHi
  ldx sourceLo
  lda gameBanks, x
  sta errorCode
  inx                  ;;;THIS IS WRONG?  SHOULD BE +$10?
  lda gameBanks, x
  sta errorCode+1
    
;  jsr Delay5Sec
  
  lda errorCode

 ; and #$20
 ; asl a
 ; ora errorCode
;  ora #$40       ;;make writeable
;  sta errorCode
  sta CONFIGWRITEBANK+$1E0  ;;put indexed bank into F0h reg
;  PrintString "banklo written"
;  PrintHexNum errorCode
  
;  jsr Delay5Sec
  
  lda errorCode+1
;  and #$20
;  asl a
;  ora errorCode+1
;  sta errorCode+1
  sta CONFIGWRITEBANK+$1F0  ;;put indexed bank into F0h reg
  
;  PrintString "bankhi written"
;  PrintHexNum errorCode+1
;  jsr Delay5Sec

  lda ggcode+3
  sta destLo
  lda ggcode+2
  sta destHi
  ldx destLo
  lda ggcode             ;;write GG data to F0hhll
  sta $F00000, x
  
  lda $F00000, x
  sta errorCode
  stx sourceLo
 ; PrintString "code written="
 ; PrintHexNum errorCode
  
 ; PrintString " addr"
 ; PrintHexNum sourceLo+1
 ; PrintHexNum sourceLo
  
;  jsr Delay5Sec
;  jsr Delay5Sec

  lda sramSizeByte
  sta CONFIGWRITESRAMSIZE
  lda gameBanks+$1E
  sta CONFIGWRITEBANK+$1E0  ;;put bank back
  lda gameBanks+$1F
  sta CONFIGWRITEBANK+$1F0  ;;put bank back
   
GameGenieWriteCodeDone:
  rts



Delay5Sec:
  ldx #$0AC
Delay5SecLoop
  wai
  dex
  cpx #$0000
  bne Delay5SecLoop
  rts


MemCheck:
  wai
  ClearLine 18
  ClearLine 19
  ClearLine 20
  ClearLine 21
  SetCursorPos 18, 1
  PrintString "SDRAM Check"
  
  stz errorCode
  stz temp
  stz temp+1
  stz temp+2
  lda #$00
  sta DMAWRITEBANK
  sta DMAWRITELO
  sta DMAWRITEHI
  SetCursorPos 19, 3
  PrintString "Write bank "
MemCheckWriteLoop:
  lda errorCode
  sta $21FF
  inc errorCode

  lda temp+2
  sta temp+3
  lda temp
  clc
  adc #$0F
  sta temp
  lda temp+1
  adc #$00
  sta temp+1
  lda temp+2
  adc #$00
  sta temp+2
  cmp temp+3
  beq MemCheckWriteLoopNext
  jsr MemCheckWriteUpdate
MemCheckWriteLoopNext:
  lda temp+2
  cmp #$FF
  bne MemCheckWriteLoop

  stz errorCode
  stz temp
  stz temp+1
  stz temp+2
  lda #$00
  sta DMAWRITEBANK
  sta DMAWRITELO
  sta DMAWRITEHI
  SetCursorPos 19, 3
  PrintString "Read bank  "
MemCheckReadLoop:
  lda $21FF
  sta temp+4
  cmp errorCode
  bne MemCheckError
  
  inc errorCode
  
  lda temp+2
  sta temp+3
  lda temp
  clc
  adc #$0F
  sta temp
  lda temp+1
  adc #$00
  sta temp+1
  lda temp+2
  adc #$00
  sta temp+2
  cmp temp+3
  beq MemCheckReadLoopNext
  jsr MemCheckReadUpdate
MemCheckReadLoopNext:
  lda temp+2
  cmp #$FF
  bne MemCheckReadLoop
  ClearLine 20
  SetCursorPos 20, 3
  PrintString "SDRAM Passed"
  rts

MemCheckError:
  ClearLine 20
  ClearLine 21
  ClearLine 22
  SetCursorPos 20, 3
  PrintString "ERROR: read="
  PrintHexNum temp+4
  PrintString " wanted="
  PrintHexNum errorCode
  PrintString "\n          at addr="
  PrintHexNum temp+2
  PrintHexNum temp+1
  PrintHexNum temp
  PrintString "\ntrying again:"
  
  PrintString "  "
  lda temp+2
  sta DMAWRITEBANK
  lda temp+1
  sta DMAWRITEHI
  lda temp+0
  sta DMAWRITELO
  lda $21FF
  sta temp+4
  PrintHexNum temp+4
  
  PrintString "  "
  lda temp+2
  sta DMAWRITEBANK
  lda temp+1
  sta DMAWRITEHI
  lda temp+0
  sta DMAWRITELO
  lda $21FF
  sta temp+4
  PrintHexNum temp+4

  PrintString "  "
  lda temp+2
  sta DMAWRITEBANK
  lda temp+1
  sta DMAWRITEHI
  lda temp+0
  sta DMAWRITELO
  lda $21FF
  sta temp+4
  PrintHexNum temp+4

  PrintString "  "
  lda temp+2
  sta DMAWRITEBANK
  lda temp+1
  sta DMAWRITEHI
  lda temp+0
  sta DMAWRITELO
  lda $21FF
  sta temp+4
  PrintHexNum temp+4
  rts

MemCheckWriteUpdate:
  SetCursorPos 19, 15
  PrintHexNum temp+2
  rts
  
MemCheckReadUpdate:
  SetCursorPos 19, 15
  PrintHexNum temp+2
  rts






ClearFindEntry:
  lda #' '
  sta findEntry
  sta findEntry+1
  sta findEntry+2
  sta findEntry+3
  sta findEntry+4
  sta findEntry+5
  sta findEntry+6
  sta findEntry+7
  rts





CopyROMInfo:
  lda $21FF  ;;D5
  sta errorCode
  and #%11101111   ;;mask off fast/slow
  sta gameROMMapper
  PrintString "\nMAP"
  PrintHexNum errorCode
  lda $21FF  ;;D6
  sta gameROMType
  PrintString " TYP"
  PrintHexNum gameROMType
  lda $21FF  ;;D7
;  sta gameROMSize  taken from file size
  sta errorCode
  PrintString " ROM"
  PrintHexNum errorCode
  lda $21FF  ;;D8
  sta saveSize
  PrintString " SRM"
  PrintHexNum saveSize
  
  ldy #$0024   ;;;36 bytes D9-FC
CopyROMInfoLoop:
  lda $21FF
  dey
  cpy #$0000
  bne CopyROMInfoLoop

  sta gameResetVector
  lda $21FF  ;;FD
  sta gameResetVector+1
  
  PrintString " RST"
  PrintHexNum gameResetVector+1
  PrintHexNum gameResetVector
  rts
  
  
  
  

CopyBanks:
  ldy #$0000
  lda [destLo], y
  sta CONFIGWRITEBANK+$010
  sta gameBanks+$01
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$030
  sta gameBanks+$03
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$050
  sta gameBanks+$05
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$070
  sta gameBanks+$07
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$090
  sta gameBanks+$09
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$0B0
  sta gameBanks+$0B
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$0D0
  sta gameBanks+$0D
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$0F0
  sta gameBanks+$0F
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$110
  sta gameBanks+$11
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$130
  sta gameBanks+$13
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$150
  sta gameBanks+$15
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$170
  sta gameBanks+$17
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$190
  sta gameBanks+$19
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$1B0
  sta gameBanks+$1B
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$1D0
  sta gameBanks+$1D
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$1F0
  sta gameBanks+$1F
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$000
  sta gameBanks+$00
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$020
  sta gameBanks+$02
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$040
  sta gameBanks+$04
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$060
  sta gameBanks+$06
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$080
  sta gameBanks+$08
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$0A0
  sta gameBanks+$0A
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$0C0
  sta gameBanks+$0C
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$0E0
  sta gameBanks+$0E
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$100
  sta gameBanks+$10
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$120
  sta gameBanks+$12
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$140
  sta gameBanks+$14
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$160
  sta gameBanks+$16
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$180
  sta gameBanks+$18
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$1A0
  sta gameBanks+$1A
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$1C0
  sta gameBanks+$1C
  iny
  lda [destLo], y
  sta CONFIGWRITEBANK+$1E0
  sta gameBanks+$1E
  rts







PrintBanks:
  PrintString "\n0 1 2 3 4 5 6 7 8 9 A B C D E F\n"
  ldx #$0001
  ldy #$0010
PrintBanks1:
  lda gameBanks, x
  sta errorCode
  PrintHexNum errorCode
  inx
  inx
  dey
  bne PrintBanks1
  PrintString "        "

  ldx #$0008
  ldy #$0004
PrintBanks2:
  lda gameBanks, x
  sta errorCode
  PrintHexNum errorCode
  inx
  inx
  dey
  bne PrintBanks2
  PrintString "        "

  ldx #$0018
  ldy #$0004
PrintBanks3:
  lda gameBanks, x
  sta errorCode
  PrintHexNum errorCode
  inx
  inx
  dey
  bne PrintBanks3
rts
  


LogScreen:
  lda #'T'
  sta exMatch1
  sta exMatch1+1
  sta exMatch1+2
  sta exMatch1+3
  lda #'X'
  sta exMatch2
  sta exMatch2+1
  sta exMatch2+2
  sta exMatch2+3
  lda #'T'
  sta exMatch3
  sta exMatch3+1
  sta exMatch3+2
  sta exMatch3+3

  lda baseDirCluster
  sta sourceCluster
  lda baseDirCluster+1
  sta sourceCluster+1
  lda baseDirCluster+2
  sta sourceCluster+2
  lda baseDirCluster+3
  sta sourceCluster+3


  jump jClearFindEntry
  lda #'L'
  sta findEntry
  lda #'O'
  sta findEntry+1
  lda #'G'
  sta findEntry+2

  jump jCardLoadDir    ; powerpak dir
  
  jump jDirFindEntry        ;;get first cluster
  lda tempEntry+$1C
  sta sourceCluster
  lda tempEntry+$1D
  sta sourceCluster+1
  lda tempEntry+$1E
  sta sourceCluster+2
  lda tempEntry+$1F
  sta sourceCluster+3

  lda #<TextBuffer
  sta sourceLo
  lda #>TextBuffer
  sta sourceHi
  
  lda #kSourceWRAM
  sta sourceType

  jump jCardWriteFile
  rts


SWCHeaderCheck:
  lda sectorBuffer1+$0008
  cmp #$AA
  bne SWCHeaderNotFound
  lda sectorBuffer1+$0009
  cmp #$BB
  bne SWCHeaderNotFound
  lda sectorBuffer1+$000A
  cmp #$04
  bne SWCHeaderNotFound
SWCHeaderFound:
  PrintString "SWC Header"
  lda #$01
  sta headerType
SWCHeaderNotFound:   
  rts
  
GD3HeaderCheck:
  lda sectorBuffer1+$0000    ;; check for "GAME"
  cmp #$47
  bne GD3HeaderNotFound
  lda sectorBuffer1+$0001
  cmp #$41
  bne GD3HeaderNotFound
  lda sectorBuffer1+$0002
  cmp #$4D
  bne GD3HeaderNotFound
  lda sectorBuffer1+$0003
  cmp #$45
  bne GD3HeaderNotFound
GD3HeaderFound:
  PrintString "GD3 Header"
  lda #$02
  sta headerType
GD3HeaderNotFound:   
  rts
  

  
.INCLUDE "Strings.asm"


.ENDS


;.BANK 2 SLOT 0
;.ORG 0
;.SECTION "FPGA"
;TopLevel:
;.INCBIN "toplevel.bit"
;.ENDS
