; Atari executable booter by Fatih Aygun

.include "atari.inc"

.import __BOOT_START__
.import __BSS_LOAD__
.import sio_handler

BOOTER_COMMAND_GET_CHUNK_INFO = $ff
BOOTER_COMMAND_GET_CHUNK = $fe
BOOTER_COMMAND_NOTIFY_RUN = $fd

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

size_ = __BSS_LOAD__ - __BOOT_START__ -1
sectors_ = (size_ + 127) / 128

; Disk boot header

.segment "HEADER"

nop_sub:
	rts				; Unused byte, reuse it as a nop subroutine
	.byte	<sectors_		; Number of sectors to load
	.word	__BOOT_START__		; Load address
	.word	go_cold			; Initialization address, cold start on reset

	address:	.res	2
	size:		.res	2

.data
	chunk:		.word	0

.code

begin:
	; Fake a succesfull boot
	ldx	#0
	stx	COLDST
	inx
	stx	BOOTQ
	lda	#<COLDSV
	sta	CASINI
	sta	DOSVEC
	lda	#>COLDSV
	sta	CASINI + 1
	sta	DOSVEC + 1

	; Initialize RUNAD
	lda	#<nop_sub
	sta	RUNAD
	lda	#>nop_sub
	sta	RUNAD + 1

main_loop:
	; Initialize INITAD
	lda	#<nop_sub
	sta	INITAD
	lda	#>nop_sub
	sta	INITAD + 1

	; Get chunk info
	lda	#$31
	sta	DDEVIC
	lda	#1
	sta	DUNIT
	lda	#BOOTER_COMMAND_GET_CHUNK_INFO
	sta	DCOMND
	lda	#6
	sta	DBYTLO
	lda	#0
	sta	DBYTHI
	lda	#<DBUFLO
	sta	DBUFLO
	lda	#>DBUFLO
	sta	DBUFHI
	lda	#GETDAT
	sta	DSTATS
	lda	chunk
	sta	DAUX1
	lda	chunk + 1
	sta	DAUX2
	jsr	sio_handler
	bmi	error

	; Load a chunk
	lda	#BOOTER_COMMAND_GET_CHUNK
	sta	DCOMND
	lda	#GETDAT
	sta	DSTATS
	jsr	sio_handler
	bmi	error
	lda	DUNUSE
	pha

	; Run the initialization code
	jsr	go_initad

	; Increase the chunk sequence number
	inc	chunk
	bne	:+
	inc	chunk + 1

	; DUNUSE = 0 means done
:	pla
	bne	main_loop

	; Tell that we are about to JMP to RUNAD
	lda	#BOOTER_COMMAND_NOTIFY_RUN
	sta	DCOMND
	lda	#NODAT
	sta	DSTATS
	lda	RUNAD
	sta	DAUX1
	lda	RUNAD + 1
	sta	DAUX2
	jsr	sio_handler
	; Don't check the error code, we're done anyway

	; Run the program
	jsr	go_runad

go_cold:
	jmp	COLDSV

go_initad:
	jmp	(INITAD)

go_runad:
	jmp	(RUNAD)

error:
	sei
	ldx	#0
	stx	DMACTL
	stx	NMIEN
	dex
	stx	COLDST
:	lda	VCOUNT
	sta	COLBK
	jmp	:-
