Google
 

Trailing-Edge - PDP-10 Archives - ks10_8080_microcode - pblast.mac
There are no other files named pblast.mac in the archive.
;<TAPE-ENG-SYSTEM-FILE-AREA>BLAST.MAC.2, 22-Oct-80 10:32:35, Edit by KINZELMAN
;Fixed missing byte on packed output mode
;<KINZELMAN.TMP>BLAST.MAC.2, 23-Jan-80 16:22:07, Edit by KINZELMAN
TITLE	BLAST - PROGRAM TO SEND PROM DATA TO PROM PROGRAMMER

VERSION=1			;PROGRAM VERSION NUMBER
EDIT=5				;PROGRAM EDIT NUMBER

SUBTTL	DEFINITIONS

SEARCH MONSYM,MACSYM

	P=17
	T1=5
	T2=6
	T3=7
	T4=10
	T5=11
	S1=12
	S2=13
	S3=14
	S4=15
	S5=16
;A MACRO TO POSITION A VALUE INTO A FIELD SPECIFIED BY A MASK

DEFINE FLD(DATA,MASK),<<MASK>&<<DATA>B<^L<<MASK>^!<<MASK>-1>>>>>

;SOME MESSAGE PRINT MACROS

;PMSG - PRINT MESSAGE
DEFINE PMSG(MSG),<
	HRROI	1,[ASCIZ\MSG\]
	PSOUT
>

;PMSGC - PRINT MESSAGE AND END WITH A <CR><LF>
DEFINE PMSGC(MSG),<
	HRROI	1,[ASCIZ\MSG
\]
	PSOUT
>

;PCMSG - PRINT MESSAGE AFTER A <CR><LF>
DEFINE PCMSG(MSG),<
	HRROI	1,[ASCIZ\
MSG\]
	PSOUT
>

;PCMSGC - PRINT MESSAGE WITH A <CR><LF> BEFORE AND AFTER
DEFINE PCMSGC(MSG),<
	HRROI	1,[ASCIZ\
MSG
\]
	PSOUT
>

;PVER - PRINT PROGRAM NAME AND VERSION
DEFINE	PVER(NAME,VERSION,EDIT),<
	PMSGC	<NAME  V'VERSION(EDIT)>
>

	SALL
SUBTTL	INITIALIZATION

LOC	137
	<VERSION>B12+EDIT	;STORE PROGRAM VERSION

START:	RESET
	MOVE	P,PLIST		;SET UP STACK POINTER

;PRINT PROGRAM NAME AND VERSION

	PVER	BLAST,\VERSION,\EDIT

;INITIALIZE THE PARAMETERS

	SETZM	FIRST		;FIRST ADDRESS IS 0
	SETZM	LAST		;LAST ADDRESS NOT SPECIFIED
	SETZM	SIZE		;SIZE NOT SPECIFIED
	SETZM	BYTE		;BYTE POSITION NOT SPECIFIED
	SETZM	FILL		;NULL CHARACTER IS 000
	SETZM	FILE		;NO JFN EXISTS
	SETZM	TYPE		;FILE TYPE NOT SPECIFIED
	SETZM	INVERT#		;SET NOINVERT MODE
	MOVEI	^D10		;ADDRESS INPUT RADIX IS DECIMAL
	MOVEM	RADIX
	SETZM	COMBUF		;CLR OUT OLD COMMENT
	SETZM	LSTJFN		;CLR OUT LIST JFN KEEPER
	SETZM	BINMOD#		;CLR OUT BINARY MODE FLG

SUBTTL	COMMAND DECODER

;GET A COMMAND

COMAND:	MOVE	P,PLIST		;SET UP STACK POINTER
	MOVEI	1,[	REPARS
			.PRIIN,,.PRIOU
			POINT 7,[ASCIZ/BLAST>/]
			POINT 7,CMDBUF
			POINT 7,CMDBUF
			CMDBFS*5
			0
			POINT 7,ATOMBF
			ATOMBS*5
			JFNBF			]
	MOVEI	2,[FLDDB. (.CMINI)]	;INITIALIZE
	COMND
	TLNE	1,(CM%NOP)	;CHECK IF ERROR
	 ERJMP	EROUT			;ERROR

REPARS:	MOVEI	2,[FLDDB. (.CMKEY,,F1)]
	COMND
	TLNE	1,(CM%NOP)
	 JRST	EROUT			;ERROR
	HRRZ	@2		;GET ADDRESS OF REQUESTED ROUTINE
	JRST	@0		;GO TO ROUTINE
SUBTTL	FILE COMMAND

;FILE ROUTINE
;GET A FILE NAME TO USE

FILENM:	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/to use/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	MOVEI	2,[FLDDB. (.CMIFI)]
	COMND			;GET A FILE NAME
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	MOVEM	2,T1		;SAVE JFN
	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/of type/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	PUSH	P,1		;SAVE COMAND ARG
	HRROI	1,TEMPBF	;GET TYPE FIELD FROM FILE NAME
	MOVE	2,T1		;GET JFN
	MOVSI	3,(FLD(1,JS%TYP))	;ASK FOR TYPE FIELD ONLY
	JFNS
	 ERJMP	EROUT
	MOVEI	1,TYPFLD	;COMPARE WITH RECOGNIZED TYPES
	HRROI	2,TEMPBF	;TYPE FIELD IS IN TEMPBF
	TBLUK
	TLNN	2,(TL%EXM)	;CHECK IF AN EXACT MATCH
	JRST	FTUNK		;NO
	MOVSI	(CM%DPP)	;GET DEFAULT STRING EXISTS BIT
	ORM	TYPCMD		;PUT INTO FUNCTION DESCRIPTOR BLOCK
	HRROI	TEMPBF		;GET POINTER TO TYPE STRING
	MOVEM	TYPCMD+.CMDEF	;PLACE IN FUNCTION DESCRIPTOR BLOCK
	JRST	FTASK
FTUNK:	MOVSI	(CM%DPP)	;GET DEFAULT STRING EXISTS BIT
	ANDCAM	TYPCMD		;CLEAR BIT IN FUNCTION DESCRIPTOR BLOCK
FTASK:	POP	P,1		;GET BACK COMND ARG
	MOVEI	2,TYPCMD	;POINT TO FUNCTION DESCRIPTOR BLOCK
	COMND			;ASK FOR TYPE OF FIELD
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	HRRZ	T2,@2		;GET POINTER TO TYPE
	MOVEI	2,[FLDDB. (.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	FILEER

	SKIPN	FILE		;CHECK IF A JFN ALREADY ASSIGNED
	JRST	FILEDO		;NO
	MOVE	1,FILE		;YES, GET OLD JFN
	RLJFN			;RELEASE THE OLD JFN
	 ERJMP	EROUT
FILEDO:	MOVEM	T1,FILE		;PUT JFN IN PARAMETER TABLE
	MOVEM	T2,TYPE		;PUT TYPE IN PARAMETER TABLE
	JRST	COMAND		;GO GET NEXT COMMAND

FILEER:	MOVE	1,T1		;GET NEW JFN
	RLJFN			;RELEASE JFN AGAIN
	 ERJMP	EROUT
	JRST	EROUT

TYPCMD:	FLD(.CMKEY)+CM%DPP	;FILE DESCRIPTOR BLOCK
	TYPFLD			;TO INPUT FILE TYPE
	0
	POINT 7,TEMPBF		;DEFAULT IS IN TEMPBF

SUBTTL	EXIT COMMAND

;EXIT ROUTINE

EXIT:	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/to monitor/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	MOVEI	2,[FLDDB. (.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	SETO	1,		;RELEASE ALL JFNS
	CLOSF
	 ERJMP	EROUT
	HALTF			;EXIT TO THE MONITOR
	JRST	COMAND		;RESTART IF CONTINUED
SUBTTL	SEND COMMAND

;SEND ROUTINE
;THIS ROUTINE ACTUALLY TRANSFERS THE DATA TO THE PROM PROGRAMMER

SEND:	MOVEM	1,SAVCMD#		;SAVE AC1 FOR LATER
;GET A JFN TO BLASTR:
	MOVSI	1,(GJ%FOU+GJ%SHT)
	HRROI	2,[ASCIZ/BLASTR:/]
	GTJFN			;GET A JFN
	 ERJMP	ERQUIT		;ERROR
	HRRZM	1,BLASTR	;SAVE JFN

;OPEN BLASTR: FOR OUTPUT IN BINARY MODE

	MOVSI	2,(8B5)		;8 BIT BYTES
	HRRI	2,OF%NWT+OF%RTD+OF%WR
	OPENF			;OPEN FILE
	 ERJMP	ERQT1			;ERROR
	DVCHR				;READ DEVICE CHARACTERISTICS
	 ERJMP	EROT1
	AND	2,[DV%TYP]		;KEEP ONLY DEVICE TYPE FIELD
	CAMN	2,[FLD(.DVTTY,DV%TYP)]	;CHECK TYPE WITH TTY CODE
	JRST	BTTY			;BLASTR: IS A TTY
	PMSGC	<?Device BLASTR: is not a TTY>
	RLJFN				;RELEASE BLASTER
	 ERJMP	EROUT
	HALTF				;STOP, ONLY PROCEED IF CONTINUED
	JRST COMAND			;THEN GO DIRECTLY TO COMAND

BTTY:	SETZ	2,			;SET JFN MODE WORD TO ZEROS
	SFMOD			;TO PUT IN BINARY MODE
	 ERJMP	EROT1
	STPAR			;AND SET WIDTH TO 0
	 ERJMP	EROT1

	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/data to programmer/]>)]
	MOVE	1,SAVCMD		;RESTORE AC1 FOR COMND
	COMND			;SEND GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROT1
	MOVEI	2,[FLDDB. (.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROT1
	PUSHJ	P,GENBUF	;GENERATE A BUFFER FULL OF DATA
	JRST	COMAND		;NO SKIP RTN IF NO DATA

	SKIPN	INVERT		;SKIP IF INVERT FLAG IS SET
	JRST	SENDGO		;BYPASS INVERSION OF DATA IF NOT
	MOVSI	1,-<PROMSZ/4>	;GET COUNT OF WORDS IN BUFFER
SENDI:	SETCMM	ROMBUF(1)	;COMPLIMENT THE DATA
	AOBJN	1,SENDI		;IN EACH BUFFER LOCATION

SENDGO:	PMSG	<Sending >
	SKIPE	INVERT		;SKIP IF NOT IN INVERT DATA MODE
	PMSG	<INVERTED >
	PMSG	<data to PROM programmer...>

	MOVEI	1,.PRIOU	;WAIT FOR TYPING TO STOP
	DOBE
	 ERJMP	EROT1

	MOVE	1,BLASTR	;GET JFN OF BLASTER
	MOVE	2,[POINT 8,ROMBUF]	;POINT TO ROM BUFFER
	MOVN	3,SNDSIZ	;GET NUMBER OF BYTES TO SEND
	SOUT			;SEND THE DATA TO THE PROGRAMMER
	 ERJMP	EROT1

	MOVE	1,BLASTR	;WAIT FOR OUTPUT BUFFER TO EMPTY
	DOBE
	 ERJMP	EROT1
	PMSGC	<done>
	MOVEI	1,.PRIOU		;PRINT ON TTY
	MOVE	2,SNDSIZ		;NUMBER OF BYTES SENT
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	 ERJMP	EROT1
	PMSGC	< bytes sent.>

	MOVE	1,BLASTR	;GET BLASTER JFN AGN
	CLOSF			;CLOSE OUT THE FILE
	 ERJMP	EROUT		;HERE IF ERROR

	JRST	COMAND		;GET NEXT COMMAND

EROT1:	PUSH	P,1		;SAVE AC1
	MOVE	1,BLASTR	;GET THE BLASTER JFN
	RLJFN			;AND RELEASE IT
	 JFCL
	POP	P,1		;RESTORE AC1
	JRST	EROUT

ERQT1:	PUSH	P,1		;SAVE AC1
	MOVE	1,BLASTR	;GET THE BLASTER JFN
	RLJFN			;AND RELEASE IT
	 JFCL
	POP	P,1
	JRST	ERQUIT
SUBTTL	GENERATE BUFFER OF DATA FOR PROM

;GENBUF ROUTINE
;THIS ROUTINE CAUSES THE FILE TO BE READ AND THE SPECIFIED RANGE
;OF ADDRESSES TO BE FILLED WITH DATA BYTES IN ROM BUFFER.
;THIS ROUTINE USES THE PARAMETER TABLE ENTRIES TO DETERMINE
;INPUT FILE AND ADDRESS RANGE.
;THE ACTUAL SIZE OF THE ROM BUFFER THAT WAS FILLED IS RETURNED
;IN SNDSIZ.  THE ACTUAL LAST ADDRESS IN THE ROM BUFFER IS RETURNED
;IN SNDLST.
;IF ERRORS OCCUR, A MESSAGE IS PRINTED AND CONTROL IS TRANSFERRED
;DIRECTLY TO COMAND.
;IF NO DATA IN WINDOW OF INTEREST, WE DON'T SKIP RTN. IF DATA THERE,
;SKIP RTN

GENBUF:	SKIPN	FILE		;CHECK IF A FILE WAS SPECIFIED
	JRST	[PMSGC <?No file was specified.>
		 JRST COMAND ]

	MOVE	T1,LAST		;GET LAST ARGUMENT FROM PARAM TABLE
	PUSHJ	P,COMPS		;COMPUTE SIZE OF PROM
				;LAST ADDRESS IS PLACED IN SNDLST
				;SIZE IS PLACED IN SNDSIZ

	PUSHJ	P,FILLBF	;WRITE FILL CHARACTER INTO BUFFER

	SETZM	TCOUNT#		;CLEAR TOTAL BYTE COUNT OF FILE
	SETZM	COUNT#		;CLEAR COUNT OF LOCATIONS FULL
	SETZM	HIGH#		;CLEAR HIGH ADDRESS FULL IN BUFFER

	HLRZ	T1,@TYPE		;GET ADDRESS OF SELECTED INIT ROUTINE
	PUSHJ	P,@T1		;INIT FILE READ ROUTINE
	HRRZ	T1,@TYPE	;GET ADDRESS OF READ BYTE ROUTINE
GENLOP:	PUSHJ	P,@T1		;READ A DATA BYTE
				;ROUTINES RETURN DATA BYTE IN T2
				;AND ADDRESS OF BYTE IN T3
				;ON NORMAL SKIP RETURN
	 JRST	DONE		;NON-SKIP RETURN MEANS END OF FILE

	AOS	TCOUNT		;COUNT BYTES READ FROM FILE
	CAML	T3,FIRST	;CHECK IF ADDRESS IS IN RANGE OF PROM
	CAMLE	T3,SNDLST
	JRST	GENLOP		;NO, GO GET NEXT BYTE

	CAMLE	T3,HIGH		;CHECK IF ADDRESS IS HIGHEST SO FAR
	MOVEM	T3,HIGH		;YES, PUT IN HIGH

	AOS	COUNT		;COUNT BYTES IN RANGE

	MOVE	T4,T3		;COPY ADDRESS TO T4
	SUB	T4,FIRST	;COMPUTE INDEX INTO ROM BUFFER
	IDIVI	T4,4		;T4-WORD INDEX, T5-BYTE INDEX OF WORD
	DPB	T2,[POINT 8,ROMBUF(T4),7
		    POINT 8,ROMBUF(T4),15
		    POINT 8,ROMBUF(T4),23
		    POINT 8,ROMBUF(T4),31 ](T5)	;DEPOSIT BYTE
	JRST	GENLOP		;GO BACK FOR NEXT BYTE
DONE:	PMSG	<File contains >
	MOVEI	1,.PRIOU	;OUTPUT TO TERMINAL
	MOVE	2,TCOUNT	;COUNT OF BYTES IN FILE
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	 ERJMP	EROUT
	PMSG	< bytes, >
	CAME	2,COUNT		;CHECK IF SAME AS BYTES IN RANGE
	JRST	DONEP1		;NO
	PMSG	<all>
	JRST	DONEP3
DONEP1:	MOVE	2,COUNT		;GET COUNT IN RANGE
	JUMPE	2,DONEP2	;CHECK IF ANY IN RANGE
	MOVEI	1,.PRIOU	;OUTPUT TO TERMINAL
	NOUT			;NUMBER IN RANGE
	 ERJMP	EROUT
	JRST	DONEP3
DONEP2:	PMSG	<none>
DONEP3:	PMSGC	< of which are in range of PROM addresses.>
	JUMPE	2,DONEX		;IF NONE IN RANGE, STOP NOW

	MOVE	T1,LAST		;GET LAST PARAMETER
	OR	T1,SIZE		;AND SIZE PARAMETER
	JUMPN	T1,DONEOK	;IF EITHER ARE SPECIFIED, RETURN NOW

	MOVE	T1,HIGH		;REDUCE ROM BUFFER TO ACTUAL SIZE OF
	CAMGE	T1,SNDLST	;DATA FROM FILE
	PUSHJ	P,COMPS		;COMPUTE SIZE USING ACTUAL HIGH ADDRESS
	PMSG	<No size was specified, so defaulting to the following (in >
	MOVE	3,RADIX		;GET ADDRESS RADIX
	CAIN	3,^D8		;IF OCTAL
	HRROI	1,[ASCIZ/octal)/]
	CAIN	3,^D10		;OR IF DECIMAL
	HRROI	1,[ASCIZ/decimal)/]
	PSOUT			;PRINT RADIX
	PCMSG	<   FIRST address >
	MOVEI	1,.PRIOU	;PRINT ON TERMINAL
	MOVE	2,FIRST		;THE FIRST ADDRESS
	NOUT
	 ERJMP	EROUT
	PCMSG	<   LAST  address >
	MOVEI	1,.PRIOU	;PRINT ON TERMINAL
	MOVE	2,SNDLST	;THE LAST ADDRESS
	NOUT
	 ERJMP	EROUT
	PMSGC	<>
DONEOK:	AOS	(P)		;INCR THE RTN ADR FOR NO ERROR
DONEX:	MOVE	1,FILE		;GET JFN
	HRLI	1,(CO%NRJ)	;CLOSE FILE, DON'T RELEASE JFN
	CLOSF
	ERJMP	EROUT
	POPJ	P,		;RETURN NOW
;COMPUTE SIZE ROUTINE

;THIS ROUTINE TAKES ONE ARGUMENT IN T1 WHICH IT USES AS THE
;LAST ADDRESS SPECIFIED (UNSPECIFIED IF T1 CONTAINS ZERO).
;IF T1 IS POSITIVE, A PROM SIZE IS CALCULATED.
;IF T1 IS ZERO, THE PARAMETER SIZE IS USED TO CALCULATE LAST ADDRESS:
;IF SIZE IS ZERO, MAXIMUM PROM SIZE IS USED.
;IF SIZE IS POSITIVE, THE SIZE PARAMETER IS USED.

COMPS:	JUMPE	T1,COMPSS	;CHECK IF A LAST PARAM IS SPECIFIED

	MOVEI	T2,1(T1)	;YES, GET ONE GREATER
	SUB	T2,FIRST	;COMPUTE SIZE OF BUFFER
	JUMPLE	T2,[PMSGC <?LAST address is not greater than FIRST address.>
			JRST COMAND ]
	CAILE	T2,PROMSZ	;CHECK IF SIZE IS NOT TOO LARGE
	JRST	[PMSG <?Size between FIRST and LAST addresses is greater than maximum of >
		MOVEI	1,.PRIOU	;OUTPUT TO TERMINAL
		MOVEI	2,PROMSZ	;MAXIMUM SIZE OF PROM
		MOVEI	3,^D10		;IN DECIMAL
		NOUT
		 ERJMP	EROUT
		PMSGC	< bytes.>
		JRST	COMAND ]
	JRST	COMPSX

COMPSS:	SKIPN	T2,SIZE		;CHECK IF SIZE WAS SPECIFIED
	MOVEI	T2,PROMSZ	;NO, GET MAXIMUM
	MOVE	T1,FIRST	;COMPUTE LAST ADDRESS
	ADDI	T1,-1(T2)	;USING SIZE AND FIRST

COMPSX:	MOVEM	T1,SNDLST#	;STORE LAST ADDRESS
	MOVEM	T2,SNDSIZ#	;STORE SIZE OF PROM
	POPJ	P,		;RETURN

;FILL BUFFER WITH NULL CHARACTERS

FILLBF:	MOVE	T1,FILL		;GET FILL CHARACTER
	MOVE	T2,[POINT 8,ROMBUF]	;POINTER TO BUFFER
	MOVE	T3,SNDSIZ	;SIZE OF BUFFER IN BYTES

FILLUP:	IDPB	T1,T2		;DEPOSIT A BYTE
	SOJG	T3,FILLUP	;COUNT THE BYTES
	POPJ	P,
SUBTTL	PRINT COMMAND

;PRINT ROM DATA ROUTINE

PRINT:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/data to/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,[FLDDB.(.CMOFI,,,,TTY:BLAST.PNT)]
	COMND			;GET FILE NAME, DEFAULT TO TTY:
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	2,PRJFN#	;SAVE JFN
	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	PUSHJ	P,GENBUF	;READ FILE AND GET BUFFER OF DATA
	JRST	COMAND		;NO SKIP RTN IF NO DATA

	MOVE	1,PRJFN		;GET OUTPUT FILE JFN
	MOVSI	2,(FLD(7,OF%BSZ))	;7 BIT BYTES
	HRRI	2,OF%WR		;OPEN FILE FOR WRITING
	OPENF
	 ERJMP	EROUT

	SETZM	RELFLG		;CLR OUT FLG TO SAY NOT LIST OR OUTPUT
	SKIPA			;SKIP OVER OUTPUT OR RELEASE ENTRY

	;ENTER HERE FROM OUTPUT OR RELEASE
LISTIT:	MOVE	1,LSTJFN		;GET LISTING JFN AGN
	HRROI	2,[ASCIZ/
BLAST		/]
	SETZ	3,
	SOUT			;PRINT HEADER
	 ERJMP	EROUT

	SETOB	2,3		;PRINT DATE AND TIME
	ODTIM
	 ERJMP	EROUT

	HRROI	2,[ASCIZ/

Input File Name  /]
	SETZ	3,
	SOUT			;PRINT HEADER FOR FILE NAME
	 ERJMP	EROUT

	MOVE	2,FILE		;GET INPUT JFN
	MOVE	3,[111110,,004011]	;SET FLAGS
	JFNS			;PRINT FILE NAME
	 ERJMP	EROUT
	;NOW LET'S SEE IF WE'RE DOING RELEAS OR OUTPUT

	SKIPN	RELFLG		;SKIP IF RELEASE OR OUTPUT CMD
	JRST	NOTRO		;HERE IF NOT, DON'T DO OUTPUT FILE NAME
	HRROI	2,[ASCIZ/
Output data file is  /]
	SETZM	3		;0 BYTE TERM
	SOUT
	 ERJMP	EROUT		;HERE IF ERROR
	HRROI	2,OFNAM		;POINT TO OUTPUT FILE NAME
	SETZM	3		;0 BYTE TERM
	SOUT
	 ERJMP	EROUT		;HERE IF ERROR

NOTRO:	MOVE	COMBUF		;GET THE 1ST COMMENT BUFFER WD
	TLNN	774000		;IS THERE ANYTHING THERE? (SKP IF YES)
	JRST	NOCOM		;JUMP HERE IF NO COMMENT
	HRROI	2,[ASCIZ/
Comment is     /]
	SETZM	3		;0 BYTE TERMINATOR
	SOUT			;OUTPUT IT
	 ERJMP	EROUT		;HERE IF ERROR
	HRROI	2,COMBUF	;POINTER TO COMMENT STRING
	SETZM	3		;0 BYTE TERMINATOR
	SOUT			;OUTPUT IT
	 ERJMP	EROUT		;HERE IF ERROR

NOCOM:	HRROI	2,[ASCIZ/
Author of ROM pattern is /]
	SETZM	3		;0 BYTE TERMINATOR
	SOUT			;OUTPUT IT
	 ERJMP	EROUT		;HERE IF ERROR
	HRROI	2,AUTHST	;POINTER TO AUTHOR STRING
	SETZM	3		;0 BYTE TERMINATOR
	SOUT			;OUTPUT IT
	 ERJMP	EROUT		;HERE IF ERROR

	HRROI	2,[ASCIZ/
First address /]
	SETZ	3,
	SOUT			;PRINT HEADER FOR FIRST ADDRESS
	 ERJMP	EROUT

	MOVE	2,FIRST		;PRINT FIRST ADDRESS
	MOVE	3,RADIX		;IN ADDRESS RADIX
	NOUT
	 ERJMP	EROUT
	MOVE	RADIX		;GET RADIX
	CAIN	^D8		;IF OCTAL
	HRROI	2,[ASCIZ/ (OCTAL)/]	;PRINT OCTAL
	CAIN	^D10		;IF DECIMAL
	HRROI	2,[ASCIZ/ (decimal)/]	;PRINT DECIMAL
	SETZ	3,
	SOUT
	 ERJMP	EROUT

	HRROI	2,[ASCIZ/
Last  address /]
	SETZ	3,
	SOUT			;PRINT HEADER FOR LAST ADDRESS
	 ERJMP	EROUT

	MOVE	2,SNDLST	;PRINT LAST ADDRESS
	MOVE	3,RADIX		;IN CURRENT ADDRESS RADIX
	NOUT
	 ERJMP	EROUT

	HRROI	2,[ASCIZ/
Size of PROM  /]
	SETZ	3,
	SOUT			;PRINT HEADER FOR SIZE
	 ERJMP	EROUT

	MOVE	2,SNDSIZ	;PRINT SIZE
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	 ERJMP	EROUT

	HRROI	2,[ASCIZ/ (decimal) bytes/]
	SETZ	3,
	SOUT
	 ERJMP	EROUT
	SKIPN	BYTE		;SKIP IF A BYTE POSITION SPECIFIED
	JRST	PRNB		;JUMP AROUND IF NOT
	HRROI	2,[ASCIZ/
Byte position /]
	SETZ	3,
	SOUT			;PRINT HEADER FOR BYTE POSITION
	 ERJMP	EROUT

	MOVE	2,BYTE		;PRINT BYTE
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	 ERJMP	EROUT

	SKIPN	SIZE		;SKIP IF SIZE HAS BEEN SPECIFIED
	JRST	PRNB	;NO
	MOVE	T1,FIRST	;GET FIRST ADDRESS
	IDIV	T1,SIZE		;CHECK IF A MULTIPLE OF SIZE
	JUMPN	T2,PRNB	;JUMP IF NOT
	HRROI	2,[ASCIZ/
Array position /]
	SETZ	3,
	SOUT
	  ERJMP	EROUT
	MOVE	2,T1		;GET MULTIPLIER
	MOVEI	3,^D10		;PRINT DECIMAL NUMBER
	NOUT
	  ERJMP	EROUT
	HRROI	2,[ASCIZ/,/]
	SETZ	3,
	SOUT
	  ERJMP	EROUT
	MOVE	2,BYTE	;PRINT BYTE POSITION IN ARRAY
	SOJ	2,
	MOVEI	3,^D10	;PRINT DECIMAL NUMBER
	NOUT
	  ERJMP	EROUT
PRNB:	HRROI	2,[ASCIZ/
Null character /]
	SETZ	3,
	SOUT			;PRINT HEADER FOR NULL CHARACTER
	 ERJMP	EROUT

	MOVE	2,FILL		;PRINT NULL CHARACTER
	MOVE	3,[NO%LFL+NO%ZRO+FLD(3,NO%COL)+8]	;IN OCTAL
	NOUT
	 ERJMP	EROUT

	SKIPE	RELFLG		;SKIP IF NOT RELEASING
	HRROI	2,[ASCIZ/
NOTE: In all cases, the first word of the releasable .DAT file will be
the flag word 377. This flag word is not shown on the following data map./]
	SETZ	3,
	SOUT
	 ERJMP	EROUT
	HRROI	2,[ASCIZ/

/]
	SETZ	3,
	SOUT
	 ERJMP	EROUT

	MOVE	RADIX		;PRINT RADIX
	CAIN	^D8
	HRROI	2,[ASCIZ/Octal  /]
	CAIN	^D10
	HRROI	2,[ASCIZ/Decimal/]
	SETZ	3,
	SOUT
	 ERJMP	EROUT
	HRROI	2,[ASCIZ/    Octal data in address
address     +0   +1   +2   +3   +4   +5   +6   +7/]
	SETZ	3,
	SOUT			;PRINT HEADER TO DATA TABLE
	 ERJMP	EROUT

	MOVE	RADIX		;GET RADIX OF ADDRESSES
	CAIE	^D10		;IF DECIMAL
	JRST	PROCTU
	HRROI	2,[ASCIZ/   +8   +9/]	;MAKE TABLE 10 COLUMNS
	SETZ	3,
	SOUT
	 ERJMP	EROUT

PROCTU:	HRROI	2,[ASCIZ/
-------    ---  ---  ---  ---  ---  ---  ---  ---/]
	SETZ	3,
	SOUT
	 ERJMP	EROUT
	MOVE	RADIX
	CAIE	^D10
	JRST	PROCTN
	HRROI	2,[ASCIZ/  ---  ---/]
	SETZ	3,
	SOUT
	 ERJMP	EROUT
PROCTN:	SETZM	S1			;CLR OUT 1ST LOC OF THIS ROM
	MOVE	S2,[POINT 8,ROMBUF]	;GET POINTER TO ROM BUFFER

PRTLOP:	HRROI	2,[ASCIZ/
/]
	SETZ	3,		;START A NEW LINE
	SOUT
	 ERJMP	EROUT

	MOVE	2,S1		;PRINT ADDRESS
	MOVE	3,RADIX
	HRLI	3,(NO%LFL+FLD(5,NO%COL))	;IN FIVE DIGIT FIELD
	NOUT
	 ERJMP	EROUT

	HRROI	2,[ASCIZ\ /  \]	;PRINT SLASH
	SETZ	3,
	SOUT
	 ERJMP	EROUT

	MOVE	S3,RADIX	;GET COUNT OF COLUMNS TO PRINT
PRTLPD:	HRROI	2,[ASCIZ/  /]	;SEPARATE COLUMNS
	SETZ	3,
	SOUT
	 ERJMP	EROUT

PRTLDO:	ILDB	2,S2		;GET A DATA BYTE
	MOVE	3,[NO%LFL+NO%ZRO+FLD(3,NO%COL)+8]
	NOUT			;PRINT 3 DIGITS
	 ERJMP	EROUT

PRTLDC:	AOS	S1		;INCREMENT TO NEXT ADDRESS
	CAML	S1,SNDSIZ	;CHECK IF DONE ALL THE DATA
	JRST	PRTDON		;YES, GET OUT OF LOOP
	SOJG	S3,PRTLPD	;CONTINUE TO NEXT COLUMN
	JRST	PRTLOP		;OR START NEXT LINE

PRTDON:	HRROI	2,[ASCIZ/

/]
	SKIPE	RELFLG		;SKIP IF NOT RELEAS OR OUTPUT (IT'S PRINT)
	HRROI	2,[15B6!12B13!14B20]	;GET A FORM FEED INSTEAD
	SETZ	3,
	SOUT			;MAKE ROOM AT END OF TABLE
	 ERJMP	EROUT

	SKIPE	RELFLG		;SKIP IF PRINT (NOT RELEAS OR OUTPUT)
	JRST	PNTRTN		;RTN TO OUTPUT OR RELEAS COMMAND
	CLOSF			;CLOSE THE FILE AND GET RID OF JFN
	 ERJMP	EROUT		;(DON'T CLOSE FILE ON RELEAS OR OUTPUT)

	JRST	COMAND		;GO BACK FOR ANOTHER COMMAND
SUBTTL	NULL COMMAND

;NULL CHARACTER COMMAND

NULL:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/character/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,NUMBER	;INPUT A NUMBER
	MOVEI	^D8		;IN OCTAL
	MOVEM	NUMBER+.CMDAT	;PUT IN FUNCTION DESCRIPTION BLOCK
	COMND
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	2,T1		;SAVE NUMBER

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	ANDI	T1,377		;STRIP CHARACTER TO 8 BITS
	MOVEM	T1,FILL		;PUT CHARACTER IN PARAMETER TABLE
	JRST	COMAND		;GO BACK FOR ANOTHER COMMAND
SUBTTL	FIRST AND LAST COMMANDS

;FIRST AND LAST ADDRESS ROUTINES

FIRSTC:	PUSHJ	P,GETADR	;GET ADDRESS FROM COMMAND
	MOVEM	T1,FIRST	;SAVE FIRST ADDRESS IN PARAM TABLE
	JRST	COMAND

LASTC:	PUSHJ	P,GETADR	;GET ADDRESS FROM COMMAND
	MOVEM	T1,LAST		;SAVE LAST ADDRESS IN PARAM TABLE
	SETZM	SIZE		;MAKE SIZE AS NOT SPECIFIED
	JRST	COMAND

GETADR:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/address to send/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,NUMBER	;GET ADDRESS OF FUNCTION DESCRIPTOR BLOCK
	MOVE	RADIX		;GET CURRENT ADDRESS RADIX
	MOVEM	NUMBER+.CMDAT	;PUT INTO FUNCTION DESC BLOCK
	COMND			;INPUT A NUMBER
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	2,T1		;SAVE NUMBER

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	JUMPL	T1,FLERR	;DON'T ALLOW NEGATIVE NUMBERS

	POPJ	P,		;RETURN

FLERR:	PMSGC	<NEGATIVE ADDRESSES ARE NOT ALLOWED.>
	JRST	COMAND

NUMBER:	FLD(.CMNUM,CM%FNC)	;ACCEPT A NUMBER
	0			;RADIX WILL BE PUT HERE
SUBTTL	SIZE COMMAND

;SIZE ROUTINE

SIZEC:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/of PROM/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,[FLDDB.(.CMKEY,,KSIZE,,,NUMBER)]
	MOVEI	^D10		;SET DECIMAL RADIX
	MOVEM	NUMBER+.CMDAT	;PUT IN NUMBER DESC BLOCK
	COMND			;INPUT A NUMBER (OR 1K, 2K)
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	HRRZS	3		;LEAVE JUST ADDRESS OF DESC BLOCK IN 3
	CAIE	3,NUMBER	;SEE IF A NUMBER WAS INPUT
	HRRZ	2,@2		;NO, GET NUMBER FROM KSIZE TABLE
	MOVEM	2,T1		;SAVE NUMBER

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	JUMPL	T1,SIZEBD	;JUMP IF SIZE IS NEGATIVE
	CAILE	T1,PROMSZ	;CHECK SIZE OF NUMBER
	JRST	SIZEBD		;JUMP IF SIZE IS TOO LARGE
	MOVEM	T1,SIZE		;STORE SIZE IN PARAM TABLE
	SETZM	LAST		;MARK LAST ADDRESS AS NOT SPECIFIED
	JRST	COMAND

SIZEBD:	PMSG	<Size out of range. Acceptable size is between 0 and >
	MOVEI	1,.PRIOU	;SEND TO TERMINAL
	MOVEI	2,PROMSZ	;THE MAXIMUM SIZE OF A PROM
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	 ERJMP	EROUT
	PMSGC	< BYTES.>
	JRST	COMAND
SUBTTL	DECIMAL AND OCTAL COMMANDS

;RADIX COMMANDS

DECIML:	MOVEI	T1,^D10		;SET TEMP RADIX TO DECIMAL
	JRST	RADIXC		;GET CONFIRMATION ON RADIX

OCTAL:	MOVEI	T1,^D8		;SET TEMP RADIX TO OCTAL

RADIXC:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/addresses/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	T1,RADIX	;PUT NEW RADIX IN PARAM TABLE
	JRST	COMAND

SUBTTL	LIST AND CLOSE COMMANDS

OPEN:	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/ROM data listing file/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	MOVEI	2,[FLDDB. (.CMOFI)]
	COMND			;GET A FILE NAME
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	MOVEM	2,T1	;SAVE JFN

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	SKIPN	LSTJFN		;IS THERE LIST JFN ALREADY?
	JRST	NOLJFN			;JRST HERE IF NO
	PMSGC	<ERROR - LIST FILE ALREADY OPEN>
	JRST	COMAND

NOLJFN:	MOVEM	T1,LSTJFN#		;SAVE JFN AWAY
	MOVE	1,LSTJFN		;PUT JFN IN PLACE FOR OPENF
	MOVE	2,[7B5!OF%WR]	;SET UP BITS (BYTE SIZE OF 7 FOR WRITE)
	OPENF			;OPEN THE FILE
	 ERJMP	EROUT
	JRST	COMAND		;HERE WHEN OPEN
CLOSE:	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/listing file/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT
	SKIPE	1,LSTJFN	;IS THERE LIST JFN?
	JRST	NOCJFN		;JRST HERE IF YES
	PMSGC	<ERROR - LIST FILE NOT OPEN YET>
	JRST	COMAND

NOCJFN:	CLOSF			;CLOSE THE FILE, RELEASE JFN
	 ERJMP	EROUT
	JRST	COMAND		;AND FINISHED

SUBTTL	BYTE COMMAND

;BYTE POSITION COMMAND

BYTEC:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/position/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,NUMBER	;INPUT A NUMBER
	MOVEI	^D10		;IN DECIMAL
	MOVEM	NUMBER+.CMDAT	;PUT IN FUNCTION DESCRIPTOR BLOCK
	COMND
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	2,T1		;SAVE NUMBER

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	JUMPL	T1,[PMSGC <?Negative byte position is not allowed.>
		    JRST 	COMAND ]

	MOVEM	T1,BYTE		;SAVE NUMBER IN PARAMETER TABLE
	JRST	COMAND		;GO BACK FOR ANOTHER COMMAND
SUBTTL	ARRAY AND RELEASE COMMAND

;PROM POSITION IN ARRAY SPECIFIER
;SIZE MUST HAVE BEEN SPECIFIED PREVIOUSLY
;FIRST ARGUMENT SPECIFIES POSITION OF ADDRESS
;SECOND ARGUMENT SPECIFIES POSITION OF BYTE

RELEAS:	SETOM	RELFLG#		;SET FLG TO INDICATE RELEASE CMD
	JRST	ARRREL		;USE COMMON CODE

ARRAY:	SETZM	RELFLG		;CLR FLG TO INDICATE ARRAY CMD
ARRREL:	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/position of address/]>)]
	COMND	;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERRORS
	  JRST	EROUT

	MOVEI	2,[FLDDB.(.CMNUM,CM%DPP,^D10,,0)]
	COMND	;GET NUMBER
	TLNE	1,(CM%NOP)	;CHECK FOR ERRORS
	  JRST	EROUT
	MOVEM	2,ARAYAD#	;SAVE NUMBER

	MOVEI	2,[FLDDB.(.CMNOI,,<POINT 7,[ASCIZ/position of byte/]>)]
	COMND	;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERRORS
	  JRST	EROUT

	MOVEI	2,[FLDDB.(.CMNUM,CM%DPP,^D10,,0)]
	COMND	;GET NUMBER
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	  JRST	EROUT
	MOVEM	2,ARAYBT#	;SAVE NUMBER

	SKIPE	RELFLG		;SKIP IF ARRAY CMD, DON'T WAIT FOR CONFIRM
	JRST	ARRL1		;BR IF RELEASE CMD, DON'T WAIT FOR CONFIRM

	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND	;WAIT FOR CONFIRMATION
	TLNE	1,(CM%NOP)	;CHECK FOR ERRORS
	  JRST	EROUT

ARRL1:
;CHECK THAT SIZE HAS BEEN SPECIFIED

	SKIPN	SIZE
	JRST	[PMSGC	<?SIZE command must be given first.>
		JRST	COMAND ]

;CALCULATE FIRST ADDRESS

	MOVE	ARAYAD	;GET FIRST ARGUMENT
	IMUL	SIZE	;  TIMES SIZE OF PROM
	MOVEM	FIRST	;STORE IN FIRST

;CALCULATE BYTE POSITION

	AOS	T1,ARAYBT	;GET FIRST ARGUMENT PLUS ONE
	MOVEM	T1,BYTE	;STORE IN BYTE
	SKIPN	RELFLG		;SKIP IF RELEASE
	JRST	COMAND		;GO GET NEXT COMMAND (IF ARRAY CMD)

	;HERE IF RELEASE COMMAND

SUBTTL	RELEASE AND OUTPUT COMMAND

OUTPUT:	SETOM	RELFLG		;SET RELEASE FLG FOR PRINT ROUTINE
	SETZM	OUTJFN		;CLR OUT THE OUTPUT JFN (WE DON'T HAVE ONE YET)
	MOVEI	2,[FLDDB.(.CMTXT,CM%HPP!CM%SDH,,<ROM part # and comment>)]
	COMND				;DO THE COMMAND
	TLNE	1,(CM%NOP)		;WAS THERE AN ERROR?
	  JRST	EROUT			;HERE IF YES
	MOVE	S1,.CMABP(1)		;GET THE ATOM BUFFER POINTER

	;WE MUST FIRST GET AND CHK THE PART # CLASS (SHOULD BE 23-)

	SETZM	S3		;CLR OUT PART CLASS HOLDER S3
	MOVE	T1,[POINT 7,S3]		;GET POINTER TO S3
	ILDB	S1			;GET 1ST BYTE
	IDPB	T1			;DEPOSIT IN S3
	ILDB	S1			;GET 2ND BYTE
	IDPB	T1			;DEPOSIT IN S3
	ILDB	S1			;GET 3RD BYTE
	IDPB	T1			;DEPOSIT IN S3
	CAME	S3,[ASCIZ/23-/]	;COMPARE PART CLASS WITH 23
	JRST	PNBAD			;BR IF NOT CLASS 23
	;NOW WE GET THE NEXT 5 OR 6 CHARACTERS UNTIL THE "-" FOR THE FILE NAME

	MOVE	S4,[POINT 7,OFNAM]	;SET UP POINTER TO FILE NAME
	MOVEI	S2,6			;CHARACTER COUNTER

PNLP:	ILDB	S1			;GET A BYTE
	CAIN	"-"			;SKIP IF NOT MINUS
	JRST	PNDON			;BR IF FILE NAME IS DONE
	JUMPE	PNDON			;BR IF FILE NAME IS DONE
	IDPB	S4			;DEPOSIT THE BYTE
	SOJL	S2,PNBAD		;BR IF TOO MANY CHARACTERS
	JRST	PNLP			;BR BACK FOR REST OF NUMBER

PNDON:	MOVE	S2,[POINT 7,[ASCIZ/.DAT/]]	;POINTER TO FINISH NAME
	MOVEI	S3,5			;COUNTER TO FINISH
PNDLP:	ILDB	S2			;GET A CHARACTER
	IDPB	S4			;PUT IN NAME BUFFER
	SOJN	S3,PNDLP		;BR BACK TO FINISH NAME

	;NOW WE TRY TO GTJFN ON THE GIVEN FILE NAME
	;DON'T CLOBBER S1 - IT CONTAINS POINTER TO COMMENT (IF ANY)

	MOVSI	1,(GJ%SHT)		;SET UP FOR SHORT GTJFN
	HRROI	2,OFNAM		;POINTER TO OUTPUT FILE NAME
	GTJFN
	 ERJMP	EROUT			;JUMP IF ERROR
	MOVE	2,[^D36B5!13B9!OF%WR]	;WRITE, 36 BIT BYTE, IMAGE BINARY MODE
	OPENF				;OPEN THE FILE
	 ERJMP	EROUT			;HERE IF ERROR
	MOVEM	1,OUTJFN#		;SAVE THE OUTPUT JFN

	;NOW WE FINISH PARSING THE COMMAND LINE FOR COMMENTS
	;FIRST WE MUST SKIP OVER THE REST OF THE PART NUMBER GARBAGE (IF ANY)

	LDB	S1			;GET THE TERMINATION CHAR
	JRST	PNGLP1			;JUMP INTO SEPARATOR LOOP
	SETZM	COMBUF			;CLR OUT 1ST WORD OF COMMENT BUFFER
PNGLP:	ILDB	S1			;GET NEXT CHARACTER
PNGLP1:	JUMPE	COMNUL			;BR IF THE END, NO COMMENT
	CAIN	11			;IS IT TAB?
	JRST	OVRSP			;BR IF YES, WE ARE AT SEPARATOR
	CAIE	40			;IS IT SPACE?
	JRST	PNGLP			;BR IF NO, STILL SKIPPING PART NR

	;NOW WE ARE AT TERMINATOR - WE MUST SKIP OVER IT

OVRSP:	ILDB	S1			;GET NEXT CHARACTER
	JUMPE	COMNUL			;BR IF THE END, NO COMMENT
	CAIN	11			;IS IT TAB?
	JRST	OVRSP			;BR IF YES, KEEP SKIPPING
	CAIN	40			;IS IT SPACE?
	JRST	OVRSP			;BR IF YES, KEEP SKIPPING

	;WE ARE NOW AT THE COMMENT
CMSON:	MOVE	S2,[POINT 7,COMBUF]	;POINTER TO COMMENT STORAGE
	IDPB	S2			;STORE THE FIRST COMMENT CHARACTER
CMSLP:	ILDB	S1			;GET A TYPED CHARACTER
	IDPB	S2			;PUT IN COMMENT BUFFER
	JUMPN	CMSLP			;BR IF NOT THE END, KEEP LOADING

COMNUL:	PUSHJ	P,GENBUF		;GENERATE BUFFER OF DATA
	JRST	COMAND			;NO SKIP RTN IF NO DATA

	SKIPE	1,LSTJFN		;SKIP IF NOT LISTING
	JRST	LISTIT			;HERE TO LIST (AC1 = JFN)

PNTRTN:	MOVEI	377			;GET INITIAL DATA MARKER
	MOVEM	ROMBUF-1		;PUT IMMEDIATELY BEFORE BUFFER

	SKIPN	BINMOD			;SKIP IF PACKED BINARY MODE
	JRST	IMMOD			;HERE IF IMAGE - DON'T REPACK

	;HERE WE MUST REPACK THE BINARY DATA FOR PDP-11 PACKED MODE
	MOVE	T1,SNDSIZ		;GET #BYTES
	AOS	T1			;MAKE ALLOWANCE FOR 377 START BYTE
	MOVE	T4,[POINT 8,ROMBUF-1,27]	;GET POINTER TO SOURCE DATA
	MOVEI	T3,ROMBUF-1		;GET POINTER TO 1ST WORD

	MOVE	T2,[-4,,PMBTAB]		;BYTE POINTER TABLE INDEX
	SETZM	S2			;CLR OUT BYTE ACCUMULATOR

IMLP:	ILDB	T4			;GET A BYTE OF DATA
	DPB	(T2)			;DEPOSIT BYTE IN S2
	AOBJN	T2,IMLP1		;LOOP FOR ALL 4 BYTES
	MOVE	T2,[-4,,PMBTAB]		;BYTE POINTER TABLE INDEX
	MOVEM	S2,(T3)			;DEPOSIT DATA
	SETZM	S2			;CLR OUT BYTE ACCUMULATOR
	AOS	T3			;POINT TO NEXT WORD
IMLP1:	SOJG	T1,IMLP			;INCR THE INDEX FOR DEPOSIT, LOOP BACK
	MOVEM	S2,(T3)			;SET UP PARTIALLY FORMED WORD
					;(OR 0 IF WE JUST FORMED A WORD)
	;NOW WE ACTUALLY OUTPUT THE DATA TO THE FILE

IMMOD:	MOVE	1,OUTJFN		;GET THE JFN
	MOVE	2,[POINT 8,ROMBUF-1,27] ;START POINTER AT 377 BYTE
	SKIPE	BINMOD			;SKIP IF IN IMAGE MODE
	MOVE	2,[POINT 36,ROMBUF-1]	;FULL WORDS IF IN PACKED MODE
	MOVE	3,SNDSIZ		;NEED THIS MANY BYTES
	AOS	3			;PLUS 1 FOR DATA MARKER
	SKIPN	BINMOD			;SKIP IF PACKED MODE - FUDGE CNT
	JRST	IMMOD1			;HERE IF IMAGE
	ADDI	3,3			;ROUND UP IF UNEVEN
	LSH	3,-2			;SHIFT 2 PLACES FOR DIVIDE BY 4
IMMOD1:	MOVN	3,3			;NEGATE THE COUNT
	SOUT				;OUTPUT THE DATA
	 ERJMP	EROUT			;HERE IF ERROR

	MOVE	1,OUTJFN		;GET THE JFN
	CLOSF				;CLOSE THE FILE
	 ERJMP	EROUT			;HERE IF ERROR
	SETZM	OUTJFN			;THE FILE IS NOW CLOSED
	JRST	COMAND			;AND DONE

PNBAD:	PMSGC	<Illegal part number>
	JRST	COMAND			;AND START OVER

SUBTTL	INVERT COMMANDS

;INVERT AND NOINVERT COMMANDS

INVRT:	TROA	T1,-1		;SET FLAG
NOINVRT:SETZ	T1,		;CLEAR FLAG

	MOVEI	2,[FLDDB. (.CMCFM)]	;WAIT FOR CONFIRMATION
	COMND
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	T1,INVERT		;STORE FLAG IN MEMORY
	JRST	COMAND
SUBTTL	IMAGE AND PACKED COMMANDS

PACKED:	TROA	T1,-1		;SET FLAG
IMAGE:	SETZ	T1,		;CLEAR FLAG
	MOVEI	2,[FLDDB. (.CMNOI,,<POINT 7,[ASCIZ/binary tape mode/]>)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEI	2,[FLDDB. (.CMCFM)]	;WAIT FOR CONFIRMATION
	COMND
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVEM	T1,BINMOD		;STORE FLAG IN MEMORY
	JRST	COMAND

SUBTTL	AUTHOR COMMAND

AUTHOR:	MOVEI	2,[FLDDB.(.CMTXT,CM%HPP!CM%SDH,,<(your name, turkey)>)]
	COMND				;DO THE COMMAND
	TLNE	1,(CM%NOP)		;WAS THERE AN ERROR?
	  JRST	EROUT			;HERE IF YES
	MOVE	S1,.CMABP(1)		;GET THE ATOM BUFFER POINTER
	MOVE	S2,[POINT 7,AUTHST]	;GET POINTER TO AUTHOR STRING
ATHLP:	ILDB	S1			;GET A BYTE
	IDPB	S2			;PUT IN SAVED AREA
	JUMPN	ATHLP			;LOOP UNTIL 0 BYTE
	JRST	COMAND			;AND DONE

SUBTTL	COMENT COMMAND

COMENT:	MOVEI	2,[FLDDB.(.CMTXT,CM%HPP!CM%SDH,,<(whatever you want)>)]
	COMND				;DO THE COMMAND
	TLNE	1,(CM%NOP)		;WAS THERE AN ERROR?
	  JRST	EROUT			;HERE IF YES
	MOVE	S1,.CMABP(1)		;GET THE ATOM BUFFER POINTER
	MOVE	S2,[POINT 7,COMBUF]	;GET POINTER TO COMMENT STRING
COMLP:	ILDB	S1			;GET A BYTE
	IDPB	S2			;PUT IN SAVED AREA
	JUMPN	COMLP			;LOOP UNTIL 0 BYTE
	JRST	COMAND			;AND DONE
SUBTTL	HELP COMMAND

;HELP COMMAND

HELP:	MOVEI	2,[FLDDB.(.CMCFM)]
	COMND			;GIVE GUIDE WORDS
	TLNE	1,(CM%NOP)	;CHECK FOR ERROR
	 JRST	EROUT

	MOVSI	1,(GJ%SHT)	;GET A JFN TO HELP FILE
	HRROI	2,[ASCIZ/HLP:BLAST.HLP/]
	GTJFN
	 ERJMP	EROUT

	MOVSI	2,(FLD(7,OF%BSZ))	;OPEN FILE
	HRRI	2,OF%RD		;FOR READING
	OPENF
	 ERJMP	EROUT

	MOVEM	1,T1		;SAVE JFN

HLPOUT:	MOVE	1,T1		;GET INPUT FILE JFN
	BIN			;READ A BYTE
	 ERJMP	COMAND		;STOP ON ANY ERROR

	MOVEI	1,.PRIOU	;SET TERMINAL AS OUTPUT DEVICE
	BOUT			;WRITE TO BYTE OUT
	JRST	HLPOUT
SUBTTL	ERROR MESSAGES
;ERROR MESSAGE PRINTER

EROUT:	PUSH	P,1		;SAVE AC'S THAT MAY CONTAIN ERROR DATA
	PUSH	P,2
	PUSH	P,3
	MOVEI	1,.PRIOU	;OUTPUT DESIGNATOR
	MOVEI	2,-1		;PRINT MOST RECENT ERROR
	HRLI	2,.FHSLF	;FOR CURRENT PROCESS
	MOVEI	3,0		;NO LIMIT ON MESSAGE SIZE
	ERSTR			;PRINT THE MESSAGE
	 HALTF
	 HALTF
	JRST COMAND

ERQUIT:	PUSH	P,1		;SAVE AC'S THAT MAY CONTAIN ERROR DATA
	PUSH	P,2
	PUSH	P,3
	PMSGC	<Cannot Access device BLASTR:>
	MOVEI	1,.PRIOU	;OUTPUT DESIGNATOR
	MOVEI	2,-1		;PRINT MOST RECENT ERROR
	HRLI	2,.FHSLF	;FOR CURRENT PROCESS
	MOVEI	3,0		;NO LIMIT ON MESSAGE SIZE
	ERSTR			;PRINT THE MESSAGE
	 HALTF
	 HALTF
	HALTF			;EXIT TO MONITOR
	JRST	START		;RESTART IF CONTINUED

SUBTTL	FILE READ ROUTINES

;THE FOLLOWING ARE TWO ROUTINES FOR EACH FILE FORMAT.

;THE FIRST ROUTINE IS CALLED ONCE TO OPEN THE FILE AND
;INITIALIZE FOR THE SECOND ROUTINE.

;THE SECOND ROUTINE IS CALLED FOR EACH DATA BYTE OBTAINABLE
;FROM THE FILE.  THIS ROUTINE GIVES A SKIP RETURN WHEN A DATA
;BYTE IS BEING SUPPLIED FROM THE FILE.  ON A SKIP RETURN, THE
;8-BIT DATA BYTE MUST BE IN T2 AND THE ADDRESS INTO WHICH
;THIS DATA IS TO BE PLACED MUST BE IN T3.

;THESE ROUTINES MAY ALSO USE THE FOLLOWING ACCUMULATORS:
; 0, 1, 2, 3, 4, S1, S2, S3, S4, S5.
;A BUFFER AREA AT ATOMBF OF SIZE ATOMBS WORDS MAY ALSO
;BE USED.
SUBTTL	ROM FILE TYPE READ ROUTINES

;ROM FILE READ ROUTINES

;OPEN FILE FOR INPUT

ROMI:	MOVE	1,FILE		;GET JFN
	MOVSI	2,(FLD(7,OF%BSZ))	;BYTE SIZE OF 7
	HRRI	2,OF%RD+OF%PLN	;FOR READING
	OPENF
	 ERJMP	EROUT
	SETOB	T3,S3		;INIT ADDRESS AND END OF LINE FLAG
	MOVEI	S1,1		;SET LINE NUMBER TO FIRST LINE
	POPJ	P,		;RETURN

;READ A DATA BYTE

ROMDAT:	SETZB	S2,T2		;CLEAR DIGIT COUNTER AND DATA BYTE
	ADDI	T3,1		;INCREMENT ADDRESS

ROMD2:	MOVE	1,FILE		;GET JFN
	BIN			;READ A CHARACTER FROM FILE
	  ERJMP	ROMDER
	JUMPE	2,ROMD2		;IGNORE NULL CHARACTERS
	CAIN	2,15		;IGNORE CARRIAGE RETURNS
	JRST	ROMD2
	CAIN	2,";"		;CHECK FOR START OF COMMENT
	JRST	ROMCMT
	CAIN	2,"/"		;CHECK FOR SLASH CHARACTER
	JRST	ROMSLA
	CAIN	2,12		;CHECK FOR LINE FEED
	JRST	ROMLF
	CAIE	2,13		;CHECK FOR VERTICAL TAB
	CAIN	2,14		; OR FORM FEED
	JRST	ROMLF		;TREAT AS A LINE FEED
	CAIE	2," "		;CHECK FOR A SPACE
	CAIN	2,"	"	; OR A TAB
	JRST	ROMSEP
	CAIL	2,"0"		;CHECK FOR AN OCTAL DIGIT
	CAILE	2,"7"
	JRST	ROMILC		;IF NOT, ILLEGAL CHARACTER

;A DIGIT

	LSH	T2,3		;MAKE ROOM FOR DIGIT
	ORI	T2,-"0"(2)	;SET IN NEW DIGIT
	AOJA	S2,ROMD2	;COUNT DIGIT AND GET NEXT CHARACTER
;COMMENT

ROMCMT:	MOVE	1,FILE		;GET JFN
	BIN			;READ ANOTHER CHARACTER FROM FILE
	  ERJMP	ROMDER
	CAIE	2,12		;LOOK FOR A LINE FEED
	JRST	ROMCMT		;INPUT UNTIL FIND ONE
	JRST	ROMLF		;NOW HONOR THE LINE FEED

;SLASH

ROMSLA:	JUMPE	S2,ROMSLI	;NUMBER INPUT
	JUMPE	S3,ROMSLI	; AND FIRST NUMBER ON LINE OR ERROR
	SETZB	S2,S3		;CLEAR DIGIT COUNTER AND END OF LINE FLAG
	MOVE	T3,T2		;COPY NUMBER INPUT TO ADDRESS
	SETZ	T2,		;CLEAR NUMBER
	JRST	ROMD2		;NOW INPUT THE DATA NUMBER

ROMSLI:	PMSG	<?Error reading input file.  "/" not after first number>
	JRST	ROMERR

;LINE FEED

ROMLF:	SETO	S3,		;SET END OF LINE FLAG
	ADDI	S1,1		;COUNT THE LINE
	JUMPE	S2,ROMD2	;KEEP LOOKING FOR NUMBER IN NONE FOUND YET
ROMSND:	AOS	(P)		;FIVE SKIP RETURN
	POPJ	P,
;SPACE OR TAB

ROMSEP:	JUMPE	S2,ROMD2	;KEEP READING IF NO DIGIT INPUT YET
	JUMPE	S3,ROMSND	;SEND DATA BYTE IF NOT FIRST DIGIT ON LINE
ROMSAD:	MOVE	1,FILE		;GET JFN
	BIN			;READ NEXT CHARACTER
	  ERJMP	ROMDER
	JUMPE	2,ROMSAD	;IGNORE NULL CHARACTERS
	CAIE	2," "		;SPACE
	CAIN	2,"	"	; OR TAB
	JRST	ROMSAD		;YES, KEEP READING
	CAIN	2,"/"		;SLASH?
	JRST	ROMSLA		;YES, GO HONOR THE SLASH
	MOVE	1,FILE		;NOT A SLASH, BACKUP THE FILE POINTER
	BKJFN
	  ERJMP	EROUT
	JRST	ROMSND		;NOW SEND THE NUMBER AS A DATA BYTE

ROMILC:	PMSG	<?Error reading input file.  Illegal charACter ">
	MOVE	1,2		;GET ILLEGAL CHARACTER
	PBOUT			;TYPE IT
	PMSG	<">
ROMERR:	PMSG	< on line >
	MOVEI	1,.PRIOU	;SELECT THE TERMINAL
	MOVE	2,S1		;TYPE LINE NUMBER
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	  ERJMP	EROUT
	PMSGC	<.>
	JRST	COMAND

;FILE READ ERROR

ROMDER:	GTSTS			;READ FILE STATUS
	TLNN	2,(GS%EOF)	;AT END OF FILE?
	JRST	EROUT		;NO, REPORT ERROR MESSAGE
	JUMPN	S2,ROMSND	;SEND DATA BYTE IF ANY
	POPJ	P,		;GIVE NON-SKIP RETURN
SUBTTL	A78, DAT, PTP FILE TYPE READ ROUTINES

;INTEL 8080 PAPER TAPE FORMAT READ ROUTINES

;OPEN FILE FOR INPUT

I80I:	MOVE	1,FILE		;GET JFN
	MOVSI	2,(FLD(7,OF%BSZ))	;7 BIT BYTES
	HRRI	2,OF%RD+OF%PLN	;FOR READING
	OPENF			;OPEN FILE
	 ERJMP	EROUT
	SETZB	S1,S5		;CLEAR BYTE COUNTER AND LINE COUNTER
	POPJ	P,		;RETURN

;READ A DATA BYTE FROM FILE

I80DAT:	JUMPN	S1,I80NXT	;JUMP IF BYTES STILL IN BUFFER
	AOJ	S5,		;READ A NEW LINE, COUNT THE LINE
	MOVE	1,FILE		;GET JFN
	HRROI	2,ATOMBF	;READ A LINE INTO ATOM BUFFER
	MOVEI	3,ATOMBS*5	;SIZE OF BUFFER
	MOVEI	4,12		;TERMINATE ON A <LF> CHARACTER
	SIN			;READ A STRING
	 ERJMP	EROUT

	SUBI	3,ATOMBS*5	;COMPUTE CHARACTERS READ
	MOVMS	3		;GET MAGNITUDE OF COUNT

	MOVE	S2,[POINT 7,ATOMBF]	;GET POINTER TO BUFFER
I80NUL:	ILDB	S2		;GET FIRST CHARACTER OF STRING
	SKIPN			;IF CHARACTER IS NULL
I80SP:	SOJA	3,I80NUL	; DECREASE COUNT AND LOOK AT NEXT
	CAIN	" "		;CHK FOR SPACE
	JRST	I80SP		;BR IF SPACE, SKIP IT
	CAIN	15		;IF CARRIAGE RETURN
	JRST	I80DAT		; LINE IS BLANK, GO READ NEXT
	CAIE	":"		;CHECK IF A COLON
	JRST	[PMSG <?Error reading input file. First character not a colon>
		 JRST I80ERR ]
	PUSH	P,S2		;SAVE POINTER
	SUBI	3,3		;COMPUTE NUMBER OF BYTES IN STRING
	LSH	3,-1		;(CHARACTERS READ MINUS COLON AND 
				; <CR><LF> DIVIDED BY 2)
	CAIGE	3,5		;CHECK IF AT LEAST 5 BYTES
	JRST	[PMSG <?Error reading input file. Not enough characters>
		 JRST I80ERR ]
	MOVEM	3,S1		;SAVE COUNT OF BYTES
	SETZ	S3,		;CLEAR CHECKSUM
I80CHK:	PUSHJ	P,I80BYT	;READ A BYTE
	ADDM	T2,S3		;ADD TO CHECKSUM
	SOJG	3,I80CHK	;READ ALL BYTES
	ANDI	S3,377		;STRIP OFF  ADDITIONAL BITS
	JUMPN	S3,[PMSG <?Error reading input file. Checksum error>
		    JRST I80ERR ]
	SUBI	S1,5		;COMPUTE NUMBER OF DATA BYTES IN LINE
	POP	P,S2		;GET POINTER TO FIRST BYTE IN LINE
	PUSHJ	P,I80BYT	;READ THE BYTE
	JUMPE	T2,I80X		;IF # BYTES = 0, WE ARE AT THE END
	CAME	T2,S1		;THIS BYTE SHOULD BE SAME AS COMPUTED
				;BYTE COUNT
	JRST	[PMSG <?Error reading input file. Byte counter does not match line length>
		 JRST	I80ERR ]
	JUMPE	S1,I80X		;IF BYTE COUNT IS ZERO, REPORT EOF
	PUSHJ	P,I80BYT	;GET HIGH BYTE OF ADDRESS
	LSH	T2,8		;POSITION
	MOVEM	T2,T3		;PUT INTO T3
	PUSHJ	P,I80BYT	;GET REST OF ADDRESS
	ORM	T2,T3		;PLACE IN T3
	PUSHJ	P,I80BYT	;GET RECORD TYPE FIELD
	JUMPN	T2,[PMSG <?Error reading input file. Record type field not zero>
		    JRST I80ERR ]
	JRST	I80NB		;GET BYTE

I80NXT:	AOJ	T3,		;BUMP ADDRESS
I80NB:	SOJ	S1,		;COUNT THE BYTE
	PUSHJ	P,I80BYT	;GET A DATA BYTE
	AOS	(P)		;CAUSE SKIP RETURN
I80X:	POPJ	P,		;RETURN
;READ A BYTE OF TWO HEX CHARACTERS INTO T2

I80BYT:	PUSHJ	P,I80CHR	;READ A CHARACTER
	LSH	4		;POSITION
	MOVEM	T2		;STORE IN T2
	PUSHJ	P,I80CHR	;READ NEXT CHARACTER
	ORM	T2		;STORE IN T2
	POPJ	P,		;RETURN

;READ A HEX CHARACTER INTO 0

I80CHR:	ILDB	S2		;READ A CHARACTER
	CAIL	"0"		;IF NOT 0 TO 9
	CAILE	"9"		; CHECK IF A TO F
	SKIPA
	JRST	I80CHX		;IF 0 TO 9, JUMP AHEAD
	CAIL	"A"		;IF NOT A TO F
	CAILE	"F"		;REPORT ERROR
	JRST	[PMSG <?Error reading input file. Illegal charACter>
		 JRST	I80ERR ]
	ADDI	11		;IF A TO F, FIX LOW 4 BITS
I80CHX:	ANDI	17		;STRIP TO 4 BITS
	POPJ	P,		;RETURN

;ERROR REPORTER

I80ERR:	PMSG	< on line >
	MOVEI	1,.PRIOU	;OUTPUT TO TERMINAL
	MOVE	2,S5		;LINE NUMBER IN ERROR
	MOVEI	3,^D10		;IN DECIMAL
	NOUT
	 ERJMP	EROUT
	PMSGC	<.>
	JRST	COMAND		;ABORT AND GO BACK FOR ANOTHER COMMAND
SUBTTL	E16, E32 FILE TYPE READ ROUTINES

;E16 AND E32 FORMAT READ ROUTINES

E16I:	MOVE	T1,BYTE		;GET BYTE PARAMETER
	JUMPE	T1,NOBYTE	;ERROR IF NO BYTE POSITION SPECIFIED
	CAILE	T1,2		;CHECK IF IN CORRECT RANGE
	JRST	[PMSGC <?Byte position out of range, must be 1 or 2.>
		 JRST	COMAND ]
	MOVE	T2,[	-2,,0
			-2,,-1 ]-1(T1)	;GET BYTE INPUT CONTROL WORD
	JRST	EII

NOBYTE:	PMSGC	<?No byte position was specified.>
	SKIPN	1,OUTJFN		;SKIP IF DOING OUTPUT
	JRST	COMAND
	HRLI	(CZ%ABT)	;ABORT THE FILE
	CLOSF			;CLOSE OUT THE OUTPUT FILE
	 ERJMP	EROUT		;HERE IF ERROR
	JRST	COMAND

E32I:	MOVE	T1,BYTE		;GET BYTE PARAMETER
	JUMPE	T1,NOBYTE	;ERROR IF NO BYTE POSITION SPECIFIED
	CAILE	T1,4		;CHECK IF IN CORRECT RANGE
	JRST	[PMSGC <?Byte position out of range, must be between 1 and 4.>
		 JRST	COMAND ]
	MOVE	T2,[	-4,,-2
			-4,,-3
			-4,,0
			-4,,-1 ]-1(T1)	;GET BYTE INPUT CONTROL WORD

EII:	MOVEM	T2,BYTECW#	;SAVE BYTE CONTROL WORD
	MOVE	1,FILE		;GET JFN OF INPUT FILE
	MOVSI	2,(FLD(^D18,OF%BSZ))	;18 BIT BYTES
	HRRI	2,OF%RD+OF%PLN	;FOR READING
	OPENF			;OPEN FILE
	 ERJMP	EROUT

	SETZ	S1,		;CLEAR BYTE COUNTER
	POPJ	P,		;RETURN
;E16 AND E32 DATA RETRIEVAL ROUTINES
;THESE ROUTINES ARE THE SAME EXCEPT THAT THE READ CONTROL WORD
;SAVED IN BYTECW WILL CAUSE DIFFERENT AMOUNTS OF DATA TO BE READ.

E16DAT:
E32DAT:	PUSHJ	P,E32BYT	;READ A BYTE - ADDRESS LOW BYTE
	 POPJ	P,		;EOF - GIVE EOF RETURN
	MOVEM	T3		;STORE IN ADDRESS RETURN LOCATION
	PUSHJ	P,E32BYT	;READ REST OF ADDRESS
	 JRST	E32EOF		;UNEXPECTED EOF
	LSH	8		;POSITION TO HIGH BYTE POSITION
	ORM	T3		;PUT IN ADDRESS LOCATION
	MOVE	S5,BYTECW	;GET BYTE CONTROL WORD
E32DLP:	PUSHJ	P,E32BYT	;READ A DATA BYTE
	 JRST	E32EOF		;UNEXPECTED EOF
	TRNN	S5,-1		;CHECK IF THIS IS DESIRED BYTE
	MOVEM	T2		;YES, STORE IN DATA LOCATION
	AOBJN	S5,E32DLP	;READ ALL BYTES FOR THIS LOCATION
	AOS	(P)		;GIVE SKIP RETURN
	POPJ	P,		;ADDRESS IS IN T3, DATA BYTE IN T2

E32EOF:	PMSGC	<?Error reading input file. EOF block found when not expected.>
	JRST	COMAND
;READ A BYTE FROM AN E16 OR E32 TYPE FILE.

E32BYT:	SOJL	S1,E32BLK	;IF NO BYTES IN CORE, READ A NEW BLOCK
	ILDB	S2		;READ A BYTE
	AOS	(P)		;CAUSE A SKIP RETURN
	POPJ	P,		;DATA BYTE IS IN AC 0

;READ A NEW BLOCK FROM THE FILE

E32BLK:	SETZB	S3,S4		;CLEAR CHECKSUM AND SECOND BYTE
	MOVE	S2,[POINT 8,ATOMBF]	;SET UP POINTER TO STORE BYTES

E32BKF:	PUSHJ	P,E32IBT	;INPUT A BYTE FROM FILE
	JUMPE	2,E32BKF	;KEEP INPUTTING UNTIL FIND FIRST BYTE
	CAIE	2,1		;FIRST BYTE MUST BE A 001
	JRST	[PMSGC <?Error reading input file. Cannot find start of a block.>
		 JRST	COMAND ]
	PUSHJ	P,E32IBT	;INPUT SECOND BYTE FROM BLOCK
	JUMPN	2,[PMSGC <?Error reading input file. Second byte of block is not zero.>
		 JRST	COMAND ]
	PUSHJ	P,E32IBT	;READ FIRST BYTE OF BYTE COUNTER
	MOVEM	2,S1		;BUILD BYTE COUNTER IN S1
	PUSHJ	P,E32IBT	;READ REST OF BYTE COUNTER
	LSH	2,8		;POSITION
	ORM	2,S1		;BUILD BYTE COUNTER
	CAILE	S1,ATOMBS*4	;CHECK IF BYTES WILL FIT IN ATOM BUFFER
	JRST	[PMSGC <?Error reading input file. Byte count from file is greater than buffer size.>
		 JRST	COMAND ]
	MOVEM	S1,EBYTSV#	;SAVE BYTE COUNTER
	SUBI	S1,3		;SUBTRACT 3 FROM COUNT TO COMPUTE
				;NUMBER OF BYTES REMAINING TO BE READ
				;FROM FILE INCLUDING CHECKSUM

E32BKR:	PUSHJ	P,E32IBT	;INPUT A BYTE FROM FILE
	IDPB	2,S2		;PUT BYTE IN MEMORY BUFFER
	SOJG	S1,E32BKR	;READ REST OF BLOCK FROM FILE
	ANDI	S3,377		;CLEAR OVERFLOW FROM ADDITION
	JUMPN	S3,[PMSGC <?Error reading input file. Checksum error.>
		    JRST COMAND ]
	MOVE	S2,[POINT 8,ATOMBF]	;GET POINTER TO START OF BUFFER
	ILDB	S1,S2		;GET BLOCK TYPE FIELD
	ILDB	2,S2		;TWO BYTES
	LSH	2,8
	ORM	2,S1		;BUILD 16 BIT FIELD
	CAIN	S1,6		;CHECK IF EOF BLOCK
	POPJ	P,		;YES, GIVE EOF RETURN

	CAIE	S1,3		;CHECK IF A DATA BLOCK
	JRST	E32BLK		;NO, GO READ NEXT BLOCK

	ILDB	2,S2		;READ ADDRESS FIELD OF BLOCK
	ILDB	2,S2		;AND THROW AWAY
	MOVE	S1,EBYTSV	;GET SAVED BYTE COUNTER FROM BLOCK
	SUBI	S1,8		;ADJUST TO NUMBER OF DATA BYTES
	JUMPG	S1,E32BYT	;NOW GET FIRST DATA BYTE
	PMSGC	<?Error reading input file. Data block found with no data.>
	JRST	COMAND

;INPUT A BYTE FROM E16 AND E32 TYPE FILES.
;BYTE IS READ AS AN 18 BIT CHUNK. THE FIRST BYTE IS RIGHT JUSTIFIED.

E32IBT:	JUMPN	S4,E32NBT	;JUMP IF BYTE IN S4 (SECOND BYTE FROM 18)

	MOVE	1,FILE		;GET JFN
	BIN			;READ AN 18 BIT CHUNK FROM FILE
	 ERJMP	EROUT
	HRROM	2,S4		;SAVE SECOND BYTE IN S4
	ANDI	2,377		;CLEAR SECOND BYTE
	JRST	E32CKB

E32NBT:	LDB	2,[POINT 8,S4,27]	;GET SECOND BYTE FROM S4
	SETZ	S4,		;CLEAR SECOND BYTE STORAGE

E32CKB:	ADDM	2,S3		;ADD BYTE TO CHECKSUM
	POPJ	P,		;RETURN WITH BYTE IN 2
SUBTTL	R16, R28 FILE TYPE READ ROUTINES

;R16 AND R28 FORMAT READ ROUTINES

R16I:	MOVE	T1,BYTE	;GET BYTE PARAMETER
	JUMPE	T1,NOBYTE	;ERROR IF NO BYTE POSITION SPECIFIED
	CAILE	T1,4	;CHECK IF IN CORRECT RANGE
	JRST	[PMSGC <?Byte position out of range, must be between 1 and 4.>
		 JRST	COMAND]
	SETZM	R1628F#	;CLEAR CONTROL FLAG
	JRST	RII

R28I:	MOVE	T1,BYTE	;GET BYTE PARAMETER
	JUMPE	T1,NOBYTE	;ERROR IF NO BYTE POSITION SPECIFIED
	CAILE	T1,7	;CHECK IF IN CORRECT RANGE
	JRST	[PMSGC <?Byte position out of range, must be between 1 and 7.>
		 JRST	COMAND]
	SETOM	R1628F	;SET CONTROL FLAG

RII:	MOVE	1,FILE	;GET JFN OF INPUT FILE
	MOVSI	2,(FLD(^D36,OF%BSZ))	;36 BIT BYTES
	HRRI	2,OF%RD+OF%PLN	;FOR READING
	OPENF	;OPEN FILE
	  ERJMP	EROUT
	MOVEI	S5,400	;GET COUNT OF LEADING BYTES TO IGNORE
RIGNOR:	PUSHJ	P,R28IN	;READ A BYTE
	  JRST	[PMSGC <?Error reading input file.  EOF before first data byte.>
		 JRST COMAND]
	SOJG	S5,RIGNOR	;READ ALL LEADING BYTES
	SETOM	T3	;SET START ADDRESS TO -1 SO IT CAN
			;INCREMENT TO ZERO
	POPJ	P,	;RETURN
;R16 AND R28 DATA RETRIEVAL ROUTINES
;THESE ROUTINES ARE THE SAME EXCEPT FOR WHERE THE HIGH ORDER TWO
;BITS OF BYTE NUMBER 4 ARE FOUND.  R1628F IS USED AS A CONTROL FLAG
;TO GET THESE BITS.

R16DAT:
R28DAT:	PUSHJ	P,R28IN	;READ NEXT WORD FROM FILE
	  POPJ	P,	;EOF - GIVE NON-SKIP RETURN

	SKIPN	R1628F	;SKIP IF R28 TYPE
	JRST	RR16
	LDB	[POINT 2,2,35]	;GET HIGH ORDER TWO BITS OF BYTE 4
	DPB	[POINT 2,2,3]	;PLACE IN POSITION AS IN R16 TYPE

RR16:	MOVE	S2,BYTE	;GET BYTE NUMBER
	LDB	T2,[POINT 4,2,17
		    POINT 4,2,13
		    POINT 4,2,9
		    POINT 4,2,5
		    POINT 4,2,33
		    POINT 4,2,29
		    POINT 4,2,25 ]-1(S2)	;GET 4 BIT BYTE
	AOJ	T3,	;INCREMENT ADDRESS IN T3
	AOS	(P)	;GIVE SUCCESSFUL RETURN
	POPJ	P,

R28DER:	PMSGC	<?Error reading input file.  EOF in the middle of a four byte group.>
	JRST	COMAND

;READ A WORD FROM THE FILE

R28IN:	MOVE	1,FILE	;GET JFN
	BIN	;READ A 36-BIT WORD
	  ERJMP	R28INE	;JUMP IF ANY ERROR
	AOS	(P)	;CAUSE SKIP RETURN
	POPJ	P,
R28INE:	GTSTS	;GET FILE STATUS
	TLNN	2,(GS%EOF)	;CHECK IF FOUND END OF FILE
	JRST	EROUT	;NO, REPORT ERROR
	POPJ	P,	;YES, GIVE NON-SKIP RETURN
SUBTTL	TAP DATA RETRIEVAL ROUTINES

UTPI:	SETOM	HDRFLG		;INDICATE HDR GARBAGE TO SKIP
	JRST	TPCOM		;USE COMMON CODE

TAPI:	SETZM	HDRFLG		;INDICATE NO HEADER GARBAGE, 377 IS DATA MRK
TPCOM:	MOVE	1,FILE		;GET FILE JFN
	MOVSI	2,(FLD(^D18,OF%BSZ))	;18 BIT BYTES
	HRRI	2,OF%RD+OF%PLN	;FOR READING
	OPENF	;OPEN FILE
	  ERJMP	EROUT
	SETZM	TAPFLG		;SET UP BYTE ALTERNATION FLG
		;THE FOLLOWING LOOP SEARCHES FOR THE -1 MARKER
	SKIPN	HDRFLG		;SKIP TO DO HDR CHECK
	JRST	TAPIGN		;JRST HERE IF JUST WAIT FOR 377 CHAR

;IF HERE, WE MUST SKIP OVER THE GOOFIE HEADER FORMAT. WE MUST GO UNTIL
;WE SEE A TRIANGLE AND THEN WAIT FOR THE 377 CODE

	PUSH	P,S5		;SAVE A REG
UTPRST:	MOVE	S5,HDNDX	;GET POINTER TO HEADER END CODE
UTPAGN:	PUSHJ	P,TAPDAT		;READ A BYTE
	  JRST	[PMSGC <?Error reading input file.  EOF before all 1's marker seen.>
		 JRST COMAND]
	CAMN	T2,(S5)		;DOES IT LOOK LIKE NEXT CHAR OF TRIANGLE?
	AOBJN	S5,UTPAGN	;INCR INDEX IF YES TO NEXT REQD CHAR, JMP BACK
	JUMPL	S5,UTPRST	;LOOP BACK IF ALL PATTERNS NOT SEEN YET
	POP	P,S5		;RESTORE THE REG

TAPIGN:	PUSHJ	P,TAPDAT		;READ A BYTE
	  JRST	[PMSGC <?Error reading input file.  EOF before all 1's marker seen.>
		 JRST COMAND]
	CAIE	T2,377		;CHK FOR ALL 1'S (SKIP IF TRUE)
	JRST	TAPIGN		;IF NOT ALL 1'S LOOP BACK UNTIL TRUE
ITS2ND:	SETOM	T3		;INIT NEXT BYTE AS FIRST BYTE OF DATA
	POPJ	P,	;RETURN

		;THIS ROUTINE ACTUALLY READS A BYTE OF DATA FROM THE FILE

TAPDAT:	SKIPE	TAPFLG#		;CHK FLG TO DECIDE WHETHER NEED A BIN
	JRST	NOBIN		;BR IF DON'T NEED IT
	MOVE	1,FILE		;GET FILE JFN
	BIN
	 ERJMP	TAPER		;BR IF ERROR
	SKIPN	BINMOD		;SKIP IF PACKED BINARY MODE
	JRST	TAPPAK		;JUMP HERE IF IMAGE MODE
	MOVEM	2,SAVTAP#	;SAVE DATA FOR LATER
	TRZ	2,777400	;SAVE ONLY 8 BITS
	JRST	BINRTN

NOBIN:	LDB	2,[POINT 8,SAVTAP,27]	;GET 8 BITS OF 2ND BYTE
BINRTN:	SETCMM	TAPFLG		;COMPL THE FLAG
BINPRT:	AOS	T3		;NEXT ADDRESS
	AOS	(P)		;DO THE SKIP RTN
	MOVE	T2,2		;MOVE DATA TO T2
	POPJ	P,		;AND RTN

TAPPAK:	BIN			;DO NOTHER BIN FOR JUST RIGHT HALF WORD
	 ERJMP	TAPER		;IMAGE (ONLY RIGHTMOST 8 BITS USED PER WORD)
	TRZ	2,777400	;CLR OUT ALL OTHER BITS
	JRST	BINPRT		;NOW RTN THE DATA

TAPER:	GTSTS			;GET FILE STATUS
	TLNN	2,(GS%EOF)	;CHK FOR EOF
	JRST	EROUT		;BR IF ERROR
	POPJ	P,		;HERE IF JUST EOF. DON'T SKIP RTN
SUBTTL	VARIABLE STORAGE

;PROGRAM VARIABLES

;OPERATING PARAMETERS

FIRST:	0			;FIRST ADDRESS TO SEND
LAST:	0			;LAST ADDRESS TO SEND (0=NOT SPECIFIED)
SIZE:	0			;SIZE OF PROM (0=NOT SPECIFIED)
BYTE:	0			;BYTE POSITION (0=NOT SPECIFIED)
FILE:	0			;JFN OF FILE (0=NO FILE SELECTED)
TYPE:	0			;INDEX OF FILE TYPE
CHECK:	0			;CHECK MODE FLAG (0=OFF, -1=ON)
RADIX:	^D10			;INPUT RADIX FOR FIRST AND LAST COMMAND
FILL:	0			;FILL CHARACTER FOR NULL ADDRESSES
BLASTR:	0			;JFN TO BLASTR:
HDRFLG:	0			;0 NO HDR (TAP), -1 HDR (UTP)

;BUFFERS
OFNAM:	BLOCK 3			;STORAGE FOR OUTPUT FILE NAME

	CMDBFS=^D20
CMDBUF:	BLOCK CMDBFS		;COMMAND TEXT BUFFER
	ATOMBS=^D20
ATOMBF:	BLOCK ATOMBS		;ATOM BUFFER
AUTHST:	ASCIZ/(no name given)/	;AUTHOR'S NAME STORAGE
	BLOCK	ATOMBS		;NEED AT LEAST AS MUCH AS ATOMBF SIZE
JFNBF:	BLOCK 16		;FILENAME INPUT BUFFER
	PROMSZ=^D1024*2
	XWD	0		;MUST HAVE A WORD HERE FOR OUTPUT ROUTINE
ROMBUF:	BLOCK	<PROMSZ/4>+2	;PROM DATA BUFFER PLUS COUPLE OF EXTRA WDS
				;(NEEDED NEAR COMNUL)

TEMPBF:	BLOCK 8
COMBUF:	BLOCK	ATOMBS		;ROOM FOR COMMENT

PATCH:	BLOCK	100		;PATCH AREA

HDNDX:	-^D8,,HDDAT		;# DATA PATTERNS FOR END OF HEADER MARKER
HDDAT:	1			;THIS TABLE IS THE LIST OF CODES IN UTP MODE
	3			;TO TELL BLAST WHERE THE END OF HEADER IS.
	7			;AFTER THIS CODE, YOU THEN SEARCH FOR THE NEXT
	17			;377 DATA CHAR AND THE NEXT CHAR IS THE 1ST
	37			;CHAR OF DATA
	77
	177
	377

PLIST:	-100,,PLISTS-1		;STACK POINTER

PLISTS:	BLOCK 100		;STACK
SUBTTL	TABLE STORAGE

;TABLE OF COMMANDS FOR INPUT BY COMND CALL

F1:	^D23,,^D23			;NUMBER OF ENTRIES
	[ASCIZ/ARRAY/],,ARRAY
	[ASCIZ/AUTHOR/],,AUTHOR
	[ASCIZ/BYTE/],,BYTEC
	[ASCIZ/CLOSE/],,CLOSE
	[ASCIZ/COMMENT/],,COMENT
	[ASCIZ/DECIMAL/],,DECIML
	[ASCIZ/EXIT/],,EXIT
	[ASCIZ/FILE/],,FILENM
	[ASCIZ/FIRST/],,FIRSTC
	[ASCIZ/HELP/],,HELP
	[ASCIZ/IMAGE/],,IMAGE
	[ASCIZ/INVERT/],,INVRT
	[ASCIZ/LAST/],,LASTC
	[ASCIZ/NOINVERT/],,NOINVRT
	[ASCIZ/NULL/],,NULL
	[ASCIZ/OCTAL/],,OCTAL
	[ASCIZ/OPEN/],,OPEN
	[ASCIZ/OUTPUT/],,OUTPUT
	[ASCIZ/PACKED/],,PACKED
	[ASCIZ/PRINT/],,PRINT
	[ASCIZ/RELEASE/],,RELEAS
	[ASCIZ/SEND/],,SEND
	[ASCIZ/SIZE/],,SIZEC

;TABLE OF RECOGNIZED TYPE FIELDS

TYPFLD:	^D10,,^D10			;NUMBER OF ENTRIES
	[ASCIZ/A78/],,[I80I,,I80DAT]
	[ASCIZ/DAT/],,[I80I,,I80DAT]
	[ASCIZ/E16/],,[E16I,,E16DAT]
	[ASCIZ/E32/],,[E32I,,E32DAT]
	[ASCIZ/PTP/],,[I80I,,I80DAT]
	[ASCIZ/R16/],,[R16I,,R16DAT]
	[ASCIZ/R28/],,[R28I,,R28DAT]
	[ASCIZ/ROM/],,[ROMI,,ROMDAT]
	[ASCIZ/TAP/],,[TAPI,,TAPDAT]
	[ASCIZ/UTP/],,[UTPI,,TAPDAT]

;TABLE OF SIZES IN K

KSIZE:	2,,2
	[ASCIZ/1K/],,^D1024*1
	[ASCIZ/2K/],,^D1024*2

PMBTAB:	POINT	8,S2,17			;1ST BYTE
	POINT	8,S2,9			;2ND BYTE
	POINT	8,S2,35			;3RD BYTE
	POINT	8,S2,27			;4TH BYTE

END	START