\ Convert a binary file to a file containing S-records.
\
\ To use from the command line:
\
\	forth srec.fth -s "to-srecs input-filename output-filename"
\
\ to-srecs  \ input-filename output-filename  ( -- )
\	"input-filename" is the name of a file containing binary data
\	(just data; no headers or anything else).  to-srec creates a
\	file named "output-filename", and stores in it the S-record
\	representation of the binary data in the input file.

h# 20 constant max-srec

variable checksum
variable load-address

create outchars ," 0123456789ABCDEF"

: fcr		( fd -- )	newline-pstring count rot fputs  ;

\ Split a longword into its constituent bytes
: lbsplit	( l -- lowbyte lmbtye hmbyte highbyte )
	dup  h# ff and  swap 8 rshift
	dup  h# ff and  swap 8 rshift
	dup  h# ff and  swap 8 rshift
	     h# ff and ;

: .nibble	( n -- )  \ Output a hex nibble
 	h# 0f and  outchars char+ swap chars+ c@  ofd @ fputc ;

: .byte	( byte -- ) \ output a hex byte and accumulate the checksum
	dup checksum +!
	dup 4 rshift .nibble .nibble ;

: .addr	( l.address -- )  \ Output a 24-bit hex address and checksum
	lbsplit drop .byte .byte .byte ;

: .data	( address count -- )  \ Output the count data bytes starting at addr
	bounds  do i c@ .byte  loop ;

: .srec ( mem-address count -- )  \ Output a data S-record
	" S2" ofd @ fputs  0 checksum !
	dup 4 + .byte		( load-address mem-address count )  \ output the count field
	load-address @ .addr	( address count )
	dup load-address +!
	.data
	checksum @  not  .byte
	ofd @ fcr ;

max-srec buffer: ibuf

\ Output data S-records until the count is exhausted
: .srecs  ( load-adr -- )
	load-address !
	" S204000000FB" ofd @ fputs  ofd @ fcr   \ Header record
	begin	ibuf max-srec
		ifd @ fgets  dup 0>
	while		( actual-length )
		ibuf swap .srec
	repeat
	drop
	" S804000000FB" ofd @ fputs  ofd @ fcr	\ Trailer record
	ofd @ fclose ;
: to-srecs  \ input-filename output-filename  ( -- )
	reading  writing  0 .srecs ;
