.TITLE DEHEX .SBTTL Stuart Hecht .IDENT /1.0.00/ .LIBRARY /LB:[1,5]RMSMAC/ .ENABLE LC .NLIST BEX ;++ ;This will take a set hexidecimal strings created by the hexify program and ; recreate the source file(s). ;-- .MCALL QIOW$C,QIO$C,QIOW$S,QIO$S,QIOW$,ALUN$S,EXIT$S .MCALL FAB$B ; RMS calls .MCALL RAB$B .MCALL $CLOSE .MCALL $CONNECT .MCALL $CREATE .MCALL $DISCONNECT .MCALL $GET .MCALL $OPEN .MCALL $FETCH .MCALL $WRITE .MCALL $STORE .MCALL $SET .MCALL ORG$ .MCALL POOL$B .SBTTL Definitions of symbols TERLUN =7 ; Terminal LUN XKLUN =8. ; XK LUN TTEFN =1 ; Terminal Event Flag XKREFN =2 ; XK read Event Flag XKWEFN =3 ; XK write Event Flag DWRLUN =1 ; Disk read LUN DWWLUN =5 ; Disk write LUN TRUE =1 ; True FALSE =0 ; False NULL =0 ; Null byte KNORMAL =0 ; No error RMS11 =1 ; RMS error LEFTBYTE=377*400 ; All ones in left byte RIGHTBYTE=377 ; All ones in right byte HEXOFFSET=7 ; Offset to get to 'A from '9+1 MAX.MSG =256. ; Maximum number of chars from XK RCV.SOH =': ; Receive start of packet RCV.EOL =13. ; End of line character UPPER ='a-'A ; Bit to clear for upper case MSB =128. ; Most significant bit ; Packet types currently supported PKDATA =00 ; Data packet code PKRFM =255. ; Record format PKRAT =254. ; Record attributes PKMRS =253. ; Maximum record size PKALQ =252. ; File length(blocks) PKFILNM =251. ; File name PKEOF =250. ; End of task file ; .SBTTL RMS Initialization POOL$B ; Allocate static pool for RMS P$RAB 5 ; For internal RABs P$BDB 5 ; For buffer descriptor blocks P$FAB 4 ; For internal FABs P$BUF 2048. ; Buffer space POOL$E ; End of pool declarations ORG$ SEQ ; $Open a sequential file .SBTTL RMS 11 Data .PSECT $PLIT$,RO,D DEFALT: .ASCIZ 'SY:' ; System default. DEFALN =.-DEFALT ; Size of the default device. .EVEN .SBTTL Data M$PORT: .BYTE CR,LF .ASCII 'Please choose device to use:' .BYTE CR,LF .ASCII '1. Communications port' .BYTE CR,LF .ASCII '2. Printer port' .BYTE CR,LF .ASCII '3. Disk file' .BYTE CR,LF .ASCII ' CHOICE (1-3): ' L$PORT= .-M$PORT M$FILE: .BYTE CR,LF .ASCII 'Please type the file name: ' L$FILE= .-M$FILE M$SET: .BYTE CR,LF .ASCII 'Is the port already setup correctly(baud rate)? ' L$SET= .-M$SET M$BAUD: .BYTE CR,LF .ASCII 'Choose a baud rate:' .BYTE CR,LF .ASCII '1. 300' .BYTE CR,LF .ASCII '2. 1200' .BYTE CR,LF .ASCII '3. 2400' .BYTE CR,LF .ASCII '4. 4800' .BYTE CR,LF .ASCII '5. 9600' .BYTE CR,LF .ASCII ' CHOICE (1-5): ' L$BUAD =.-M$BAUD D$BAUD: .BYTE S.300,S.1200,S.2400,S.4800,S.9600 ; Baud rate code table ; for set multiple characteristics M$CRLF: .BYTE CR,LF ; Data for carriage return/line feed L$CRLF =.-M$CRLF M$AK: .BYTE LF ; Data for aknowledged .ASCII 'Y' .BYTE CR L$AK =.-M$AK M$NAK: .BYTE LF ; Data for not aknowledged .ASCII 'N' .BYTE CR L$NAK =.-M$NAK M$UN: .BYTE LF ; Data for unrecognized code .ASCII 'U' .BYTE CR L$UN =.-M$UN M$RMS: .BYTE CR,LF,LF .ASCII 'RMS ERROR' L$RMS =.-M$RMS M$INIT: .BYTE CR,LF,LF .ASCII 'Port in use - Try again when free.' L$INIT =.-M$INIT M$REC: .BYTE CR,LF,LF .ASCII 'RECEIVE ERROR - Try again.' L$REC =.-M$REC .EVEN .SBTTL Data for set multiple characteristics .PSECT $OWN$ T$SMC: .BYTE TC.RSP ; Receive speed RSP: .BLKB 1 .BYTE TC.XSP ; Transmit speed XSP: .BLKB 1 .BYTE TC.PAR,0 ; No parity .BYTE TC.FSZ,8. ; Frame size L$SMC =.-T$SMC .SBTTL Storage locations IOSTAT: .BLKW 1 ; QIO status STAT1: .BLKW 1 ; Second word of status WTCOUNT: .BLKW 1 ; Number of characters written LENGTH: .BLKW 1 ; Length of data portion of packet OPENFL: .BLKW 1 ; Tells us if the file is open FILEFL: .BLKW 1 ; Flag that is set when reading from ; a file LPFLAG: .BLKW 1 ; Flag that is set when reading from ; the printer port CHKSUM: .BLKW 1 ; Checksum for the line ADDRESS: .BLKW 1 ; Current address ALQLOC: .BLKW 2 ; Storage for allocation OUT.N: .BLKB 28. ; Space for output file name OUT.L =.-OUT.N ; Length of output file name INP.N: .BLKB 28. ; Space for input file name INP.L =.-INP.N ; Length of input file name .EVEN ; Need to start RDBUF on even boundary RDBUF: .BLKB MAX.MSG ; XK read buffer .EVEN WTBUF: .BLKB 512. ; Disk write buffer .EVEN .SBTTL RMS 11 Data structures RDFAB:: FAB$B F$DNA DEFALT ; Address of default device. F$DNS DEFALN ; Default length field. F$FNA INP.N ; Address of file name F$FNS INP.L ; Length of file name F$LCH DWRLUN ; Logical channel to use FAB$E .EVEN RDRAB:: RAB$B ; Beginning of RAB block. R$FAB RDFAB ; Chain to FAB block. R$RAC RB$SEQ ; Set the sequential access flag. RAB$E ; End RAB block. .EVEN WTFAB:: FAB$B F$DNA DEFALT ; Address of default device. F$DNS DEFALN ; Default length field. F$FNA OUT.N ; Address of file name F$FNS OUT.L ; Length of file name F$LCH DWWLUN ; Logical channel to use FAB$E .EVEN WTRAB:: RAB$B ; Beginning of RAB block. R$FAB WTFAB ; Chain to FAB block. R$RAC RB$SEQ ; Set the sequential access flag. RAB$E ; End RAB block. .EVEN .SBTTL Start of program .PSECT $CODE$,RO,I DEHEX:: ALUN$S #TERLUN,#"TI,#0 ; Assign terminal LUN 1$: MOV #M$PORT,R0 ; Output the port option list MOV #L$PORT,R1 JSR PC,WRITE MOV #RDBUF,R0 ; Input the port the user wants MOV #2,R1 JSR PC,READ CLR FILEFL ; Set flag to say we are reading from CLR LPFLAG ; some port(assume correct) CMPB RDBUF,#'1 ; Check and see if choice is XK BNE 3$ ; No so branch ALUN$S #XKLUN,#"XK,#0 ; Assign the LUN BR 6$ ; Continue with program (set port) 3$: CMPB RDBUF,#'2 ; Check and see if choice is LP BNE 4$ ; If no then branch ALUN$S #XKLUN,#"TT,#2 ; Assign the LUN MOV #TRUE,LPFLAG ; Set flag we're reading from LP BR BEGIN ; Continue with program 4$: CMPB RDBUF,#'3 ; Make sure its the remaining choice BNE 1$ ; If not then try again JMP FILE ; Go do the disk file ; Set up XK port 6$: JSR PC,XKINIT ; Get the XK port 7$: MOV #M$SET,R0 ; Output the is port set up message MOV #L$SET,R1 JSR PC,WRITE MOV #RDBUF,R0 ; Get response MOV #2,R1 JSR PC,READ TST R0 ; Check for input BEQ 7$ ; If none then reprompt BICB #UPPER,RDBUF ; Convert to upper case CMPB RDBUF,#'Y ; Check to see if afirmative BNE 8$ ; If not then set it up JMP BEGIN ; Port already set so don't do it 8$: MOV #M$BAUD,R0 ; Output baud rate message MOV #L$BUAD,R1 JSR PC,WRITE MOV #RDBUF,R0 ; Get response MOV #2,R1 JSR PC,READ TST R0 ; Check for input BEQ 7$ ; If none then reprompt MOVB RDBUF,R0 ; Get the answer SUB #'1,R0 ; Subtract off ASCII MOVB D$BAUD(R0),RSP ; Set the baud rate MOVB D$BAUD(R0),XSP ; Set the characteristics QIO$C SF.SMC,XKLUN,XKWEFN,,IOSTAT,,,$CODE$ BR BEGIN ; Go do real stuff ; If here then we're doing a file FILE: MOV #M$FILE,R0 ; Output the get file name message MOV #L$FILE,R1 JSR PC,WRITE MOV #INP.N,R0 ; Get the file name MOV #INP.L,R1 JSR PC,READ TST R0 ; Check for no input BEQ FILE ; Go back and get some ;Open the file MOV #RDFAB,R1 ; Put address of FAB into R1. $STORE R0,FNS,R1 ; Tell RMS file name length $OPEN #RDFAB ; Open the file JSR PC,RMSERR ; Check for file error MOV #RDRAB,R1 ; Put address of RAB into R1. $STORE #RDBUF,UBF,R1 ; Put address of user buffer in RAB. $STORE #RDBUF,RBF,R1 ; Put record buffer address in RAB $STORE #MAX.MSG,USZ,R1 ; Put size of user buffer into RAB. $STORE #MAX.MSG,RSZ,R1 ; Put record buffer size in RAB $CONNECT #RDRAB ; Connect to record. JSR PC,RMSERR ; Check for file error MOV #TRUE,FILEFL ; Set flag to file reading .SBTTL Do the real work ;++ ; Do the actual work ;-- BEGIN: MOV #M$CRLF,R0 ; Get a return/linefeed and output them MOV #L$CRLF,R1 JSR PC,WRITE 20$: CLR WTCOUNT ; Initialize the pointer CLR ADDRESS ; Initialize the address CLR OPENFL ; Set the file to not open ; Say we're ready for data MOV #M$AK,R0 ; Get the address of stuff to send MOV #L$AK,R1 ; Get the length JSR PC,SEND ; Tell host that we got it .SBTTL Main loop ; Main loop to get data DOLIN: CLR CHKSUM ; Clear the checksum JSR PC,RECEIVE ; Get the line JSR PC,CVTBIN ; Convert it to a real number MOV R0,LENGTH ; Save the length JSR PC,CVTBIN ; MOV R0,R3 ; Save high order of address SWAB R3 ; Shift to correct spot JSR PC,CVTBIN ; BIS R0,R3 ; Fill in the low order of address JSR PC,CVTBIN ; CMP #PKDATA,R0 ; Check to see if this is regular data BNE NOTDAT ; If not then check the special cases ; Check for end of hex file TST R3 ; Check to see if the address is all BNE DATST ; zero, if not then branch TST LENGTH ; Check to see if the length is zero BNE DATST ; also, if not then branch MOV #M$AK,R0 ; Send an AK for this line since we MOV #L$AK,R1 ; never reach the place we normally JSR PC,SEND ; do this JMP FINISH ; Must be end of hex file so finish up ; Regular data to put into the file DATST: TST OPENFL ; Check to see if the file is open yet BNE DAT1 ; If it is then skip the open JSR PC,OPEN ; Open the file DAT1: CMP R3,ADDRESS ; Check for null compression BEQ 10$ ; If none compressed then continue past CLR R0 ; Make a null JSR PC,PUT ; and put it into the file INC ADDRESS ; Point to next address BR DATST ; Go see if there are any more nulls ; Go to work on the HEX we got on the line 10$: MOV LENGTH,R2 ; Get the length TST R2 ; See if there is any data BEQ 30$ ; If not then branch 25$: JSR PC,CVTBIN ; Convert it JSR PC,PUT ; Put the character in the file INC ADDRESS ; Increment the address SOB R2,25$ ; Repeat until all done 30$: BR LINDON ; Go finish this line NOTDAT: MOV #WTFAB,R5 ; Get the FAB address CMP #PKRFM,R0 ; Check to see if this is record fmt BNE NOTRFM ; If not then don't do this stuff ; Store the Record format (FIX, VAR, ...) JSR PC,CVTBIN ; $STORE R0,RFM,R5 ; Store the record format BR LINDON ; Go finish this line NOTRFM: CMP #PKRAT,R0 ; Check to see if this is record type BNE NOTRAT ; If not then branch ; Store the record type (CR, ...) JSR PC,CVTBIN ; $STORE R0,RAT,R5 ; Store the record type BR LINDON ; Go finish this line NOTRAT: CMP #PKMRS,R0 ; Check to see if this is max record BNE NOTMRS ; size, branch if not ; Get the maximum record size (512. for tasks) JSR PC,CVTBIN ; Convert high order byte MOV R0,R3 ; Save it SWAB R3 ; Shift it to the high order byte JSR PC,CVTBIN ; Convert low order byte BIS R0,R3 ; Put low order word into R3 also $STORE R3,MRS,R5 ; Store the maximum record size BR LINDON ; Go finish this line NOTMRS: CMP #PKALQ,R0 ; Check to see if this is allocation BNE NOTALQ ; If not then branch ; Get the file length (in blocks) JSR PC,CVTBIN ; Convert high order byte MOV R0,R3 ; Save it SWAB R3 ; Shift it to the high order byte JSR PC,CVTBIN ; Convert low order byte BIS R0,R3 ; Put low order word into R3 also MOV R3,ALQLOC ; Save it CLR ALQLOC+2 ; clear out high word $STORE ALQLOC,ALQ,R5 ; Store the allocation BR LINDON ; Go finish this line NOTALQ: CMP #PKFILNM,R0 ; Check to see if this is file name BNE NOTFILNM ; If not then branch ; Get the file name MOV LENGTH,R2 ; Get the length $STORE R2,FNS,R5 ; Store the file name length MOV #OUT.N,R3 ; Get the output file name address 25$: JSR PC,CVTBIN ; Convert next character of the name MOVB R0,(R3)+ ; Save the character SOB R2,25$ ; Repeat until all done MOV #M$CRLF,R0 ; MOV #L$CRLF,R1 ; JSR PC,WRITE ; Output a return/line feed MOV #OUT.N,R0 ; MOV LENGTH,R1 ; JSR PC,WRITE ; Output the file name MOV #M$CRLF,R0 ; MOV #L$CRLF,R1 ; JSR PC,WRITE ; Output a return/line feed BR LINDON ; Go finish this line NOTFILNM: CMP #PKEOF,R0 ; Check to see if this is end of task BNE NOTPKEOF ; If not then branch ; End of ouput file record found JSR PC,CLTSK ; Close the task file CLR WTCOUNT ; Initialize the pointer CLR ADDRESS ; Initialize the address JMP LINDON ; Go finish this line ; Unknown code NOTPKEOF: ; Since we don't know what the code MOV #M$UN+1,R0 ; just send the unknown code text to MOV #1,R1 ; the terminal and the port JSR PC,WRITE ; DEC R0 ; Move to beginning of data MOV #L$UN,R1 ; JSR PC,SEND ; JMP DOLIN ; Go do next input line .SBTTL Finished with this line ; Line processed without a problem LINDON: MOV #M$AK+1,R0 ; Get the data address of the ; single character MOV #1,R1 ; Only write single char to terminal JSR PC,WRITE ; Write to the terminal DEC R0 ; Get to beginning of data MOV #L$AK,R1 ; Get the length of the data JSR PC,SEND ; Send the aknowledgement to the port JMP DOLIN ; Good so do next line .SBTTL Finish up ;++ ;Finish up ;-- FINISH: ; Close the file(s) JSR PC,CLTSK ; Close the task file if it isn't yet TST FILEFL ; See if we read from a file BEQ 10$ ; If not then branch MOV #RDFAB,R1 ; Get FAB for input file $CLOSE R1 ; Close the input file JSR PC,RMSERR ; Check for file error BR END ; Go exit 10$: JSR PC,XK.SHT ; Shut down the XK port if we didn't ; read from a file END: EXIT$S .SBTTL Close file ;++ ; Close the output file if there is one open ; ; If there is an error the program stops with an RMS error ; ; Registers destroyed: R0, R1 ; The OPENFL state is changed to file not open (OPENFL=0). ;-- CLTSK: TST OPENFL ; See if the task file is open BEQ 10$ ; If not then just return ; Write last buffer if needed TST WTCOUNT ; See if there is any data not written BEQ 8$ ; If not then branch MOV #WTRAB,R1 ; Get the RAB address $STORE WTCOUNT,RSZ,R1 ; Put its size into the RAB. $WRITE R1 ; Put the buffer of data. JSR PC,RMSERR ; Check for file error ; Close the file 8$: MOV #WTFAB,R1 ; Get FAB for output file $CLOSE R1 ; Close output file JSR PC,RMSERR ; Check for file error CLR OPENFL ; Set the state to file not open 10$: RTS PC ; Return to sender .SBTTL Output and input to/from terminal ;++ ; Write data to terminal. ; Call with: R0 Address of data to output ; R1 Length of data ; Registers destroyed: NONE ;-- WRITE: QIOW$S #IO.WVB,#TERLUN,#TTEFN,,#IOSTAT,, RTS PC ;++ ; Read from the terminal ; Call with: R0 Address of buffer ; R1 Number of characters to read ; ; Returned: R0 Number of characters read ; Registers destroyed: R0 ;-- READ: QIOW$S #IO.RVB!TF.ESQ,#TERLUN,#TTEFN,,#IOSTAT,, MOV STAT1,R0 ; Get the number of character read RTS PC .SBTTL RMS error routine ;++ ;Check for RMS error ; Call with: R1 RMS FAB address ; ; Returned: R0 Status ; Registers destroyed: R0 ; Program stops after error message is displayed if there is any type of error. ;-- RMSERR: $FETCH R0,STS,R1 ; Get the status and put it in R0 TST R0 ; Test the status code for success. BMI 60$ ; If negative then branch. MOV #KNORMAL,R0 ; Set up a successful return code. RTS PC ; Return to caller ; Here if there is an RMS error we can't recover from 60$: MOV #M$RMS,R0 ; Get the RMS error message MOV #L$RMS,R1 ; address and length JSR PC,WRITE ; Output the error message EXIT$S ; Exit since we can not recover .SBTTL Open the output file ;++ ; Create and open the output file and set the file open flag ; ; Registers destroyed: R0, R1 ; Program stops after error message is displayed if there is any type of error. ;-- OPEN: MOV #TRUE,OPENFL ; State that the file is open MOV #WTFAB,R1 ; Put address of FAB into R1. $SET #FB$WRT,FAC,R1 ; Set the block write in FAB. $STORE #FB$CTG,FOP,R1 ; Tell RMS to make the task contiguous $CREATE #WTFAB ; Create the file JSR PC,RMSERR ; Check for file error MOV #WTRAB,R1 ; Put address of RAB into R1. $STORE #WTBUF,UBF,R1 ; Put address of user buffer in RAB. $STORE #WTBUF,RBF,R1 ; Put record buffer address in RAB $STORE #512.,USZ,R1 ; Put size of user buffer into RAB. $STORE #512.,RSZ,R1 ; Put record buffer size in RAB $CONNECT #WTRAB ; Connect to record. JSR PC,RMSERR ; Check for file error RTS PC ; Return to sender .SBTTL Put a character to the file ;++ ; Put a character to the output file. ; The buffer is only written when 512. characters have been sent to the routine ; If the file does not end on a boundary then the buffer will have to be ; written by some other routine. ; ; Call with: R0 Contains the character to be put into file ; Registers destroyed: R0, R1 ; ; Program stops after error message is displayed if there is any type of error. ;-- PUT: MOV R0,-(SP) ; Save the character MOV WTCOUNT,R0 ; Get the offset into the buffer MOVB (SP)+,WTBUF(R0) ; Put the character INC WTCOUNT ; Increment the offset into the buffer CMP WTCOUNT,#512. ; Check to see if we are past the end BNE 10$ ; If not then branch MOV #WTRAB,R1 ; Get the RAB address $STORE WTCOUNT,RSZ,R1 ; Put its size into the RAB. $WRITE R1 ; Put the buffer of data. JSR PC,RMSERR ; Check for file error CLR WTCOUNT ; Clear the pointer 10$: RTS PC ; Return to sender .SBTTL Convert to binary ;++ ; Convert 2 hexidecimal digits to binary ; Input is from the input buffer pointed to by R4 (it is incremented twice) ; ; Call with: R4 The pointer into the input buffer ; Returned: R0 The binary walue ; Registers destroyed: R0,R1 ;-- CVTBIN: CLR R0 ; Clear R0 for the BISB BISB (R4)+,R0 ; Get the next digit JSR PC,BIN ; in place and convert to binary ASH #4,R0 ; Multiply the result by 16 MOV R0,R1 ; and save it CLR R0 ; Clear R0 BISB (R4)+,R0 ; Get the next digit JSR PC,BIN ; Convert to binary BIS R1,R0 ; Set the correct bits for high order ADD R0,CHKSUM ; Add the value to the checksum RTS PC ; Return to sender BIN: CMP R0,#'9 ; Check to see if above '9 BLE 1$ ; If not then branch SUB #HEXOFFSET,R0 ; Subtract offset to alphabet 1$: SUB #48.,R0 ; Make binary RTS PC ; Return to sender .SBTTL Initialize the port XKINIT: ;++ ; Attach to the port so that no one else can be screwing around ; with it behind our backs. ; ; Registers destroyed: R0 ; ; If there is an error the error message will be output and the program ; will stop. ;-- QIO$S #IO.ATT,#XKLUN,#XKREFN,,#IOSTAT ; Grab the device MOVB IOSTAT,R0 ; Get the status BLE BAD ; Branch if bad ; Set the characteristics RTS PC ; Return good try ; Here if we can't get the XK port BAD: MOV #M$INIT,R0 ; Get the INIT error message MOV #L$INIT,R1 ; address and length JSR PC,WRITE ; Output the error message QIOW$C IO.KIL,XKLUN,XKWEFN,,,,,$CODE$ ; Kill pending I/O queues. EXIT$S ; Exit since we can not recover XK.SHT: QIOW$C IO.KIL,XKLUN,XKWEFN,,,,,$CODE$ ; Kill pending I/O queues. QIOW$C IO.DET,XKLUN,XKWEFN,,,,,$CODE$ ; Detach the device RTS PC ; And return .SBTTL Receive a line of data ;++ ; This will get a line of data from the input device ; ; Returned: R4 Address of start of data buffer ; Registers destroyed: R0, R1, R3, R4 ; ; A checksum error will cause a NAK to be sent and input to be read again ; A real error will cause an error message to be output and the program to stop ;-- RECEIVE: TST FILEFL ; See if we're reading from a file BEQ 10$ ; If not then don't read from the file ; Here if we're reading from a file MOV #RDRAB,R1 ; Get the RAB address $GET R1 ; Get the record JSR PC,RMSERR ; Check for file error MOV #MAX.MSG,R3 ; Assume we got a full buffer BR RECCHK ; Check the data we got ; Here so reading from one of the ports 10$: TST LPFLAG ; See if we're reading from LP: BNE RECLP ; If so then use that routine ; Here if we're reading from the XK port MOV #RDBUF,R1 ; Point at first byte of buffer CLR R3 ; Clear count of chars we have seen QIOW$S #IO.RAL!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,, TST IOSTAT ; Test for error BMI 85$ ; If we got an error, return it BICB #MSB,(R1) ; Clear most significant bit CMPB (R1)+,#RCV.SOH ; Check for start of header BNE 10$ ; If not, check timeout and try again INC R3 ; Increment the counter ; Here after we have gotten the start of packet character. Now pick up the ;rest 20$: QIOW$S #IO.RAL!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,, TST IOSTAT ; Test for error BMI 85$ ; If we got an error, return it BICB #MSB,(R1) ; Clear most significant bit CMPB @R1,#RCV.SOH ; Check for start of header BEQ 10$ ; Restart buffer if so INC R3 ; Count the character CMPB (R1)+,#RCV.EOL ; Get end of line character? BEQ RECCHK ; Yes, go return CMP R3,#MAX.MSG ; Fill buffer completly yet? BNE 20$ ; If not, just get next character DEC R1 ; Otherwise, back up one character BR 20$ ; And try again ; Here if we got some error that makes it impossible to continue the transfer 85$: MOV #M$REC,R0 ; Get the receive error message MOV #L$REC,R1 ; address and length JSR PC,WRITE ; Output the error message EXIT$S ; Exit since we can not recover ; Here to read from LP port(TT2:) RECLP: QIOW$S #IO.RVB!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<#RDBUF,#MAX.MSG> MOV STAT1,R3 ; Get number of characters read ; Here to check the data we got from any type of receive routine RECCHK: MOV #RDBUF,R4 ; Get the address of the information CLR R1 ; Clear the data start address 80$: BICB #MSB,(R4) ; Clear parity bit CMPB (R4)+,#RCV.SOH ; Check for start of header BNE 81$ ; If not the just keep going MOV R4,R1 ; Start of header so save it 81$: SOB R3,80$ ; Repeat until done TST R1 ; Check to see if we got a SOH BNE 85$ ; If good then skip the jump JMP RECEIVE ; If not then re-read 85$: MOV R1,R4 ; Move to R4 for use MOV R4,-(SP) ; Save SOH pointer on stack JSR PC,CVTBIN ; Convert all to binary to see if MOV R0,R3 ; Get the length of data ADD #4,R3 ; Add the length of address and field ; type and checksum BMI 94$ ; If we have a negative number then ; must have been a bad length CMP R3,#MAX.MSG/2-1 ; If we got some length that is out of BGE 94$ ; range then NAK right away 92$: JSR PC,CVTBIN ; Convert all to binary to see if SOB R3,92$ ; the checksum is OK 93$: BIC #LEFTBYTE,CHKSUM ; We only want an 8 bit checksum TST CHKSUM ; Test for a zero checksum BEQ 95$ ; If OK then exit normally 94$: CLR CHKSUM ; Clear the checksum for the line MOV #M$NAK+1,R0 ; Get the address of the message MOV #1,R1 ; Only write the first character to JSR PC,WRITE ; the terminal DEC R0 ; Move to beginning of data MOV #L$NAK,R1 ; Get the whole message length for port JSR PC,SEND ; Send a NAK to the port TST (SP)+ ; Pull to pointer off the stack JMP RECEIVE ; Try to get the line again ; Return to sender 95$: MOV (SP)+,R4 ; Get the pointer back RTS PC ; Return to sender .SBTTL Send a line to the host ;++ ; Send the buffer to the host if we aren't reading from a file ; If reading from a file just return ; ; Registers destroyed: None ;-- SEND: TST FILEFL ; See if we're reading from a file BNE 20$ ; If so then don't send to the port QIOW$S #IO.WLB,#XKLUN,#XKWEFN,,#IOSTAT,, 20$: RTS PC ; Return to sender .SBTTL End of the Dehexify .END DEHEX