*----------------------------------------------------------
* PUNCH.ASM
*    Punch a range of memory to paper tape. Located in 
*    the 3712 OS PROM at $FE70
*----------------------------------------------------------
 
* Monitor equates

MON	equ	$FFAB		;return to monitor
RDWORD	equ	$FF62		;read 16 bit hex value
OUTHEX	equ	$FF6D		;output 8 bit hex value
OUTCH	equ	$FF81		;outout a character
XHI	equ	$00FA		;high byte from RDWORD
XLO	equ	$00FB		;low byte from RDWORD
DSPMSG	equ	$FD0F		;display null terminated message

* ASCII equates

CR	equ	$0D
LF	equ	$0A
DC2	equ	$12		;punch on
DC4	equ	$14		;punch off

* Data is on page zero

	org	$60
	
count	rmb	1		;line byte counter
chkSum	rmb	1		;checksum on line
atEnd	rmb	1		;0=end reached		
memPtr	rmb	2		;current pointer into memory

* Start of program

	org	$FE70

	ldx	#mBeg		;get start address
	jsr	DSPMSG
	jsr	RDWORD
	stx	memPtr

	ldx	#mEnd		;get end address
	jsr	DSPMSG
	jsr	RDWORD		;saves in XHI,XLO

* Punch the S-records

	ldab	#DC2		;turn on punch
	jsr	OUTCH
	ldaa	#30		;punch 30 nulls
	bsr	nulls

doLine	ldx	#mS113		;CR/LF S113
	jsr	DSPMSG

	ldx	memPtr		;point to memory to punch
	ldaa	#17		;punch 16 bytes +1 address byte
	staa	count
	staa	atEnd		;cleared to zero if end reached

	ldaa	#19		;total byte count on line
	adda	memPtr		;init checksum with 1st two bytes
	staa	chkSum
	
	ldaa	memPtr		;punch first address byte
	jsr	OUTHEX
	ldaa	memPtr+1	;punch 2nd address byte 
	bra	punchA

* punch the bytes within a line

doByte	ldaa	0,x		;A=next byte to punch
	inx
punchA	tab			;update checksum
	addb	chkSum
	stab	chkSum
	jsr	OUTHEX		;punch the byte
	cpx	XHI		;reach end?
	bne	nxtByte		;no
	clr	atEnd		;else, indicate we're done
nxtByte	dec	count
	bne	doByte		;punch full 16 byte line

	ldaa	chkSum		;punch the checksum
	eora	#$FF		;1s compliment
	jsr	OUTHEX

	stx	memPtr		;save current memory address
	ldaa	atEnd		;did we reach the end?
	bne	doLine		;no

* Punch S9 and a trailer of nulls

	ldx	#mS9		;end
	jsr	DSPMSG

	ldaa	#10		;10 trailing nulls
	bsr	nulls		;punch trailer
	ldab	#DC4		;punch off
	jsr	OUTCH
	jmp	MON		;return to monitor

* nulls - Punch the number of nulls in A
		
nulls	clrb
	jsr	OUTCH
	deca
	bne	nulls
	rts

* Messages and data

mBeg	fcc	'START: '
	fcb	0

mEnd	fcc	'END: '
	fcb	0

mS113	fcb	$08		;give more CR time (BS does nothing)
	fcc	'S113'
	fcb	0

mS9	fcc	'S9'
	fcb	0

	end
