;==========================================================================================
;
;   UNOFFICIAL SNES POWERPAK FIRMWARE V2.02 (CODENAME: "SIMBA")
;   (c) 2012/2013 by ManuLöwe (http://www.manuloewe.de/)
;
;	*** CF MODULE: SU (AUTOMATIC FLASH UPDATER) ***
;
;==========================================================================================



; !!! IMPORTANT !!! CODE IN THIS FILE HAS TO BE BACKWARD-COMPATIBLE WITH ANY PREVIOUS
; VERSION(S) TO BE SUPPORTED BY THE UPDATER !!!



; ****************************** Includes ******************************

	.INCLUDE "module_rommakeup.inc"		; MemoryMap, VectorTable, HeaderInfo

	.INCLUDE "global_variables.asm"		; Global Variables



; ******************************** Main ********************************

Main:
	sep #A_8BIT				; 8 bit Accumulator, 16 bit X/Y
	rep #XY_8BIT

	lda #$FF				; hide logo
	sta SpriteBuf1+17
	sta SpriteBuf1+21
	sta SpriteBuf1+25
	sta SpriteBuf1+29
	sta SpriteBuf2+1			; 32x32 sprites

	stz configBGdesign			; switch to black HDMA background before stopping HDMA

	wai

	lda #$01				; now disable HDMA ...
	sta disableHDMA

	stz $2123				; ... and manually reenable BG1/2 window

	jsr msg_Loading

	wai

	lda #$00
	sta CONFIGWRITEDSP			; turn off DSP chip

	stz Joy1Press				; reset input buttons
	stz Joy1Press+1
	stz Joy1New
	stz Joy1New+1

	lda CONFIGREADSTATUS			; check if FPGA is configured
	and #$F0
	cmp #$A0
	beq +

	jsr ConfigureFPGA

+	lda #$00
	sta DMAWRITELO
	sta DMAWRITEHI
	sta DMAWRITEBANK

	jsr LoadUpdateFile

	jsr msg_Intro

	jsr SPIdentification

	lda temp
	cmp #$1F
	bne +
	lda temp+1
	cmp #$D5
	bne +
	PrintString "AT29C010A"
	bra Flash_AT29C010A

+	lda temp
	cmp #$BF
	bne +
	lda temp+1
	cmp #$B5
	bne +
	PrintString "SST39SF010A"
	jmp Flash_SST39SF010A

+	PrintString "UNKNOWN"
	jmp error_UnknownFlashChip



; ************************* Flashing routines **************************

Flash_AT29C010A:
	jsr msg_Warning

	sei					; disable NMI & IRQ
	stz REG_NMI_TIMEN

	lda #$00
	sta DMAWRITELO
	sta DMAWRITEHI
	sta DMAWRITEBANK

	ldx #$0000

__NextSectorBank0:
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$A0
	sta $00D555

	ldy #$0000

-	lda DMAREADDATA
	sta $008000, x
	inx
	iny
	cpy #$0080
	bne -

	jsr CheckToggleBit

	cpx #$8000
	bne __NextSectorBank0

	ldx #$0000

__NextSectorBank1:
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$A0
	sta $00D555

	ldy #$0000

-	lda DMAREADDATA
	sta $018000, x
	inx
	iny
	cpy #$0080
	bne -

	jsr CheckToggleBit

	cpx #$8000
	bne __NextSectorBank1

	ldx #$0000

__NextSectorBank2:
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$A0
	sta $00D555

	ldy #$0000

-	lda DMAREADDATA
	sta $028000, x
	inx
	iny
	cpy #$0080
	bne -

	jsr CheckToggleBit

	cpx #$8000
	bne __NextSectorBank2

-	lda HVBJOY				; wait a bit, this helps prevent palette glitches after resetting
	bpl -

-	lda HVBJOY
	bmi -

-	lda HVBJOY
	bpl -

-	lda HVBJOY
	bmi -

	lda #%10000001
	sta CONFIGWRITESTATUS			; reset PowerPak, stay in boot mode



Flash_SST39SF010A:
	jsr msg_Warning

	sei					; disable NMI & IRQ
	stz REG_NMI_TIMEN

	lda #$00
	sta DMAWRITELO
	sta DMAWRITEHI
	sta DMAWRITEBANK

	ldx #$0000

__Prepare4KBSectorBank0:
	lda #$AA				; sector erase command sequence
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$80
	sta $00D555
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$30
	sta $008000, x

	jsr Wait10ms

	ldy #$0000

__Write4KBSectorBank0:
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$A0
	sta $00D555

	lda DMAREADDATA
	sta $008000, x

	jsr CheckToggleBit

	inx
	iny
	cpy #$1000
	bne __Write4KBSectorBank0

	cpx #$8000
	bne __Prepare4KBSectorBank0

	ldx #$0000

__Prepare4KBSectorBank1:
	lda #$AA				; sector erase command sequence
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$80
	sta $00D555
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$30
	sta $018000, x

	jsr Wait10ms

	ldy #$0000

__Write4KBSectorBank1:
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$A0
	sta $00D555

	lda DMAREADDATA
	sta $018000, x

	jsr CheckToggleBit

	inx
	iny
	cpy #$1000
	bne __Write4KBSectorBank1

	cpx #$8000
	bne __Prepare4KBSectorBank1

	ldx #$0000

__Prepare4KBSectorBank2:
	lda #$AA				; sector erase command sequence
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$80
	sta $00D555
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$30
	sta $028000, x

	jsr Wait10ms

	ldy #$0000

__Write4KBSectorBank2:
	lda #$AA
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$A0
	sta $00D555

	lda DMAREADDATA
	sta $028000, x

	jsr CheckToggleBit

	inx
	iny
	cpy #$1000
	bne __Write4KBSectorBank2

	cpx #$8000
	bne __Prepare4KBSectorBank2

-	lda HVBJOY				; wait a bit, this helps prevent palette glitches after resetting
	bpl -

-	lda HVBJOY
	bmi -

-	lda HVBJOY
	bpl -

-	lda HVBJOY
	bmi -

	lda #%10000001
	sta CONFIGWRITESTATUS			; reset PowerPak, stay in boot mode



; **************************** Subroutines *****************************

LoadUpdateFile:
	FindFile "UPDATE.BIN"

	stz sectorCounter
	stz bankCounter

	jump jCardReadFile

	jsr VerifyUpdateFile
rts



ConfigureFPGA:
	lda #$01
	sta FPGAPROGRAMWRITE			; SEND PROGRAM SIGNAL TO FPGA
	lda #$00
	sta FPGAPROGRAMWRITE			; SEND PROGRAM SIGNAL TO FPGA
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	lda #$01
	sta FPGAPROGRAMWRITE			; SEND PROGRAM SIGNAL TO FPGA

	FindFile "TOPLEVEL.BIT"

	jump jCardLoadFPGA

	wai

	lda #%00000001
	sta CONFIGWRITESTATUS			; unlock SDRAM
rts



SPIdentification:
	PrintString "\nDETECTED FLASH ROM CHIP ID: "

	sei					; disable NMI & IRQ
	stz REG_NMI_TIMEN

	lda #$AA				; software product identification entry
	sta $00D555				; $5555 + $8000 (SNES LoROM address)
	lda #$55
	sta $00AAAA				; $2AAA + $8000 (SNES LoROM address)
	lda #$90
	sta $00D555

	jsr Wait10ms

	lda $008000				; manufacturer code (AT29C010A: $1F - SST39SF010A: $BF)
	sta temp
	lda $008001				; device code (AT29C010A: $D5 - SST39SF010A: $B5)
	sta temp+1

	lda #$AA				; software product identification exit
	sta $00D555
	lda #$55
	sta $00AAAA
	lda #$F0
	sta $00D555

	jsr Wait10ms

	lda #$81				; Vblank NMI + Auto Joypad Read
	sta REG_NMI_TIMEN			; re-enable Vblank NMI
	cli
rts



CheckToggleBit:
-	bit $008000				; wait for DQ6 bit toggling to stop
	bvs +
	bit $008000
	bvc __DeviceReady

+	bit $008000
	bvc -

__DeviceReady:

rts



Wait10ms:					; actually, two Vblanks (1 frame = ~17ms)
-	lda HVBJOY
	bpl -

-	lda HVBJOY
	bmi -

-	lda HVBJOY
	bpl -

-	lda HVBJOY
	bmi -
rts



msg_Loading:
	jump jPrintClearScreen

	SetCursorPos 1, 0
	PrintString "LOADING ..."
rts



msg_Intro:
	SetCursorPos 1, 0
	PrintString "SNES POWERPAK FLASH UPDATER (VERSION: 2.02)\n"
	PrintString "(C) 2013 BY WWW.MANULOEWE.DE\n\n"

	lda $008149
	sta temp
	stz temp+1

	lda #<temp
	sta strPtr
	lda #>temp
	sta strPtr+1

	ldy #strPtr

	PrintString "DETECTED CURRENT ROM VERSION: 2.0%s"
rts



msg_Warning:
	SetCursorPos 7, 0
	PrintString "WARNING: THIS UPDATE IS PERFORMED AT YOUR OWN\n"
	PrintString "RISK! DON'T SWITCH OFF OR RESET YOUR SNES\n"
	PrintString "IN THE PROCESS.\n"
	PrintString "THE SCREEN MIGHT GO BLACK AND/OR SHOW GARBLED\n"
	PrintString "GRAPHICS. IF SUCCESSFUL, YOUR POWERPAK WILL\n"
	PrintString "RESTART IN A FEW SECONDS.\n\n"
	PrintString "PRESS (A) TO PROCEED ..."

-	wai
	lda Joy1New				; wait for user input
	and #%10000000				; A button
	beq -

	SetCursorPos 14, 0			; this overwrites the previous line ("PRESS (A) ...")
	PrintString "FLASHING, PLEASE WAIT ..."

	wai					; ensure the message appears on the screen
rts



VerifyUpdateFile:
	lda #$C5				; string at offset $7FC5: "PowerPak" (part of internal ROM name),
	sta DMAWRITELO				; this ensures UPDATE.BIN actually contains a PowerPak bootloader
	lda #$7F				; while not preventing a possibly intended downgrade
	sta DMAWRITEHI
	lda #$00
	sta DMAWRITEBANK

	lda DMAREADDATA
	cmp #'P'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'o'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'w'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'e'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'r'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'P'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'a'
	bne error_UpdateFileCorrupt
	lda DMAREADDATA
	cmp #'k'
	bne error_UpdateFileCorrupt
rts



error_UpdateFileCorrupt:
	SetCursorPos 3, 0
	PrintString "ERROR:\n"
	PrintString "UPDATE.BIN APPEARS TO BE CORRUPT! PLEASE\n"
	PrintString "REDOWNLOAD THE FLASH UPDATE PACKAGE AND\n"
	PrintString "TRY AGAIN."

	jump jForever



error_UnknownFlashChip:
	SetCursorPos 7, 0
	PrintString "ERROR:\n"
	PrintString "YOUR POWERPAK CANNOT BE UPGRADED AS OF YET.\n"
	PrintString "PLEASE REVERT TO YOUR PREVIOUS CF MODULES."

	jump jForever
