;
; MOS Papertape Checksum Calculator - by Dave Hassler, Dec. '22
;
; Calculates the checksum of any-sized record in a MOS Papertape file
; (so *you* don't have to!).  It's handy for cropping the "extra" off
; the end of a PTP, so it won't overwrite something else you want to
; keep.  By "extra" I mean that the KIM TTY monitor spits out a
; 24-byte-long record when it makes a papertape dump.  I can't do that 
; much hexidecimal addition in my head, and it's extra hard when the
: bytes all run together.
;
; This program expects addresses as 4 digits and bytes counts as
; 2 digits.  It uses Zero Page locations $EA-$EE.  And, if entered as
; a subroutine, it will clobber all three registers.  You're welcome!
;
; To use, just enter the starting address corresponding to the line of
; the paper tape file, then the number of bytes to be "summed."
; E.g., you have this as the last data record in a PTP file:
;
;    ;1801D010CF6002C3037E112233445566778899AABBCCDDEEFF00000B66
;
; That's getting perilously close to the stack, and you don't need all
; the "extra" stuff after $01D6 anyway.  Just run the checksum calculator
; with 01D0 as the starting address and ask for 07 bytes.  Then you can
; chop off the end in the PTP record line in a text editor, edit the
; number of bytes at the start of the line, and add the new checksum, 
; 035D, to the end, like so:
;
;    ;0701D010CF6002C3037E035D
; 
; That's about it.  Feel free to make changes or improvements.  DHH


CHKSUM = $EA			; loc. of checksum as built (2 bytes)
STORAD = $EC			; storage for st addr & # bytes

* = $1340

	CLD
	LDA #$00
	STA $EA
	STA $EB
	JSR $1E2F
TITLE	LDX #MSG2-MSGBAS    	; welcome line
        JSR SNDMSG
	JSR $1E2F

STARTA	LDX #MSG3-MSGBAS    	; enter starting addr to check
        JSR SNDMSG
	JSR $1F9D		; call GETBYT
	STA STORAD+1		; store high byte
	JSR $1F9D		; call GETBYT
	STA STORAD		; store low byte
	JSR $1E2F		; CRLF

BYTENO	LDX #MSG4-MSGBAS	; enter # of bytes in record
        JSR SNDMSG
GETBYT	JSR $1F9D		; get a byte
	CMP #$19		; compare it with #25 dec.
	BCS GETBYT		; if >= #25, get another
	STA STORAD+2		; store the #

	TAX			; set up loop
	LDY #$00		; set up index counter
LOOP1	CLC
	LDA CHKSUM		; get LSB of checksum
	ADC (STORAD),Y		; add with byte from addr range
	STA CHKSUM		; store it
	LDA CHKSUM+1		; same with MSB
	ADC #$00
	STA CHKSUM+1
	INY
	DEX
	BEQ LASTAD		; if 0 go add the last parts
	BNE LOOP1

LASTAD	LDX #$00
LOOP2	CLC			; get ready for addition
	LDA CHKSUM		; load the checksum LSB
	ADC STORAD,X		; add to A what's in LSB of checksum
	STA CHKSUM		; and store it
	LDA CHKSUM+1		; load A with MSB of checksum
	ADC #$00
	STA CHKSUM+1		; store it
GOBAK2	INX
	CPX #03			; looped 3x?
	BEQ RESULT		; yes, to result
	BNE LOOP2		; no, keep looping

RESULT	JSR $1E2F		; CRLF
	LDX #MSG5-MSGBAS	; display checksum msg
        JSR SNDMSG
	LDA CHKSUM+1		; get MSB and print
	JSR $1E3B
	LDA CHKSUM		; get LSB and print
	JSR $1E3B
	JSR $1E2F		; CRLF
	
	BRK			; done (could be RTS, too)


; display message from table (style snatched from JMON by Jeff Tranter)
SNDMSG	LDA MSGBAS,X
	BEQ RETRN2	
	JSR $1EA0
	INX
	BNE SNDMSG
RETRN2	RTS


; message table; terminating character $00
MSGBAS  =*

MSG2
.BYTE "PTP CHECKSUM CALC"
.BYTE $00

MSG3
.BYTE "Address: "
.BYTE $00

MSG4
.BYTE "No. bytes <$19: "
.BYTE $00

MSG5
.BYTE "Checksum = "
.BYTE $00
