
  .inesprg 4 ;04 x 16k prg bank   64KB = 4x16KB  8x8KB
  .ineschr 0	;no chr bank
  .inesmir 1	; VERTICAL mirroring
  .inesmap 2	;uxrom

  .include "variables.h"

  .bank 0
  .org    $8000
  .incbin "loadertop.bit"   ;;BOOT FPGA CONFIG FILE  xc2s30 = 44KB of 48KB     fpga = 42096 bytes
  
    
    
  .bank 6
  .org $8000
  .incbin "powerpak.nes"   ;;GRAPHICS FILE 4KB
  .incbin "powerpak.nes"   ;;GRAPHICS FILE 4KB
    
  .bank 7   ;;LAST BANK OF FLASH ROM 8KB
  .org $E000


;16KB  8KB  banks
;0     0/1 - fpga config 16KB
;1     2/3 - fpga config 16KB
;2     4/5 - fpga config 12KB
;3     6/7 - chr in first 8KB, boot code in last 8KB

  
  
;--------------------Set Up Program--------------------:
;------------------------------------------------------:


MESSAGETABLE .dw PP,NOCARD,NOTREADY,FORMAT,RERR,WERR,NOTFOUND,LOADDIR,LOADRAM,GG,WEBSITE,STARTG,LOADGAME,HEADER,DUDE,SAVERAM,CFBUSY
PP:           .db "            PowerPak            "
NOCARD:       .db "   Card Error - No Card Found   "
NOTREADY:     .db "      Card Error - Not Ready    "
FORMAT:       .db "    Bad Format - Use FAT16/FAT32"
RERR:         .db "      Fatal Card Read Error     "
WERR:         .db "     Fatal Card Write Error     "
NOTFOUND:     .db "         File Not Found         "
LOADDIR:      .db "      Loading Directory...      "
LOADRAM:      .db "        Load Battery RAM        "
GG:           .db "        Game Genie Codes        "
WEBSITE:      .db "        www.retrousb.com        "
STARTG:       .db "        Start Game              "
LOADGAME:     .db "         Loading Game...        "
HEADER:       .db "         Bad iNES Header        "
DUDE:         .db "       Say NO to DiskDude       "
SAVERAM:      .db "      Saving Battery RAM...     "
CFBUSY:       .db "           Card Busy            "
LOGO1:        .db $80, $81, $82, $83, $84, $85, $86, $87
LOGO2:        .db $90, $91, $92, $93, $94, $95, $96, $97
LOGO3:        .db $A0, $A1, $A2, $A3, $A4, $A5, $A6, $A7
LOGO4:        .db $B0, $B1, $B2, $B3, $B4, $B5, $B6, $B7
LOGO5:        .db $C0, $C1, $C2, $C3, $C4, $C5, $C6, $C7
LOGO6:        .db $D0, $D1, $D2, $D3, $D4, $D5, $D6, $D7
LOGO7:        .db $E0, $E1, $E2, $E3, $E4, $E5, $E6, $E7
LOGO8:        .db $F0, $F1, $F2, $F3, $F4, $F5, $F6, $F7

IRQ:
  rti
  
  
  
NMI:
  ;backup registers
  php     ;push status
  pha     ;push a
  tya
  pha     ;push y
  txa
  pha     ;push x  

	lda #%00000110           ;graphics off
  sta $2001
    
  ;do graphics updates
  jsr PrintLine
  

MoveSprite:
  ;move sprite 0
  lda $2002
  lda #$3F
  sta $2003
  lda #$10
  sta $2003
  lda cursorY      ; initialize Sprite 0 = cursor
  sec
  sbc #$01  
  sta $2004        ; Y coordinate
  lda #$10
  sta $2004        ; Pattern number
  lda #$03
  sta $2004        ; color/attributes  CHANGE ME cursor color
  lda cursorX
  sta $2004        ; X coordinate  

    
SetScroll:    
	lda #%10001000           ;nmi on  
  sta $2000
	lda #%00011110           ;4 sprites on, 3 background on
  sta $2001  
  lda $2002
  lda #$00
  sta $2006
  sta $2006
  sta $2005  ;scroll x
  lda scrollY
  sta $2005
  ;all nmi graphics done by here;
  inc frameCounter
  ;restore registers
  pla
  tax   ;pop x
  pla
  tay   ;pop y
  pla   ;pop a
  plp
  rti




DoFrame:  
  jsr JoystickRead
  jsr $0404             ;go to module controller handler vector

CheckCursor:
  ;check cursor counter, no scroll if counter=0
  lda cursorYCounter
  cmp #$00
  beq CursorDone
  dec cursorYCounter  
  ;scroll = scroll + scrollUp - scrollDown
DoCursorScroll:
  lda cursorY
  sec
  sbc cursorYUp
  clc
  adc cursorYDown
  sta cursorY
CursorDone:
  
    
    
CheckYScroll:
  ;check scroll counter, no scroll if counter=0
  lda scrollYCounter
  beq DoYScrollDone
  dec scrollYCounter  
  ;scroll = scroll - scrollUp + scrollDown
DoYScroll:
  lda scrollY
  sec
  sbc scrollYUp
  clc
  adc scrollYDown
  sta scrollY
	cmp #$F0 ; 240
	bcc	DoYScrollDone  ; scrollY < 240, no underflow/overflow
DoYScrollOverflow:
	cmp	#$F8	; 248
	bcs	DoYScrollUnderflow  ; scrollY > 248, no overflow
	sec
	sbc	#$F0	; scroll = scroll - 240
	sta	scrollY
	jmp	DoYScrollDone
DoYScrollUnderflow:
	lda scrollY
	sec
	sbc	#$10
	sta	scrollY
DoYScrollDone:
  
  rts



;---------------------------------;


ScrollUp:
  sec
  lda selectedEntry
  sbc #$01
  sta selectedEntry
  lda selectedEntry+1              ;go to prev entry
  sbc #$00
  sta selectedEntry+1

  lda selectedEntry
  cmp #$FF
  bne ScrollUpCheckTop
  lda selectedEntry+1
  cmp #$FF
  bne ScrollUpCheckTop             ;check if selectedEntry = FFFF (underflow)
  
  lda filesInDir
  sta selectedEntry
  lda filesInDir+1
  sta selectedEntry+1              ;underflow, reset selectedEntry = filesInDir-1
  sec
  lda selectedEntry
  sbc #$01
  sta selectedEntry
  lda selectedEntry+1              
  sbc #$00
  sta selectedEntry+1  

  lda filesInDir+1
  cmp #$00
  bne ScrollUpCheckTop
  lda filesInDir
  cmp #$1d
  bcs ScrollUpCheckTop              ; check if filesInDir > 28
  
  lda filesInDir
  jsr ASLA3                         ;multiply by 8 for sprite height
  clc
  adc #$08
  sta cursorY                       ; put cursor at bottom of list
  jmp ScrollUpCheckMiddle

ScrollUpCheckTop:
  lda cursorY
  cmp #$08
  bne ScrollUpCheckMiddle           ;check if cursor at top
  
  lda speedCounter
  sta scrollYCounter                ;cursor at top, scroll background, leave cursor
  lda speedScroll
  sta scrollYUp
  lda #$00
  sta scrollYDown
  
  lda scrollY
  jsr LSRA3
  sta printY                       
  jsr DirPrintEntry
  
  jmp ScrollUpDone
    
ScrollUpCheckMiddle:    
  lda speedCounter
  sta cursorYCounter
  lda speedScroll
  sta cursorYUp
  lda #$00
  sta cursorYDown

ScrollUpDone:
  rts
  
  



ScrollDown:
  clc
  lda selectedEntry
  adc #$01
  sta selectedEntry
  lda selectedEntry+1              ;go to next entry
  adc #$00
  sta selectedEntry+1
  
  lda selectedEntry
  cmp filesInDir
  bne ScrollDownCheckBottom
  lda selectedEntry+1
  cmp filesInDir+1
  bne ScrollDownCheckBottom        ;check if selectedEntry = filesInDir
  
  lda #$00
  sta selectedEntry
  sta selectedEntry+1              ;overflow, reset to 0
  
  lda filesInDir+1
  cmp #$00
  bne ScrollDownCheckBottom
  lda filesInDir
  cmp #$1d
  bcs ScrollDownCheckBottom         ; check if filesInDir > 28
  
  lda #$00
  sta cursorY                       ; put cursor at top of screen
  jmp ScrollDownCheckMiddle
  
ScrollDownCheckBottom:
  lda cursorY
  cmp #$E0   ;= pixel 224
  bne ScrollDownCheckMiddle         ; check if cursor at bottom
  
  lda speedCounter                         ;cursor at bottom, move background, leave cursor
  sta scrollYCounter                ;set scrollYCounter (8 or 4)
  lda speedScroll
  sta scrollYDown                   ;set scrollYDown to speed (1 or 2)
  lda #$00
  sta scrollYUp
  
  lda scrollY
  jsr LSRA3                       ; a = scroll div 8
  sec   
  sbc #$01                         ; a = a - 1
  cmp #$FF
  bne ScrollDownCheckBottomDone
  lda #$1D                         ; if a = ff, a = 29
  
ScrollDownCheckBottomDone  
  sta printY                     
  jsr DirPrintEntry
  
  jmp ScrollDownDone
    
ScrollDownCheckMiddle:
  lda speedCounter
  sta cursorYCounter
  lda speedScroll
  sta cursorYDown
  lda #$00
  sta cursorYUp
    
ScrollDownDone:
  rts 





;--------------------Main Code-------------------------:
;------------------------------------------------------:

RESET:
  cld
  sei
  
  ;turn rendering OFF
  lda #$00  
  sta $2000     ;7 vblank int, 4 screen addr, 3 sprite addr, 2 vertical wr, 10 name table addr  
  sta $2001     ;765 bg color, 4 sprites on, 3 screen on, 2 sprite mask, 1 image mask


  lda #$40
  sta $4017  ;disable frame IRQ
  
  ldx #$FF   ;reset stack pointer
  txs
  
  jmp ClearRam
ClearRamReturn:    
  lda #$60
  sta $0400    ;add vectors for dummy module, $60 = rts
  sta $0404


  ;load from game genie address
  lda $4208
  cmp #$01
  beq ResetFPGAConfigured     ;;fpga was configured and battery must be saved
  jmp ResetFPGANotConfigured  ;;fpga wasnt configured, or battery not saved
  
ResetFPGAConfigured:
  ;  fpga is configured, poweron = 0
  lda #$00
  sta powerOn
  jmp ResetCopyFPGA
  
ResetFPGANotConfigured:
  ;  fpga isnt configured, poweron = 1
  lda #$01
  sta powerOn
  jmp ResetCopyFPGA

ResetCopyFPGA:
  ;copy fpga data from rom $8000... to fpga
  jsr FPGACopyRom
  
  jsr WaitVBlank
  jsr WaitVBlank
  jsr WaitVBlank

  lda #$40
  sta PRGBANK  ;enable chr ram writing

  ;copy chr tiles from rom to chrram  8KB to ppu $0000
  lda #$00
  sta sourceLo
  sta destLo
  sta destHi
  lda #$80
  sta sourceHi
  lda #$20      ;32*256 = 8KB
  sta source256
  jsr CopyChrRam

  lda #$00
  sta PRGBANK  ;disable chr ram writing

  jsr ClearNameTable
  
  ;               00 TEXT CART        01  CF         10  RED         11  CART/RED
  ;               blk dgr gry wht   blk ye gry wht  blk lrd rd drd   blk lrd gry rd
  ;IMAGE PALETTE    3E 00 10 30      3E 28 10 30     3E 26 16 17      3E 17 10 16

	;Write image then sprite palettes 32 bytes
  lda $2002         ;clear 2006 latch
  lda #$3F
  sta $2006
  lda #$00
  sta $2006
  ldx #$02
WritePalette:
  lda #$3E
  sta $2007
  lda #$00
  sta $2007
  lda #$10
  sta $2007
  lda #$30
  sta $2007

  lda #$3E
  sta $2007
  lda #$28
  sta $2007
  lda #$2D
  sta $2007
  lda #$30
  sta $2007

  lda #$3E
  sta $2007
  lda #$26
  sta $2007
  lda #$26
  sta $2007
  lda #$26
  sta $2007
  
  lda #$3E
  sta $2007
  lda #$26
  sta $2007
  lda #$10
  sta $2007
  lda #$16
  sta $2007      
  dex
  bne WritePalette

    
  ;put intro screen in name table
  lda #messagePP           ;load message = POWERPAK
  sta temp
  jsr StrCopy
  lda #$05
  sta printY
  jsr PrintLine
      
  lda #$F8
  sta cursorX
  sta cursorY
  jsr RenderingOn
 
                        
  
  nop
  nop
  nop
  nop
  nop
  nop
  ;nop
  ;nop
  ;nop
  jmp NewCFBoot    ;;new card booting, skips to CardReady when done
  
CardBootLoop:
  ;read status byte   all good = 01010000 = $50
  ;                   no card = 11111111 = $FF
  lda CARDSTATUS           ;card status read
  cmp #$FF                 ;compare to 11111111
  bne CheckCardReset
  lda #messageNOCARD       ;load message = no card
  sta temp
  jsr StrCopy
  lda #$07                 ; message position
  sta printY
  jmp ForeverLoop          ;stop everything
  
  
  
CheckCardReset:
  lda #$01	; directly loads the Accumulator with 1
  sta $4016	; stores the Accumulator (1) into $4016
  lda #$00	; directly loads the Accumulator with 0
  sta $4016	; stores the Accumulator (0) into $4016
  
  lda $4016	; loads the info from the joystick
  and #$01	; ||
  cmp #$00
  beq CardInserted         ;if no button is pressed, no card reset
CardReset:                 ;if A is pressed, do card reset
  lda #%00000110           ;do card sw reset
  sta CARDDEVICE           ;in device ctl reg
  nop
  nop
  nop
  nop
  nop
  lda #%00000010
  sta CARDDEVICE           ;clear reset
  nop
  nop
  jmp CardBootLoop


CardInserted:
  lda CARDSTATUS           ;card status read
  sta sourceSector         ;store somewhere unused
  and #%10000000
  cmp #%10000000           ;check busy bit
  bne CardNotBusy
  
CardBusy:
  lda #messageCARDBUSY     ;load message = card busy
  sta temp
  jsr StrCopy
  lda #$1A                 
  sta printY
  
  lda sourceSector         ;card status read
  sta temp
  jsr Byte2Str  
  
  lda sourceSector+1
  clc
  adc #$01
  sta sourceSector+1
  beq CardReset
  
  jmp CardBootLoop
  
  
  
  
CardNotBusy:
  lda CARDSTATUS           ;card status read
  sta sourceSector
  and #%01010000
  cmp #%01010000           ;check ready bit
  beq CardReady

CardNotReady:
  lda #messageNOTREADY     ;load message = card not ready
  sta temp
  jsr StrCopy
  lda #$1A                 
  sta printY
  
  lda sourceSector           ;card status read
  sta temp
  jsr Byte2Str  
  jmp CardInserted
   
   
   
   
CardReady:
  jmp CheckCardFormat





  .org $E642
GetVolumeID:  
  lda #$00
  sta destLo
  lda #$02
  sta destHi  
  jsr CardReadSector       ;read FAT16/FAT32 Volume ID sector  (partition boot record)

  
  lda $020D                ;copy FAT16/FAT32 sectorsPerCluster from offset 13
  sta sectorsPerCluster
  
  lda $020E                ;copy FAT16/FAT32 reservedSectors from offset 14
  sta reservedSectors
  lda $020F
  sta reservedSectors+1
        
  ldx #$00
CardCopySectorsPerFat:     ;copy FAT32 sectorsPerFat from offset 36
  lda $0224, x
  sta sectorsPerFat, x
  inx
  cpx #$04
  bne CardCopySectorsPerFat
    
  ldx #$00
CardCopyRootDirCluster32:    ;copy FAT32 rootDirCluster from offset 44
  lda $022C, x
  sta rootDirCluster, x
  inx
  cpx #$04
  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:
  lda #$00                  ;when FAT16, rootDirCluster = 0000    root dir is not in cluster nums
  sta rootDirCluster
  sta rootDirCluster+1
  sta rootDirCluster+2
  sta rootDirCluster+3
          
                               
  lda $0216
  sta sectorsPerFat           ;FAT16 copy sectorsPerFat from offset 22
  lda $0217
  sta sectorsPerFat+1
  lda #$00
  sta sectorsPerFat+2
  sta sectorsPerFat+3         ;;FAT16 sectors per fat = 16 bits, in different place than FAT32
                                                                                                                                                
  

CardCopyRootDirEntries16:     ;copy max root directory entries from offset 17
  lda $0211
  sta fat16RootSectors
  lda $0212
  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
    
  jsr CardLoadDir        ; 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
  
  jsr DirFindEntryNew         ;"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

    
  ;if poweron = 1  
  ;  fpga isnt configured, go to i.map
  ;if poweron = 0
  ;  fpga is configured, go to q.map
    
  lda powerOn
  beq LoadModuleQ
LoadModuleI:
  lda #'I'
  sta findEntry  
  jmp LoaderLoadModuleDone
LoadModuleQ:
  lda #'Q'
  sta findEntry  
  jmp LoaderLoadModuleDone
  
  
  
LoaderLoadModuleDone:  

  lda #' '
  sta findEntry+1
  sta findEntry+2
  sta findEntry+3
  sta findEntry+4
  sta findEntry+5
  sta findEntry+6
  sta findEntry+7
  jmp CardLoadModule      ;load intro module


Forever:
  jsr RenderingOn
ForeverLoop:  
  ;wait for nmi
  lda frameCounter
  cmp prevFrameCounter
  beq ForeverLoop
  jsr DoFrame
  lda frameCounter
  sta prevFrameCounter
  jmp ForeverLoop
  


;----------------------------;

  
WaitVBlank:
  lda $2002 
  bpl WaitVBlank
  rts


;---------------------------:


JoystickRead:		;**-Get Joystick Status**

  lda #$01	; directly loads the Accumulator with 1
  sta $4016	; stores the Accumulator (1) into $4016
  lda #$00	; directly loads the Accumulator with 0
  sta $4016	; stores the Accumulator (0) into $4016

  ldx #$08	; loads 8 so it can loop for each byte

Joyloop:
  lda $4016	; loads the info from the joystick
  and #$03	; ||
  cmp #$01	; narrows down the data
  rol $02	; rotates info into memory...
  dex 		; decrements X 
  bne Joyloop	; loops again if not 0 

  lda $02
  sta joystick

  rts 		; returns to main routine


  

;-------------------------;  
ClearNameTable:
  lda $2002
  lda #$20
  sta $2006
  lda #$00
  sta $2006
  ldx #$00
  ldy #$08
ClearNameTableLoop: 
  sta $2007
  dex
  bne ClearNameTableLoop 
  dey   ;LAST CHANGE
  bne ClearNameTableLoop
  rts


ClearSpriteRam:
  ;setup sprite ram    
  lda $2002
  lda #$00
  sta $2003
  sta $2003
  lda #$ff
  ldx #$00
ClearSpriteRamLoop: 
  sta $2004
  inx 
  bne ClearSpriteRamLoop 
  rts


ClearLine:
  ldy #$00
  lda #' '
ClearLineLoop:
  sta printString, y
  iny
  cpy #$20
  bne ClearLineLoop
  rts

ClearFindEntry:
  ldx #$08
  lda #' '
ClearFindEntryLoop
  sta findEntry, x
  dex
  cpx #$00
  bne ClearFindEntryLoop
  rts
  

PrintLine:
  lda #$00
  sta printAddrLo
  sta printAddrHi
	ldx	#$03
	lda	printY
	sta printAddrHi       ; x256
ShiftLine:  						;shift right 3x to mult x32
  clc
	lsr printAddrHi
	ror printAddrLo
	dex
	bne	ShiftLine

	lda printAddrHi
	clc										;add printAddr + $2000 (name table address)
	adc #$20
	sta printAddrHi
  
  lda $2002             ;clear latch
	lda	printAddrHi       ;starting address to ppu
	sta	$2006
	lda	printAddrLo
	sta	$2006
	
	ldx	#$00
PrintChar:
	lda	printString, x
	sta	$2007
	inx
	cpx #$20
  bne	PrintChar
			
	rts





LoadLogo:
  lda #$03
  sta printY
  jsr ClearLine
  ldx #$00

LoadLogoLineLoop:
  ldy #$00
  
LoadLogoCharLoop:  
  lda LOGO1, x
  sta printString+12, y
  inx
  iny
  cpy #$08
  bne LoadLogoCharLoop
  
  stx temp
  inc printY
  jsr PrintLine
  ldx temp
  lda printY
  cmp #$0B
  bne LoadLogoLineLoop
  
  ;;copy attributes
  lda $2002             ;clear latch
	lda	#$23       ;starting address to ppu
	sta	$2006
	lda	#$C0       ;$23C0 = attribute table
	sta	$2006  
  
  lda #$55
  ldx #$00
LoadLogoPaletteLoop1:   ;;load yellow area  first 8 rows
  sta $2007
  inx
  cpx #$10
  bne LoadLogoPaletteLoop1

  lda #$F0              ;;load left side cart area  
  sta $2007
  sta $2007
  sta $2007
  sta $2007

  lda #$FD             ;;load right side cart area
  sta $2007
  sta $2007
  sta $2007
  sta $2007
  
  
  
  
  rts
  
  
  
  
  
  
;------------------------;

CopyChrRam:
  lda #$03  ;16KB bank 3, 8KB bank 6
  sta MAPPERWR

  lda $2002
  lda destHi
  sta $2006
  lda destLo
  sta $2006
  ldy #$00          ;256 byte counter
  ldx source256    ;block counter
CopyChrRamLoop:
  lda [sourceLo], y
  sta $2007
  iny
  bne CopyChrRamLoop
  inc sourceHi
  dex
  bne CopyChrRamLoop
  rts
 
;-------------------------;

StrCopy:
  asl temp
  ldx temp
  lda MESSAGETABLE, x
  sta sourceStrLo
  lda MESSAGETABLE+1, x
  sta sourceStrHi
  jsr ClearLine
  ldy #$00
StrCopyLoop:
  lda [sourceStrLo], y
  sta printString, y      ;copy 32 text chars
  iny
  cpy #$20
  bne StrCopyLoop

;  ldy #$00  
;  lda #' '
;  jsr StrCopyBlankLoop
;  ldy #$18
;  jsr StrCopyBlankLoop
  rts
  
  
  
;StrCopyBlankLoop:
;  ldx #$08
;StrCopyBlankLoop1:  
;  sta printString, y        ;blank 8 chars
;  iny
;  dex
;  bne StrCopyBlankLoop1
;  rts
 
  
;----------------------------;
  
MemCopy:
  ldy #$00          ;256 byte counter
  ldx source256    ;block counter
MemCopyLoop:
  lda [sourceLo], y
  sta [destLo], y
  iny
  bne MemCopyLoop
  inc sourceHi
  inc destHi
  dex
  bne MemCopyLoop
  rts 

;------------------------------;  
Long2Str:
  lda temp+3
  and #$F0
  lsr a
  lsr a
  lsr a
  lsr a
  clc
  adc #$30
  sta printString+6
  cmp #$3A
  bcc Long2Str2
  clc
  lda printString+6
  adc #$07
  sta printString+6
Long2Str2:  
  lda temp+3
  and #$0F
  clc
  adc #$30
  sta printString+7
  cmp #$3A
  bcc Long2Str3
  clc
  lda printString+7
  adc #$07
  sta printString+7
Long2Str3:
  lda temp+2
  and #$F0
  lsr a
  lsr a
  lsr a
  lsr a
  clc
  adc #$30
  sta printString+4
  cmp #$3A
  bcc Long2Str4
  clc
  lda printString+4
  adc #$07
  sta printString+4
Long2Str4:  
  lda temp+2
  and #$0F
  clc
  adc #$30
  sta printString+5
  cmp #$3A
  bcc Short2Str
  clc
  lda printString+5
  adc #$07
  sta printString+5
Short2Str:
  lda temp+1
  and #$F0
  lsr a
  lsr a
  lsr a
  lsr a
  clc
  adc #$30
  sta printString+2
  cmp #$3A
  bcc Short2Str2
  clc
  lda printString+2
  adc #$07
  sta printString+2
Short2Str2:
  lda temp+1
  and #$0F
  clc
  adc #$30
  sta printString+3
  cmp #$3A
  bcc Byte2Str
  clc
  lda printString+3
  adc #$07
  sta printString+3
Byte2Str:  
  lda temp
  and #$F0
  lsr a
  lsr a
  lsr a
  lsr a
  clc
  adc #$30
  sta printString+0
  cmp #$3A
  bcc Byte2Str2
  clc
  lda printString+0
  adc #$07
  sta printString+0
Byte2Str2:
  lda temp
  and #$0F
  clc
  adc #$30
  sta printString+1  
  cmp #$3A
  bcc Byte2Str3
  clc
  lda printString+1
  adc #$07
  sta printString+1
Byte2Str3:
  rts

   
;----------------------------;
GameGenieEncodeBad:
  lda #$00
  sta gameGenieCodes
  sta gameGenieCodes+1
  sta gameGenieCodes+2
  sta gameGenieCodes+3
  sta gameGenieCodes+4
  sta gameGenieCodes+5
  sta gameGenieCodes+6
  sta gameGenieCodes+7
  rts

GameGenieAddressEncode:
  ;ADDRESS  LO/HI
  lda gameGenie+3, x       ;n3 & 8
  and #$08
  sta gameGenieCodes
  lda gameGenie+4, x       ;n4 & 7
  and #$07
  ora gameGenieCodes
  sta gameGenieCodes
  lda gameGenie+1, x       ;n1 & 8 << 4
  and #$08
  jsr ASLA4
  ora gameGenieCodes
  sta gameGenieCodes
  lda gameGenie+2, x       ;n2 & 7 << 4
  and #$07
  jsr ASLA4
  ora gameGenieCodes
  sta gameGenieCodes
  
  
  lda gameGenie+3, x       ;n3 & 7 << 4
  and #$07
  jsr ASLA4
  sta gameGenieCodes+1
  lda gameGenie+5, x       ;n5 & 7
  and #$07
  ora gameGenieCodes+1
  sta gameGenieCodes+1
  lda gameGenie+4, x       ;n4 & 8
  and #$08
  ora gameGenieCodes+1
  sta gameGenieCodes+1
  
  lda gameGenieCodes+1  ;;enable a15=1
  ora #$80
  sta gameGenieCodes+1
  rts  

GameGenieEncodeBadJump:
  jmp GameGenieEncodeBad

GameGenieEncode:
  lda temp
  asl a
  asl a
  asl a
  sta temp
  ldx temp          ; x = 0/8/16/24/32, beginning of code
  
  lda gameGenie+0, x
  cmp #$10   ;'_'
  beq GameGenieEncodeBadJump
  lda gameGenie+1, x
  cmp #$10   ;'_'
  beq GameGenieEncodeBadJump
  lda gameGenie+2, x
  cmp #$10   ;'_'
  beq GameGenieEncodeBadJump
  lda gameGenie+3, x
  cmp #$10   ;'_'
  beq GameGenieEncodeBadJump
  lda gameGenie+4, x
  cmp #$10   ;'_'
  beq GameGenieEncodeBadJump
  lda gameGenie+5, x
  cmp #$10   ;'_'
  beq GameGenieEncodeBadJump  
  
  lda gameGenie+7, x
  cmp #$10   ;'_'
  beq GameGenie6Encode
  jmp GameGenie8Encode
                        ;                               0      1     2     3       4
GameGenie6Encode:       ;x=source  y=dest    codes = addrlo/addrhi/data/compare/enable8
  jsr GameGenieAddressEncode
  ;DATA
  lda gameGenie+1, x       ;n1 & 7 << 4
  and #$07
  jsr ASLA4
  sta gameGenieCodes+2
  lda gameGenie+0, x       ;n0 & 8 << 4
  and #$08
  jsr ASLA4
  ora gameGenieCodes+2
  sta gameGenieCodes+2
  lda gameGenie+0, x       ;n0 & 7
  and #$07
  ora gameGenieCodes+2
  sta gameGenieCodes+2
  lda gameGenie+5, x       ;n5 & 8
  and #$08
  ora gameGenieCodes+2
  sta gameGenieCodes+2

  lda #$00
  sta gameGenieCodes+3
  sta gameGenieCodes+4
  rts

GameGenie8Encode:       ;x=source  y=dest    codes = addrlo/addrhi/data/compare/enable8
  jsr GameGenieAddressEncode
  lda #$FF
  sta gameGenieCodes+4
  ;DATA
  lda gameGenie+1, x       ;n1 & 7 << 4
  and #$07
  jsr ASLA4
  sta gameGenieCodes+2
  lda gameGenie+0, x       ;n0 & 8 << 4
  and #$08
  jsr ASLA4
  ora gameGenieCodes+2
  sta gameGenieCodes+2
  lda gameGenie+0, x       ;n0 & 7
  and #$07
  ora gameGenieCodes+2
  sta gameGenieCodes+2
  lda gameGenie+7, x       ;n7 & 8
  and #$08
  ora gameGenieCodes+2
  sta gameGenieCodes+2

  ;COMPARE
  lda gameGenie+7, x       ;n7 & 7 << 4
  and #$07
  jsr ASLA4
  sta gameGenieCodes+3
  lda gameGenie+6, x       ;n6 & 8 << 4
  and #$08
  jsr ASLA4
  ora gameGenieCodes+3
  sta gameGenieCodes+3
  lda gameGenie+6, x       ;n6 & 7
  and #$07
  ora gameGenieCodes+3
  sta gameGenieCodes+3
  lda gameGenie+5, x       ;n5 & 8
  and #$08
  ora gameGenieCodes+3
  sta gameGenieCodes+3

  rts


 

ASLA4:
  asl a
  asl a
  asl a
  asl a
  rts

ASLA3:
  asl a
  asl a
  asl a
  rts

LSRA3:
  lsr a
  lsr a
  lsr a
  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
 
  
  ;;FAT32 all done 
  ;lda fat32Enabled
  ;cmp #$01
  ;beq ClusterToLBADone
    
  ;;;FIXME FAT16 add fat16RootSectors    already included in clusterBeginLBA?
      
ClusterToLBADone:
  rts


;-------------------------;


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 #$02
  sta destHi
  lda #$00
  sta destLo
  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
  
  ;next cluster = [sector], offset
  lda #$00
  sta sourceLo
  
  lda #$02
  adc sourceCluster+1       ;sourceHi = 2 or 3 for which 256 byte block too look in
  sta sourceHi
  
  ldy sourceCluster
  ldx #$00
NextClusterLoop:  
  lda [sourceLo], y
  sta sourceCluster, x
  iny
  inx
  cpx #$04
  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



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
  jsr NextCluster                      ;get cluster num into sourceCluster
  jsr ClusterToLBA                     ;get sector num into sourceSector
  rts
  

;----------------------------;  

CardWaitNotBusy:           ;wait for not busy
  lda CARDSTATUS           ;card status read
  and #%10000000
  cmp #%10000000           ;check busy bit
  beq CardWaitNotBusy
  rts

CardWaitDataReq:           ;wait for not busy, ready, datareq, no error
  lda CARDSTATUS
  and #%01011000
  cmp #%01011000
  bne CardWaitDataReq
  rts

CardCheckError:
  lda CARDSTATUS           ; get card status, check for general error
  and #%00000001
  cmp #%00000001
  beq CardSectorError
  rts  
  
  
CardSectorError:
  lda #messageREADERR
  sta temp
  jsr StrCopy
  lda #$07                 ;message position
  sta printY  
  lda CARDERROR            ;card error read
  sta temp
  jsr Byte2Str
  jmp Forever              ;display message, stop everything


CardLoadLBA:
  lda #$01
  sta CARDSECTORCOUNT
  lda sourceSector
  sta CARDLBA0
  lda sourceSector+1
  sta CARDLBA1
  lda sourceSector+2
  sta CARDLBA2
  lda sourceSector+3        ;load lba number
  and #%00001111
  ora #%11100000
  sta CARDLBA3
  rts


CardReadSector:
  jsr CardCheckError
  jsr CardWaitNotBusy
  jsr CardLoadLBA
  jsr CardCheckError


  lda #$20
  sta CARDCOMMAND           ;send card read sector command
  nop
  nop

  jsr CardCheckError
  jsr CardWaitDataReq
  
  lda #$00
  sta sourceBytes
  lda #$02
  sta source256
  jsr CardReadBytes
  
  jsr CardCheckError
  
CardReadSectorDone:
  rts  
  
  
  
  
  
CardReadBytes:         ;read source256*sourceBytes bytes into ram
  ldx source256
  ldy sourceBytes
CardReadBytesLoop:
  lda CARDDATAREAD
  sta [destLo], y
  iny
  bne CardReadBytesLoop
  inc destHi
  dex
  bne CardReadBytesLoop
  rts
  
  
  
  
CardReadSector16:

  jsr CardWaitNotBusy
  jsr CardLoadLBA

  lda #$20
  sta CARDCOMMAND           ;send card read sector command
  nop
  nop
  
  jsr CardCheckError
  jsr CardWaitDataReq
  
  ldy #$00
CardReadSector16Loop:         ;read 16 bytes into ram
  lda CARDDATAREAD
  sta [destLo], y
  iny
  cpy #$10
  bne CardReadSector16Loop
  
  clc
  lda destLo
  adc #$10
  sta destLo
  lda destHi
  adc #$00
  sta destHi
  
  rts


CardReadSector496:
  ldx #$00
  ldy #$00
CardReadSector496Loop:         ;read 496 bytes into ram
  lda CARDDATAREAD
  sta [destLo], y
 
  cpy #$EF
  bne CardReadSector496LoopInc
  cpx #$01
  bne CardReadSector496LoopInc
  jmp CardReadSector496LoopDone

CardReadSector496LoopInc:
  iny
  bne CardReadSector496Loop
  inc destHi
  inx
  jmp CardReadSector496Loop
  
CardReadSector496LoopDone:  
  jsr CardCheckError

CardReadSector496Done:
  rts  


  
;------------------------------;  
  
CardWriteSector:
  jsr CardWaitNotBusy
  jsr CardLoadLBA  
  
  lda #$30
  sta CARDCOMMAND           ;send card write sector command
  nop
  nop
  
  jsr CardCheckError
  jsr CardWaitDataReq
    
  ldy #$00
  ldx #$02
CardWriteSectorLoop:         ;read 512 bytes from ram to card
  lda [sourceLo], y
  sta CARDDATAWRITE
  iny
  bne CardWriteSectorLoop
  inc sourceHi
  dex
  bne CardWriteSectorLoop
  
  jsr CardCheckError
  
CardWriteSectorDone:
  rts
  

;------------------------------;
CardLoadDirClearEntryName:
  lda #$00
  sta lfnFound
  ldy #$00
  lda #$00  
CardLoadDirClearEntryNameLoop:            ;clear entry name    //CHANGE ME 128 BYTES
  sta tempEntry, y
  iny
  cpy #$20
  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 #$02
  sta destHi                   ; $0200 = where to put sector
  sta sourceEntryHi
  
  lda #$60                     ; $6000 = where to put entry
  sta destEntryHi
  
  lda #$F8
  sta cursorX
  sta cursorY                  ; cursor off screen
  
  lda #$00
  sta destLo
  sta sourceEntryLo
  sta destEntryLo
  sta filesInDir
  sta filesInDir+1
  sta destBank
  sta sectorCounter
  sta temp
  sta temp+1
  sta selectedEntry
  sta selectedEntry+1
  sta cursorYCounter
  sta speedCounter
  sta speedScroll
  sta scrollYCounter
  sta PRGBANK
  sta lfnFound
    
  jsr ClusterToLBA            ; 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:  
  jsr CardReadSector          ; put into dest
  jsr CardLoadDirClearEntryName   ;clear entry name

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

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



CardLoadDirCheckLongName:
  ldy #$0B
  lda [sourceEntryLo], y            ; if flag = %00001111, long file name entry found
  and #$0F
  cmp #$0F
  bne CardLoadDirCheckShortName
  
  ldy #$00
  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
  
  jsr CardLoadDirClearEntryName
  
  jmp CardLoadDirNextEntry
  
  
      ;//CHANGE ME  USE MULTIPLY13 FUNCTION
CardLoadDirLongName1:
  ldx #$00                     ; index 1 = chars 0-12
  jmp CardLoadDirLongName
CardLoadDirLongName2:
  ldx #$0D                     ; index 2 = chars 13-25
  jmp CardLoadDirLongName
  
  
  
CardLoadDirLongName:
  lda #$00
  sta tempEntry+$20                 ;use as char counter    //CHANGE ME
  ldy #$01
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 #$0E
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 #$1C
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 #$0B
  lda [sourceEntryLo], y                 ;if flag = volume id, skip
  and #$08
  cmp #$08
  bne CardLoadDirCheckHidden
  jsr CardLoadDirClearEntryName
  lda #$00
  sta lfnFound
  jmp CardLoadDirNextEntry


CardLoadDirCheckHidden:
  ldy #$0B
  lda [sourceEntryLo], y
  and #$02
  cmp #$02                                ; if flag = 0x02, hidden, skip
  bne CardLoadDirCheckDir
  lda #$00
  sta lfnFound
  jsr CardLoadDirClearEntryName           ;clear entry name  
  jmp CardLoadDirNextEntry
  
      
CardLoadDirCheckDir:
  ldy #$0B
  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 #$00
  ldy #$08
CardLoadDirCheckEx1Loop:
  lda [sourceEntryLo], y
  cmp exMatch1, x
  beq CardLoadDirCheckEx2
  inx
  cpx #$04
  bne CardLoadDirCheckEx1Loop
  lda #$00
  sta lfnFound
  jsr CardLoadDirClearEntryName    
  jmp CardLoadDirNextEntry          ;if extension doesnt match, skip

CardLoadDirCheckEx2:
  ldx #$00
  ldy #$09
CardLoadDirCheckEx2Loop:
  lda [sourceEntryLo], y
  cmp exMatch2, x
  beq CardLoadDirCheckEx3
  inx
  cpx #$04
  bne CardLoadDirCheckEx2Loop
  lda #$00
  sta lfnFound
  jsr CardLoadDirClearEntryName
  jmp CardLoadDirNextEntry          ;if extension doesnt match, skip

CardLoadDirCheckEx3:
  ldx #$00
  ldy #$0A
CardLoadDirCheckEx3Loop:
  lda [sourceEntryLo], y
  cmp exMatch3, x
  beq CardLoadDirShortName
  inx
  cpx #$04
  bne CardLoadDirCheckEx3Loop
  lda #$00
  sta lfnFound
  jsr CardLoadDirClearEntryName
  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 #$00
CardLoadDirShortNameLoop:            ;if lfnFound = 0, copy short name
  lda [sourceEntryLo], y
  sta tempEntry, y
  iny
  cpy #$08
  bne CardLoadDirShortNameLoop

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

  lda #'.'
  sta tempEntry+$8
  ldy #$08
  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 #$1A
  lda [sourceEntryLo], y                  ;copy clusterhilo to last 4 bytes of entry   ///CHANGE ME
  sta tempEntry+$1C
  iny
  lda [sourceEntryLo], y
  sta tempEntry+$1D
  ldy #$14
  lda [sourceEntryLo], y
  sta tempEntry+$1E
  iny
  lda [sourceEntryLo], y
  sta tempEntry+$1F
  
  lda destBank                            ;change to entry storage bank
  sta PRGBANK
  
  ldy #$00
CardLoadDirSaveEntryLoop:                 ;copy entry to prg ram   //CHANGE ME  128 bytes
  lda tempEntry, y
  sta [destEntryLo], y                
  iny
  cpy #$20
  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

CardLoadDirClearTempEntryName:
  ldy #$00
  lda #$00  
  sta lfnFound  
CardLoadDirClearTempEntryLoop:            ;clear entry name
  sta tempEntry, y
  iny
  cpy #$20
  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 #$04
  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
  jsr NextCluster                      ;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:
  jsr ClusterToLBA                     ;sourceCluster -> first sourceSector
  lda #$00
  sta sectorCounter                    ;reset sector counter

CardLoadDirLoadNextSector:
  lda #$00
  sta destLo                          ;reset sector dest
  sta sourceEntryLo                   ;reset entry source
  lda #$02                              
  sta destHi
  sta sourceEntryHi
  jsr CardReadSector
  jmp CardLoadDirLoop
  
  
  
  
  
    
;-------------------------------------;


CardLoadModule:
  lda #$60
  sta $0404      ;module not ready, set controller vector to rts
  lda #$00
  sta moduleReady

  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
  
 
  
  jsr CardLoadDir    ; powerpak dir
;-------------------;
;  jsr DirPrintDir
;--------------------;  

  ;findEntry info already loaded

  jsr DirFindEntryNew       
  lda tempEntry+$1C
  sta sourceCluster
  sta mapperCluster
  lda tempEntry+$1D
  sta sourceCluster+1
  sta mapperCluster+1
  lda tempEntry+$1E
  sta sourceCluster+2
  sta mapperCluster+2
  lda tempEntry+$1F
  sta sourceCluster+3
  sta mapperCluster+3
 


  lda #$00
  sta destLo
  lda #$04
  sta destHi      ;put into module ram
  
  ;find first sector
  jsr ClusterToLBA            ;sourceCluster -> first sourceSector
  


  jsr RenderingOff    ;;DEBUG REMOVE
  jsr CardReadSector

  clc
  lda sourceSector
  adc #$01  
  sta sourceSector
  lda sourceSector+1
  adc #$00
  sta sourceSector+1
  lda sourceSector+2
  adc #$00  
  sta sourceSector+2
  lda sourceSector+3
  adc #$00  
  sta sourceSector+3
  lda sectorsPerCluster
  cmp #$01
  bne CardLoadModuleNextSector
  ;only one sector per cluster, go to next cluster
  jsr NextCluster
  jsr ClusterToLBA

CardLoadModuleNextSector:
  lda #$00
  sta destLo
  lda #$06
  sta destHi
  jsr CardReadSector

 ;;;DEBUG
;  lda $0400
;  sta temp
;  lda $0400+1
;  sta temp+1
;  lda $0400+2
;  sta temp+2
;  lda $0400+3
;  sta temp+3
;  jsr Long2Str
;  jsr PrintLine
;  jsr ForeverLoop
;;;DEBUG


  
  lda #$00
  sta scrollY           
  sta scrollYCounter    
  sta scrollYUp         
  sta scrollYDown       
  sta cursorYCounter
  sta cursorYUp         
  sta cursorYDown
  lda #$F8
  sta cursorX
  sta cursorY


  lda #$4C
  sta $0404      ;module ready, set controller vector to jmp

  jmp $0400      ;go to module begin
  
  
  
;-------------------------------------;


DirPrintEntry:
  ;offset = temp * 32   temp << 5
  ;bank num = temp+1 -> temp+2

  lda selectedEntry
  sta sourceEntryLo
  lda #$00
  sta sourceEntryHi
  sta printString
  sta printString+$1     ;replace with dir symbol
  sta printString+$1D    ;empty text at end of string
  sta printString+$1E
  sta printString+$1F
  lda selectedEntry+$1
  sta PRGBANK
  
  ldy #$05
DirPrintEntryShiftLoop:         ;//CHANGE ME temp << 7 = 128 bytes
  clc
  asl sourceEntryLo
  rol sourceEntryHi
  dey
  bne DirPrintEntryShiftLoop

  clc
  lda #$60
  adc sourceEntryHi
  sta sourceEntryHi
    
  ldy #$00                          ;//CHANGE ME  set starting char number
DirPrintEntryCopyLoop:
  lda [sourceEntryLo], y
  sta printString+2, y
  iny
  cpy #$1B
  bne DirPrintEntryCopyLoop
  
  ;;; add dir symbol or empty symbol     //CHANGE ME dir flag in new place
  ldy #$1B
  lda [sourceEntryLo], y
  beq DirPrintEntryDone
  
  lda #'/'
  sta printString+1
  
DirPrintEntryDone:
  rts
  
  
  
  
DirGetEntry:
  ;offset = selectedEntry * 32   temp << 5
  ;bank num = selectedEntry+1

  lda selectedEntry
  sta sourceEntryLo
  lda #$00
  sta sourceEntryHi
  lda selectedEntry+1
  sta PRGBANK
  
  ldy #$05
DirGetEntryShiftLoop:
  asl sourceEntryLo
  rol sourceEntryHi
  dey
  bne DirGetEntryShiftLoop

  clc
  lda #$60
  adc sourceEntryHi
  sta sourceEntryHi
    
  ldy #$00
DirGetEntryCopyLoop:
  lda [sourceEntryLo], y
  sta tempEntry, y
  iny
  cpy #$20
  bne DirGetEntryCopyLoop
  
  rts
  
  
  
  
DirFindEntry:
  lda #$00
  sta selectedEntry
  sta selectedEntry+1
  
DirFindEntryLoop:
  jsr DirGetEntry
  
  ;;check if entry matches, only look at first 8 chars
  ldy #$00
DirFindEntryCharLoop:
  lda tempEntry, y
  cmp findEntry, y
  bne DirFindEntryNext
  iny
  cpy #$08
  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:
  lda #messageNOTFOUND
  sta temp
  jsr StrCopy
  lda #$1A                       ;FIXME message position
  sta printY
;  jsr PrintLine                  ;FIXME change to 3x nops
  jsr FileNotFound
;  nop
;  nop
;  nop
  jmp Forever
  
;---------------------------------;  
  
  
DirPrintDir:
  
  ;turn off rendering
  jsr RenderingOff
  jsr ClearNameTable
  
  ;loop thro entries 0 to 31 or 0 to filesInDir
  lda #$00
  sta selectedEntry
  sta selectedEntry+1
  sta printY
  sta destBank
  sta PRGBANK
  
DirPrintDirLoop:
  inc printY                                   ; go to next print line

  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 printY
  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:
  
  lda #$00
  sta cursorX
  sta scrollY
  sta selectedEntry
  sta selectedEntry+1
  sta scrollYCounter
  sta scrollYUp 
  sta scrollYDown
  sta cursorYCounter
  sta cursorYUp
  sta cursorYDown
  sta speedCounter
  sta speedScroll
  sta destBank
 
  lda #$08
  sta cursorY

  jsr RenderingOn

  rts
 

    
;------------------------------;

FPGACopyRom:

  lda #$FF
  sta FPGAPROGRAM         ;tell fpga its being reprogrammed
  
    

  lda #$00
  sta MAPPERWR      ;;;;SWITCH BANK TO 16KB bank 0
  lda #$00
  sta sourceLo      ;copy FPGA from $8000 to $BFFF = 16KB
  lda #$80
  sta sourceHi
  ldy #$00          ;256 byte counter
  ldx #$40          ;block counter $40 = 64 * 256 = 16KB
FPGACopyRomLoop0:
  lda [sourceLo], y
  sta FPGADATA         ;fpga data address
  iny
  bne FPGACopyRomLoop0
  inc sourceHi
  dex
  bne FPGACopyRomLoop0



  lda #$01
  sta MAPPERWR      ;;;;SWITCH BANK TO 16KB bank 1
  lda #$00
  sta sourceLo      ;copy FPGA from $8000 to $BFFF = 16KB
  lda #$80
  sta sourceHi
  ldy #$00          ;256 byte counter
  ldx #$40          ;block counter $40 = 64 * 256 = 16KB
FPGACopyRomLoop1:
  lda [sourceLo], y
  sta FPGADATA         ;fpga data address
  iny
  bne FPGACopyRomLoop1
  inc sourceHi
  dex
  bne FPGACopyRomLoop1

  
  
  lda #$02
  sta MAPPERWR      ;;;;SWITCH BANK TO 16KB bank 2
  lda #$00
  sta sourceLo      ;copy FPGA from $8000 to $8125
  lda #$80
  sta sourceHi
  ldy #$00          ;256 byte counter
  ldx #$25          ;block counter 9328 more bytes= 37 * 256 = $25
FPGACopyRomLoop2:
  lda [sourceLo], y
  sta FPGADATA         ;fpga data address
  iny
  bne FPGACopyRomLoop2
  inc sourceHi
  dex
  bne FPGACopyRomLoop2
  
  rts


LoadPRGRam:
  lda #$00
  sta sectorCounter
  sta destLo
  lda #$60
  sta destHi  
  
  lda gameCluster
  sta sourceCluster
  lda gameCluster+1
  sta sourceCluster+1
  lda gameCluster+2
  sta sourceCluster+2
  lda gameCluster+3
  sta sourceCluster+3
  
  jsr ClusterToLBA
  jsr CardReadSector16     ;get ines header  16bytes
  
  lda #$00
  sta bankCounter
  sta destLo               ;reset to beginning of prgram
  lda #$60
  sta destHi  
LoadPRGRamLoop:
  lda #$00
  sta destLo
  
  jsr CardReadSector496    ;get 496 bytes
  
  lda destHi
  sta temp
  jsr LoadNextSectorNum    ;uses x,y,destHi,destLo
  lda temp
  sta destHi
  lda #$F0
  sta destLo
  jsr CardReadSector16     ;get 16 bytes  
LoadPRGRamLoopCheckBank:
  lda destHi
  cmp #$80
  bne LoadPRGRamLoop       ;check if next bank needed, destHi=80
  lda #$60
  sta destHi
  lda #$00
  sta destLo
  inc destBank
  inc bankCounter
LoadPRGRamLoopCheckDone:
  ;check if all prg loaded
  lda bankCounter
  cmp prgSize
  beq LoadPRGRamDone
  lda destBank
  sta PRGBANK
  jmp LoadPRGRamLoop
LoadPRGRamDone:
  rts
  
  
  
LoadWRam:
  rts





 .org $F51F
LoadCHRRam:
  
  lda chrSize           ;if no chr, set to chrram
  cmp #$00
  beq LoadCHRRamDone  

LoadCHRRam1: 
  lda #$00
  sta destBank
  sta CHRBANK
  sta destLo
  sta destHi  
  sta bankCounter

  
  ;16 bytes already read for prg  
LoadCHRRamLoop:

  lda #$00
  sta destLo

  lda $2002 
  lda destHi
  sta $2006
  lda destLo
  sta $2006

  jsr CardReadSector496Chr   ;get 496 bytes
  lda destHi
  sta temp
  jsr LoadNextSectorNum
  lda temp
  sta destHi
  lda #$F0
  sta destLo
  jsr CardReadSector16Chr    ;get 16 bytes  
LoadCHRRamLoopCheckBank:
  lda destHi
  cmp #$20
  bne LoadCHRRamLoop          ;check if next bank needed, destHi=20
  lda #$00
  sta destHi
  sta destLo
  inc destBank
  inc bankCounter
  lda $2002 
  lda destHi
  sta $2006
  lda destLo
  sta $2006
LoadCHRRamLoopCheckDone:
  ;check if all prg loaded
  lda bankCounter
  cmp chrSize
  beq LoadCHRRamDone
  lda destBank
  sta CHRBANK
  jmp LoadCHRRamLoop
LoadCHRRamDone:
  lda #$02
  sta destHi
  lda #$00
  sta destLo
  jsr CardReadSector496         ;get 496 bytes to finish sector
  lda #$00
  sta CHRBANK
  rts



CardReadSector16Chr:

  jsr CardWaitNotBusy
  jsr CardLoadLBA

  lda #$20
  sta CARDCOMMAND           ;send card read sector command
  nop
  nop
  
  jsr CardCheckError
  jsr CardWaitDataReq
  
  ldy #$00
CardReadSector16ChrLoop:         ;read 16 bytes into ram
  lda CARDDATAREAD
  sta $2007
  iny
  cpy #$10
  bne CardReadSector16ChrLoop
  
  clc
  lda destLo
  adc #$10
  sta destLo
  lda destHi
  adc #$00
  sta destHi
  
  rts


CardReadSector496Chr:
  ldx #$00
  ldy #$00
CardReadSector496ChrLoop:         ;read 496 bytes into ram
  lda CARDDATAREAD
  sta $2007
 
  cpy #$EF
  bne CardReadSector496ChrLoopInc
  cpx #$01
  bne CardReadSector496ChrLoopInc
  jmp CardReadSector496ChrLoopDone

CardReadSector496ChrLoopInc:
  iny
  bne CardReadSector496ChrLoop
  inc destHi
  inx
  jmp CardReadSector496ChrLoop
  
CardReadSector496ChrLoopDone:  
  jsr CardCheckError

CardReadSector496ChrDone:
  rts  

  
  
  
  
  
LoadFPGA:
  ;get fpga data starting after 2 sectors
  lda mapperCluster
  sta sourceCluster
  lda mapperCluster+1
  sta sourceCluster+1
  lda mapperCluster+2
  sta sourceCluster+2
  lda mapperCluster+3
  sta sourceCluster+3
  
  lda #$00
  sta sectorCounter
  sta tempEntry
    
  jsr ClusterToLBA     ;cluster->sector#1 into sourceSector
  jsr LoadNextSectorNum    ;sector#2  

  lda #$FF
  sta FPGAPROGRAM         ;fpga program address
LoadFPGALoop:
  jsr LoadNextSectorNum    ;uses x,y,destHi,destLo
  jsr LoadFPGASector
  inc tempEntry
  lda tempEntry
  cmp #$53         ;$53 sectors = 83 sectors = 42496 bytes, fpga = 42096 bytes
  bne LoadFPGALoop
  rts  
  
  
  
LoadFPGASector:

  jsr CardWaitNotBusy
  jsr CardLoadLBA

  lda #$20
  sta CARDCOMMAND           ;send card read sector command
  nop
  nop
  
  jsr CardCheckError
  jsr CardWaitDataReq
  
  ldy #$00
  ldx #$02
LoadFPGASectorLoop:         ;read 512 bytes into fpga data
  lda CARDDATAREAD
  sta FPGADATA
  iny
  bne LoadFPGASectorLoop
  dex
  bne LoadFPGASectorLoop
  
  jsr CardCheckError
  
LoadFPGASectorDone:
  rts  

  
  
  
LoadGameGenie:
  ;send 5 game genie codes, newdata/enable8mode/comparedata/addresslo/addresshi
  
  lda #$00
  sta temp
  sta temp+1
  
LoadGameGenieLoop:
  
  lda temp+1
  sta temp
  inc temp+1
  jsr GameGenieEncode

  lda gameGenieCodes+2
  sta GAMEGENIEWR       ;new data
  lda gameGenieCodes+4
  sta GAMEGENIEWR       ;enable8 mode
  lda gameGenieCodes+3
  sta GAMEGENIEWR       ;compare data
  lda gameGenieCodes+0
  sta GAMEGENIEWR       ;address lo
  lda gameGenieCodes+1
  sta GAMEGENIEWR       ;address hi

  lda temp+1
  cmp #$05
  bne LoadGameGenieLoop
  
  ;;load fpga configured info
  lda useBattery
  sta GAMEGENIEWR       ;new data
  lda #$00
  sta GAMEGENIEWR       ;enable8mode
  sta GAMEGENIEWR       ;compare data
  lda #$08
  sta GAMEGENIEWR       ;address lo
  lda #$42
  sta GAMEGENIEWR       ;address hi
  
  rts
  
  
  
  
LoadPrgChrSize:
  lda prgSize     ;4x8KB 0100
  sec
  sbc #$01        ;0011
  and #$7F        ;wram disabled
  sta PRGSIZEWR
  
  lda chrSize
  beq LoadPrgChrSizeChrRam

  lda chrSize     ;4x8KB 0100
  asl a           ;1000
  sec
  sbc #$01        ;0111
  and #$7F        ;chrram wr disabled
  sta CHRSIZEWR   
  rts
  
LoadPrgChrSizeChrRam:
  lda #$81
  sta CHRSIZEWR  ;chr size = 0, enable chrram wr
  rts
  
  

LoadMirroring:
  ;send mirroring h/v/four
  lda mirroring
  sta MIRRORINGWR
  rts  
  
;---------------------------:


RenderingOn:
  ;turn screen on, display screen/sprites
  jsr ClearSpriteRam
  jsr WaitVBlank
  
	lda #%10001000           ;7 vblank nmi, 4 screen addr, 3 sprite addr, 2 vertical wr, 10 name table addr  
  sta $2000
	lda #%00011110           ;567 emphasis color BGR, 4 sprites on, 3 background on, 2 sprite clipping, 1 image clipping
  sta $2001
  ;set scroll registers
  lda $2002                ;clear 2006 latch
  lda #$00                 ;;fixme????  was #$20
  sta $2006
  sta $2006  
  sta $2005
  sta $2005

  rts
  
  
RenderingOff:
  ;turn screen off
  jsr WaitVBlank
  lda $2002                ;clear 2006 latch
	lda #%00001000           ;7 vblank nmi, 4 screen addr, 3 sprite addr, 2 vertical wr, 10 name table addr  
  sta $2000
	lda #%00000110           ;567 emphasis color BGR, 4 sprites on, 3 background on, 2 sprite clipping, 1 image clipping
  sta $2001
  rts

ClearRam:
  ;clear ram variable 2KB bytes
  lda #$00
  ldx #$00
ClearRamLoop:
  sta $0000, x
  sta $0100, x
  sta $0200, x
  sta $0300, x
  sta $0400, x
  sta $0500, x
  sta $0600, x
  sta $0700, x
  inx
  bne ClearRamLoop
  
  lda #'1'
  sta romVers
  lda #'1'
  sta romVers+1
  lda #'2'
  sta romVers+2
  
  jmp ClearRamReturn
  
  
  
CheckCardFormat:
  lda #$00
  sta sourceSector
  sta sourceSector+1
  sta sourceSector+2
  sta sourceSector+3
  sta destLo
  lda #$02
  sta destHi
  
  jsr CardReadSector        ;read sector 0 to internal ram
  
  lda $03FE
  cmp #$55
  bne CardFormatError       ;last word check  should be $55AA
  lda $03FF
  cmp #$AA
  bne CardFormatError
  lda #$01
  sta fat32Enabled
  lda $03C2                 ;format  fat32 = 0x0B   FAT32
  cmp #$0B
  beq CardGoodFormat
  lda $03C2                 ;format  fat32 = 0x0C   FAT32 LBA
  cmp #$0C
  beq CardGoodFormat
  
  
  lda #$00
  sta fat32Enabled
  lda $03C2                ;format  fat16 = 0x06  larger than 32MB
  cmp #$06
  beq CardGoodFormat
  lda $03C2                ;format  fat16 = 0x04  smaller than 32MB
  cmp #$04
  beq CardGoodFormat
  lda $03C2                ;format  fat16 = 0x0E  with LBA
  cmp #$0E
  beq CardGoodFormat
  
  nop
  nop
  nop

CardFormatError:
  lda #messageBADFORMAT
  sta temp
  jsr StrCopy              ;print format error message, stop everything
  lda #$1A                 
  sta printY
  
  lda $03C2                ;card last word read
  sta temp
  jsr Byte2Str
  jmp ForeverLoop

  
CardGoodFormat:            ;fat32/fat16 partition found  
  
  ldx #$00
CardCopyPartitionLBABegin: ;copy partitionLBABegin from offset 455
  lda $03C6, x
  sta sourceSector, x
  sta partitionLBABegin, x
  inx
  cpx #$04
  bne CardCopyPartitionLBABegin

  jmp GetVolumeID  ;;rts

















CheckCardFormatFail:
  lda #$00
  sta sourceSector
  sta sourceSector+1
  sta sourceSector+2
  sta sourceSector+3
  sta destLo
  lda #$02
  sta destHi
  
  jsr CardReadSector        ;read sector 0 to internal ram
  
FindCardPartition:  
  lda $03FE
  cmp #$55
  bne CardFormatErrorX       ;last word check  should be $55AA
  lda $03FF
  cmp #$AA
  bne CardFormatErrorX
  
  
  
  ldx #$00      ;;x = partition index  0, 16, 32, 48
  ldy #$00      ;;y = partition number 0, 1, 2, 3
CardFormatCheckLoop:
  lda #$01
  sta fat32Enabled
  lda $03C2, x                 ;format  fat32 = 0x0B   FAT32
  cmp #$0B
  beq CardGoodFormatX
  lda $03C2, x                 ;format  fat32 = 0x0C   FAT32 LBA
  cmp #$0C
  beq CardGoodFormatX
  
  
  lda #$00
  sta fat32Enabled
  lda $03C2, x                ;format  fat16 = 0x06  larger than 32MB
  cmp #$06
  beq CardGoodFormatX
  lda $03C2, x                ;format  fat16 = 0x04  smaller than 32MB
  cmp #$04
  beq CardGoodFormatX
  lda $03C2, x                ;format  fat16 = 0x0E  with LBA
  cmp #$0E
  beq CardGoodFormatX
  
  inx
  inx
  inx
  inx

  inx
  inx
  inx
  inx

  inx
  inx
  inx
  inx

  inx
  inx
  inx
  inx
  
  iny
  cpy #$04
  bne CardFormatCheckLoop

CardFormatErrorX:
  lda #messageBADFORMAT
  sta temp
  jsr StrCopy              ;print format error message, stop everything
  lda #$1A                 
  sta printY
  
  lda $03C2                ;card last word read
  sta temp
  jsr Byte2Str
  jmp ForeverLoop

  
CardGoodFormatX:                ;fat32/fat16 partition found  

  lda #messageBADFORMAT
  sta temp
  jsr StrCopy              ;print format error message, stop everything
  lda #$1A                 
  sta printY
  
  lda $03C2,x                ;card last word read
  sta temp
  jsr Byte2Str

  ldy #$00
CardCopyPartitionLBABeginX:    ;copy partitionLBABegin from offset 455
  lda $03C6, x                ;;x = partition index
  sta sourceSector, y
  sta partitionLBABegin, y
  inx
  iny
  cpy #$04
  bne CardCopyPartitionLBABeginX
  
  
  jmp GetVolumeID  ;;rts







DirFindEntryNew:
  lda #$00
  sta selectedEntry
  sta selectedEntry+1

  lda selectedEntry 
  cmp filesInDir
  bne DirFindEntryNewLoop
  lda selectedEntry+1
  cmp filesInDir+1
  bne DirFindEntryNewLoop
  jmp DirFindEntryNewFailed
  
  
DirFindEntryNewLoop:
  jsr DirGetEntry
  
  ;;check if entry matches, only look at first 8 chars
  ldy #$00
DirFindEntryNewCharLoop:
  lda tempEntry, y
  cmp findEntry, y
  bne DirFindEntryNewNext
  iny
  cpy #$08
  bne DirFindEntryNewCharLoop
  
  rts  ;all 8 chars match

DirFindEntryNewNext:
  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 DirFindEntryNewLoop
  lda selectedEntry+1
  cmp filesInDir+1
  bne DirFindEntryNewLoop
  
DirFindEntryNewFailed:
  lda #messageNOTFOUND
  sta temp
  jsr StrCopy
  lda #$1A
  sta printY
  
FileNotFound:
  ldy #$00
FileNotFoundLoop:
  lda findEntry, y
  sta printString, y
  iny
  cpy #$08
  bne FileNotFoundLoop
  jmp Forever
  
  
WaitFrame:
  lda frameCounter
WaitFrameLoop:
  cmp frameCounter
  beq WaitFrameLoop
  rts
  
  
NewCFBoot:
NewCFInserted:
  lda CARDSTATUS           ;card status read
  cmp #$FF                 ;compare to 11111111
  bne NewCFResetDone
  jsr WaitFrame
  lda #messageNOCARD       ;load message = no card
  sta temp
  jsr StrCopy
  lda #$07                 ; message position
  sta printY
  jmp ForeverLoop          ;stop everything


NewCFReset:
;  lda #%00001110
;  sta CARDDEVICE
;  jsr WaitFrame
;  jsr WaitFrame
;  lda #%00001010
;  sta CARDDEVICE    ;;do software reset
  lda #$FF
  sta $8000
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  lda #$00
  sta $8000
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame

NewCFResetDone
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame
  jsr WaitFrame

  lda #$00
  sta sourceSector+1       ;use as loop counter
NewCFBusy:
  lda CARDSTATUS           ;card status read
  sta sourceSector         ;store somewhere unused
  and #%10000000
  cmp #%10000000           ;check busy bit
  bne NewCFNotBusy
  
  lda #messageCARDBUSY     ;load message = card busy
  sta temp
  jsr StrCopy
  lda #$1A                 
  sta printY
  
  lda sourceSector         ;card status read
  sta temp
  jsr Byte2Str
  
  jsr WaitFrame

  lda sourceSector+1
  clc
  adc #$01
  sta sourceSector+1
  cmp #30              ;;only check busy bit for 30 frames
  beq NewCFReset
  jmp NewCFBusy
  
  
NewCFNotBusy:
  lda #$00
  sta sourceSector+1       ;use as loop counter

NewCFReady:
  lda CARDSTATUS           ;card status read
  sta sourceSector
  and #%11010000
  cmp #%01010000           ;check busy+ready bit
  beq NewCFDone

NewCFNotReady:
  lda #messageNOTREADY     ;load message = card not ready
  sta temp
  jsr StrCopy
  lda #$1A                 
  sta printY
  
  lda sourceSector           ;card status read
  sta temp
  jsr Byte2Str

  jsr WaitFrame

  lda sourceSector+1
  clc
  adc #$01
  sta sourceSector+1
  cmp #30              ;;only check ready bit for 30 frames
  bne NewCFReady
  jmp NewCFReset


NewCFDone:
  jmp CardReady
;--------------------End Code--------------------------:
;------------------------------------------------------:

  .org  $FFFA
  .dw   NMI    ;FFFa FFFb
  .dw   RESET  ;FFFc FFFd
  .dw   IRQ    ;FFFe FFFf