*******************************************************************
*
*  BINLOAD.ASM
*    Binary loader for the Altair 680 cassette interface board.
*    Uses the same data record sync and jump record sync bytes
*    as the 8800 format tapes.
*
*    Mike Douglas, July 24, 2022
*
*******************************************************************
OUTCH	equ	$FF81		;display char from B (in monitor)
OUT2H	equ	$FF6D		;output A in hex
SIOSR	equ	$F010		;cassette UART status register
SIODR	equ	$F011		;data register

DATAREC	equ	$3C		;flag that a data record follows
JUMPREC	equ	$78		;flag that a jump record follows

*----------------------------------------------------------------
*  The loader is located at $3F00 at the top of the 1st
*  16K RAM board. 
*----------------------------------------------------------------
	org	$3F00		;loader at top of 1st 16K
	
main	bsr	casRead		;look for a sync byte
	cmpb	#DATAREC	;data record?
	beq	loadRec		;yes
	
	cmpb	#JUMPREC	;jump record?
	bne	main		;no, keep looking

	bsr	getAddr		;get jump-to address in X
	jmp	0,x		;jump to loaded code
	
* loadRec - Load a data record

loadRec	bsr	getAddr		;get pointer in X for data

	ldab	#$0D		;display the address we're on
	jsr	OUTCH
	ldab	#$0A
	jsr	OUTCH
	ldaa	saveX
	jsr	OUT2H
	ldaa	saveX+1
	jsr	OUT2H
	
	bsr	casRead		;get byte count to read
	stab	byteCnt
	clra			;init checksum
	
loadLp	bsr	casRead		;load, save, and verify byte
	stab	0,x
	cmpb	0,x
	bne	memErr
	
	aba			;update checksum
	inx
	dec	byteCnt
	bne	loadLp
	
	bsr	casRead		;read checksum
	sba
	bne	csumErr		;didn't match
	
	bra	main		;else, look for next record

* getAddr - Read two byte address from the cassette interface
*   and return it in X

getAddr	bsr	casRead		;get MSB
	stab	saveX
	bsr	casRead		;get LSB
	stab	saveX+1
	ldx	saveX		;X contains the address
	rts

* csumErr, memErr - Die in a loop displaying the error code

csumErr	ldab	#'C		;display C for checksum errors
	bra	dieLoop
	
memErr	ldab	#'M		display M for memory errors

dieLoop	jsr	OUTCH		;die here sending error code
	bra	dieLoop

* casRead - Read a byte from the cassette serial port into B

casRead	ldab	SIOSR		;wait for new byte
	rorb
	bcs	casRead

	ldab	SIODR		;load and return byte
	rts
	
* Data area

saveX	rmb	2
byteCnt	rmb	1

	end
