; JatariCart flasher
; by Jakub Husak , 04.01.2020
; All Rights Reserved.
;
; JatariCart is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; JatariCart is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with JatariCart256.  If not, see <http://www.gnu.org/licenses/>.
;
	icl 'atari.hea'
; flash image is included at the end of file
; uncomment when flashing all cart or want to check all blocks written so far.
;.def compareall

BankNum	equ	$88
operation	equ $8a
start	equ	6	; format chip and program
select  equ	5	; ferify and format sectors
option	equ	3	; verify
outchar equ	$F2B0
memtop 	equ	$2e5
dmactls	equ	$22f

_SOURCE	equ	$6000
_DEST	equ	$A000

; test code
	org $2000
FINISH_PROCESS_JMP
	.print "#define	FINISH_PROCESS_JMP	0x",*
	jmp FINISH_PROCESS
MAIN_PROCESS_JMP
	.print "#define	MAIN_PROCESS_JMP	0x",*
	jmp MAIN_PROCESS
	.print "#define	STARTFLASHWRITE	0x",*
STARTFLASHWRITE
	mva #$A0 106
	jsr opened
	lda 20
@	cmp 20
	beq @-
@	lda #$1
	sta 66
	; waiting for cart to be inserted
	jsr print
	.print "#define	TITLE	0x",*-$2000+6
	TITLE+128
	dta $9b,c'JatariCart/MaxFlash flasher'
	dta $9b
	dta c'by JHusak, version 26.01.2025'
	dta $9b
	dta c'JatariCart of size '
	.print "#define	CARTSIZE1	0x",*-$2000+6
	CARTSIZE+128
	dta c' kB needed',$9b,$9b
	dta c'Insert JatariCart of '
	.print "#define	CARTSIZE2	0x",*-$2000+6
	CARTSIZE+128
	dta c' kB...',0

	sta $d500
?wloop	lda $d013
	lsr
	bcc ?wloop

	ldx #$25
?lloop	; wait 0.5 sec after inserting
	bit VCOUNT
	bmi *-3
	bit VCOUNT
	bpl *-3
	dex
	bne ?lloop

	jsr print
	dta $9b,c'Inserted.',$9b,0
	
	; cart inserted, fake it was not changed
	jsr accept_bank_change

	ldx #0 ; chip address
	stx numgoodchipsneeded
_check_chips
	stx _storex
	jsr check_type
	bcc ?chip_ok
	beq ?unrecog2
?unrecog1
	jsr print
	dta c'no chip #'
?chipign1
	dta c'1, ignoring... ',0
	clc
	bcc ?common

?unrecog2
	jsr print
	dta c'unknown chip #'
?chipign2
	dta c'1 protocol, ignoring...',0

?common
	lda #0
	sta m_vendor
	sta m_kind
	jmp ?exit
?chip_ok
	lda numgoodchipsneeded
	ora goodchipsmask
	sta numgoodchipsneeded
	jsr print
	dta c'chip #'
?chipno
	dta c'1' ; will be incremented if TWOCHIPS defined
	dta c' vend/prod: ',0
	lda m_vendor
	jsr printhex
	lda m_kind
	jsr printhex
	jsr print
	dta c' code: ',0

	; print memory type
	lda M_VECTOR
	clc
	adc #flash_idstr ; will print flashmem text id
	sta ?taddr
	lda M_VECTOR+1
	adc #0
	sta ?taddr+1
	ldy #0
?loop	; write string onscreen, 0-ended
	lda ?taddr:$ffff,y
	beq ?exit
	sty st_y
	jsr outchar
	ldy st_y:#0
	iny
	bne ?loop
?exit
	jsr printnl
	ldx _storex

	asl goodchipsmask

	cpx #$40
	beq menu
	lda m_vendor
	sta t_vendor
	lda m_kind
	sta t_kind
	inc ?chipno
	inc ?chipign1
	inc ?chipign2
	ldx #$40
	jmp _check_chips
menu
	lda numgoodchipsneeded
	.if .def TWOCHIPS
	cmp #3 ; two chips needed
	.else
	and #1
	cmp #1 ; at least first chip needed
	.endif
	beq ?cont

	; FAIL and loop forever
	jsr print
	dta $9b
	dta c'Sorry, recognized chip configuration',$9b
	dta c'does not suit your binary.',$9b
	dta c'Your cart needs '
	.if .def TWOCHIPS
	dta c'two chips.',$9b
	.else
	dta c'at least first chip.',$9b
	.endif
	dta c'Please reboot.',$9b,0
	jmp *

?cont
	jsr printnl
	;lda #$ff
	;sta $d301
	
	jsr print
	dta c'Press:',$9b
	dta c'START  - cartridge format and flash!',$9b
	;dta c'SELECT - verify; repair bad blocks.',$9b
	dta c'OPTION - verify',$9b,0
?wloop	lda 53279
	cmp #7
	beq ?wloop
	sta operation

	cmp #select
	beq ?wloop

	cmp #option
	jeq CHECKONLY

	cmp #start
	beq FORMAT
	bne ?wloop

	; start
FORMAT
	jsr printformatting
	jsr print
	dta c'1...',0
	jsr flashformatchip1
	bcs formatfailed
	jsr flashend ; restores display etc. preserves all
	.print "#define	TWO_CHIPS_SWITCH	0x",*-$2000+6+1
	.print "#define	TWO_CHIPS_SWITCH_ADDR	0x",*+1
	.if .def TWOCHIPS
	lda #1
	.else
	lda #0
	.endif
	beq ?exit2
	jsr printdone
	jsr printformatting
	jsr print
	dta c'2...',0
	jsr flashformatchip2
	bcs formatfailed
?exit2
	jsr flashend ; restores display etc. preserves all
printdone	jsr print
	dta c'done:)',$9b,0
	jmp eraseSRC_FF

printformatting
	jsr print
	dta c'Formatting cart chip ',0
	rts

formatfailed
	jsr flashend
	jsr print
	dta c'failed:(',$9b,'Waiting for reboot...',$9b,0
	jmp *
VERIFYREPAIR
	jsr print
	dta c'Verify and ',0
CHECKONLY
	jsr print
	dta c'Compare.',$9b,0
	jsr eraseSRC_FF
	rts

t_vendor	.byte 0
t_kind		.byte 0
numgoodchipsneeded	.byte 0
goodchipsmask	.byte 1
_storex		.byte 0

crcsums
	:128	.word 0
opened	
	ldx	#0
	lda 	#12
	jsr 	icio
	mwa 	#name	icbufa,x
	mva 	#$0c	icax1,x
	mva 	#$0	icax2,x
	lda 	#3
icio	sta	iccmd,x
	jmp 	$e456
name	dta 'E:',$9b

CHECKINIT
	mwa #_SOURCE _csrc
	mwa #_DEST _cdst
	sei
CHECK
	mva #0 badcompare_counter
	sta badcompare_counter+1
	jsr GetBankNumToX
	sta $d500,x
checkloop
	lda _csrc:$6000 ; src
	cmp _cdst:$A000 ; dst
	beq _byte_ok
	lda _csrc
	ldx _csrc+1
	jsr BADCOMPARE
_byte_ok
	inw _csrc
	inw _cdst
	lda _csrc+1
	cmp #>_SOURCE+$20
	bne checkloop
	cpw #0 badcompare_counter
	beq _all_bytes_ok
	; several differences found...
	; cart off
	jsr cartoff_and_accept_bank_change
	cli
	; print status
	jsr print
	dta 253,c'non-match byte#:',0
	lda badcompare_counter+1
	jsr printhex
	lda badcompare_counter
	jsr printhex
	jsr print
	dta c' (START-cont)',0

	lda #7
	cmp CONSOL ; wait for consol
	req

	jsr printnl
	jsr eraseSRC_FF
	sec
	rts
_all_bytes_ok
	jsr cartoff_and_accept_bank_change
	jsr eraseSRC_FF
	cli
	lda #'o'
	jsr outchar
@	clc
dmaon	mva #34 dmactls
	sta dmactl
	rts

cartoff_and_accept_bank_change
	sta $d5ff
accept_bank_change
	lda $d013
	sta $3fa
	rts

eraseSRC_FF
	mwa #_SOURCE e_csrc
e_loop_init
	lda #$FF
e_loop
	sta e_csrc:$ffff ; src
	inc e_csrc
	bne e_loop
	inc e_csrc+1
	lda e_csrc+1
	cmp #>_SOURCE+$20
	bne e_loop_init
	rts

VERIFY
	;mwa #_SOURCE _csrc
	;mwa #_DEST _cdst
	jsr CHECKINIT
	bcc v_rts
	lda #'f'
	jsr outchar
	jsr GetBankNumToX
	lda #$a0
	jsr flashformatsector
	jsr GetBankNumToX
	lda #$b0
	jsr flashformatsector
	jsr FORMATTED
v_rts	jmp dmaon

COMPARE_CRC16_DEST_ALL
	jsr GetBankNumToX
	stx _tbanknum
@	sei
_tbanknum	equ * + 1
	sta $d500
	clc
	mva _tbanknum calccrc_bank
	jsr CALCCRC_DEST
	jsr status_crc
	.ifdef compareall
	dec _tbanknum
	bpl @-
	.endif
	jsr cartoff_and_accept_bank_change
	cli
	rts
status_crc
	php
	jsr printBank_t
	plp
	php
	sne
	lda #'o'
	plp
	seq
	lda #'!'+128
	jsr outchar
	lda #','
	jmp outchar
	
	
CALCCRC_DEST
	php
	mwa #_DEST _tsrc
	bne crccont

CALCCRC ; c=1 - write; c=0 - check
	php
	mwa #_SOURCE _tsrc
	mwa #$2000 _tcnt
crccont	mwa #$ffff crc16.crc
	lda _tsrc:$ffff
	jsr crc16.updCRC
	inw _tsrc
	dew _tcnt
	bne _tsrc -1
	lda calccrc_bank:#$ba ;nk number
	asl
	tax
	plp
	bcc crccheck
	mwa crc16.crc crcsums,x
	rts
_tcnt	:2 dta 0
crccheck
	cpw crc16.crc crcsums,x
	rts


printBank_t
	lda _tbanknum
	bpl skip
printBank
	jsr printnl
	jsr GetBankNumToX
	txa
skip	pha
	lda #'B'
	jsr outchar
	pla
	jsr printhex
	lda #':'
	jmp outchar
MAIN_PROCESS
	;mva #0 dmactls
	;sta dmactl
	sec
	jsr GetBankNumToX
	stx calccrc_bank
	jsr CALCCRC
	mwa #_DEST flashaddr
	;ldx #<_DEST
	;ldy #>_DEST
	;jsr flashsetaddr
	jsr printBank

	lda operation
	;cmp #select
	;jeq VERIFY

	cmp #option
	jeq CHECKINIT
	; START (was CONSOL & !OPTION, so START)
FORMATTED
	mwa #_SOURCE _writeaddr
	lda _writeaddr+1
	clc
	adc #$20
	sta _cmpaddr ; only hi byte
	mwa #_DEST flashaddr
	; sec
formatted_next
	jsr GetBankNumToX
	jsr flashunlockchip
formatted_next2
	lda _writeaddr:$ffff ; this is source address
	jsr flashwritebyte
	jsr flashincaddr
	inw _writeaddr
	lda _cmpaddr:#$ff ; this is the page to end
	cmp _writeaddr+1
	bne formatted_next2
	jsr flashend
	jsr flashlockchip
	jsr COMPARE_CRC16_DEST_ALL
	jmp eraseSRC_FF

FINISH_PROCESS
	jsr print
	dta $9b,'Finished',0
	jmp *
	rts
badcompare_counter	dta 0,0
BADCOMPARE
	ldy 53279
	cpy #7
	beq @+
	pha
	txa
	pha
	lda #'!'
	jsr outchar
	pla
	jsr printhex
	pla
	jsr printhex
	lda #':'
	jsr outchar
	mwa _csrc badcompare_tmp1
badcompare_tmp1 equ 	* +1
	lda $ffff
	jsr printhex
	lda #'/'
	jsr outchar
	mwa _cdst badcompare_tmp2
badcompare_tmp2 equ 	* +1
	lda $ffff
	jsr printhex
	jsr printnl
@	inw badcompare_counter
	sec
	jmp dmaon ; rts inside dmaon
; -------
	icl 'flashwritelib.asx'
	icl 'crc16_v2.asm'
	icl 'print2.asx'

bank_order_tab
.if .not .def BANK_ORDER
	.rept 128
	.byte .R
	.endr
.else
	BANK_ORDER
.endif

GetBankNumToX
	ldx BankNum
	lda bank_order_tab,x
	tax
	rts
	.print  "#define	END_OF_MAIN_CODE	0x",*-$2000+6+6

	org $2e2
	dta a(STARTFLASHWRITE)


; ---------------------------------------
; blocks for every 8kb bank
.rept BANKS, #
        .print "A :1"
        .local block:1
;------------
        org BankNum
        dta b(:1)
;------------
        org _SOURCE
	BANKS_FILE :1
;------------
        org $2e2
        dta a(MAIN_PROCESS_JMP)
;------------
        .endl
 .endr
;------------
	.if .def CUSTOM_CART_LAYOUT
	CUSTOM_CART_LAYOUT
	.endif
        org $2e2
        dta a(FINISH_PROCESS_JMP)
