// Tar-format tape boot -- accepts name of file to read off tar tape and
//  execute.  Assumes tm11-compatible tape drive, at least 56KB memory, and
//  processor with SOB and EIS.

	halt=0
	console=177560
	tmaddr=172520
	k=1024.
	me=55.*k		// Where boot relocates self to.

	// Relocate self to top, if not there already.
	rsrc=r1
	rdst=r2
	rcnt=r3
	cmp pc, $me		/ Are we up that high already?
	bhis setup
	clr rsrc		/ No: copy us up and transfer control.
	mov $me, rdst
	mov $512.\/2, rcnt	//  /2 for words, not bytes
1:		mov (rsrc)+, (rdst)+
		sob rcnt, 1b
	jmp *$me+setup

setup:
	// Set up environment.
	mov $me+stack, sp

	// Get name.
	rptr=r1
	mov $me+name, rptr
	mov $'-, r0		/ prompt
	jsr pc, putch
1:		jsr pc, getch
		cmp r0, $'\n		/ Is NL?
		beq 1f
		movb r0, (rptr)+	/ No: save it.
		br 1b
1:	clrb (rptr)+		/ supply trailing NUL

	// Rewind magtape
	mov $me+tmrew, r0
	jsr pc, tm

	// Master loop.
loop:

	// Get tar header block.
	mov $me+tmbuf, r0
	jsr pc, tm

	// Check name.
	rname=r1
	rtar=r2
	mov $me+buf, rtar
	mov $me+name, rname
1:		cmpb (rname), (rtar)+
		bne 2f
		tstb (rname)+
		beq found
		br 1b

2:	// Wasn't it.  Damn.  Skip rest of file.
	rskip=r4
	jsr pc, getsize
	div $512., r0		// Convert to block count.
	tst r1			// Remainder?
	beq 1f
	inc r0			// Yes:  quotient += 1
1:
	mov r0, rskip
1:		mov $me+tmskip, r0
		jsr pc, tm
		sob rskip, 1b

	// And go back and try again.
	br loop

found:	// Found the file!!!

	// Try to figure out what it is.
	mov $me+tmbuf, r0
	jsr pc, tm
	mov buf, r0
	cmp r0, $407		// Unix file?
	beq unixload
/	cmp r0, $1		// DEC absloader file?
/	beq decload
	halt			// Je ne comprends pas.

unixload:
	raddr=r2
	rcount=r3
	rbuf=r4
	rbss=r5

	// Pick up the header.
	mov $me+buf+2, rbuf
	mov (rbuf)+, rcount
	add (rbuf)+, rcount
	mov (rbuf)+, rbss
	add $10, rbuf
	clr raddr

	// Copy remainder of first block.
	mov $[bufsize-20]\/2, r0
	sub r0, rcount
1:		mov (rbuf)+, (raddr)+
		sob r0, 1b

	// Read blocks until text and data all in.
	tst rcount
	beq 2f
1:		mov raddr, tmread
		mov $me+tmread, r0
		jsr pc, tm
		add $512., raddr
		sub $512., rcount
		bhi 1b

	// Fix up raddr after possibly reading more than wanted.
2:	add rcount, raddr		// rcount has gone negative

	// Zero out bss area.
	tst rbss
	beq 9f
1:		clrb (raddr)+
		sob rbss, 1b

	// Rewind the magtape and go.
	mov $me+tmrew, r0
	jsr pc, tm
9:	clr pc				// jmp *$0


/-------------------------------------------------------------------------
/ get long-int size from a tar header block (field is octal ascii)

getsize:
	rscan=r2
	rtmp=r3

	mov $me+buf+124., rscan		// 124. is offset to size

	// Scan leading blanks and zeros.
1:		bitb (rscan)+, $7	// (' '&07) == ('0'&07) == 0
		beq 1b
	dec rscan

	clr r0
	clr r1
1:		movb (rscan)+, rtmp
		cmpb rtmp, $40		// SP ends it
		beq 1f
		bic $!7, rtmp
		ashc $3, r0
		bis rtmp, r1
		br 1b

1:	rts pc

/-------------------------------------------------------------------------
/ console i/o -- getch and putch tie together for echoing

getch:
	tks=console+0
	tkb=console+2

1:	tstb *$tks		// Await ready bit.
	bpl 1b
	movb *$tkb, r0		// Got it.
	bic $!177, r0		// Dispose of extraneous bits, if any.
	jsr pc, putch		// Echo it.

	cmp r0, $'\r		// If CR, turn into NL and echo CR-LF.
	bne 9f
	mov $'\n, r0
	// And fall through into echoing.

putch:
	tps=console+4
	tpb=console+6

	movb r0, *$tpb		// Hit it.
1:	tstb *$tps		// Await done bit.
	bpl 1b
9:	rts pc			// Common return for getch and putch.


/-----------------------------------------------------------------------
/ magtape handling

tm:
	rdev=r1

	mov $tmaddr+6, rdev	// 6 is offset to bus address
	mov (r0)+, (rdev)
	mov (r0)+, -(rdev)	// count
	mov (r0)+, -(rdev)	// command
	// Spin until operation finished.
1:		tstb (rdev)
		bpl 1b
	// Spin until tape halts.
1:		bit $10000, 10(rdev)
		bne 1b
	// Success or failure?
	tst (rdev)
	bpl 1f			// branch on success
	tst (r0)+
1:	mov (r0), r0		// next-op ptr, either success or failure.
	bne tm			// if nonnull, do it
	rts pc

// Command structures.  Contents are:
//	bus addr
//	count (negative!)
//	command
//	next command on success
//	next command on failure
// A next command of 0 means terminate.
	cmdrew=60017
	cmdskip=60011
	cmdback=60013
	cmdread=60003

tmrew:	0
	0
	cmdrew
	0
	me+tmrew		// try again on failure

tmskip:	0
	-1
	cmdskip
	0
	0			// skip probably did succeed

tmbuf:	me+buf
	-512.
	cmdread
	0
	me+1f

1:	0
	-1
	cmdback
	me+tmbuf
	me+tmbuf		// skip probably did succeed

tmread:	0			// in here goes the address
	-512.
	cmdread
	0
	me+1f

1:	0
	-1
	cmdback
	me+tmread
	me+tmread		// skip probably did succeed

.bss
name:	.=.+100.
stack=name+100.		// Not bottom addr -- one word past top.
buf=-512.		// Below "me".
bufsize=512.
