home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / vmskermit32.zip / vmsdeh.mar < prev    next >
Text File  |  1989-04-04  |  26KB  |  591 lines

  1.         .TITLE  DEHEX
  2.         .SBTTL  Stuart Hecht and Eric McQueen, Stevens Inst of Technology
  3.  
  4.         .LIBRARY /SYS$LIBRARY:STARLET/
  5.         .LIBRARY /SYS$LIBRARY:LIB/
  6.         .IDENT   /1.1.02/
  7. ;++
  8. ;1.1.01
  9. ;Updated March 9, 1898, by Susan Webb and Jerry Holliday of Lockheed Aircraft
  10. ;Systems Co, Marietta, GA, to work for files longer than 64K.  Added lines
  11. ;marked with ";JH".
  12. ;--
  13. ;++
  14. ;1.1.02
  15. ;Updated March 15, 1989, by Tom Allebrandi of Advanced Computer Consulting,
  16. ;Inc, Charlottesville, VA. (ta2@acci.com)
  17. ;
  18. ;On March 14, 1989, I pulled this file and VMSMIT.HEX from Columbia via
  19. ;KERMSRV. After compiling, this utility would not decode the VMSMIT file.
  20. ;The problem was the 1.1.01 fix noted above.
  21. ;
  22. ;I have removed the 1.1.01 fix and coded it so that it works correctly.
  23. ;My changes are marked ";ta2"
  24. ;--
  25.  
  26. ;++
  27. ;This will take a set hexidecimal strings created by the hexify program and
  28. ;  recreate the source file(s).
  29. ;--
  30.  
  31.         .EXTRN  LIB$GET_INPUT
  32.         .EXTRN  LIB$PUT_OUTPUT
  33.         .EXTRN  DSC$K_DTYPE_T
  34.         .EXTRN  DSC$K_CLASS_S
  35.         .EXTRN  SS$_NORMAL
  36.         .MCALL  $FAB                            ; RMS calls
  37.         .MCALL  $RAB
  38.         .MCALL  $CLOSE
  39.         .MCALL  $CONNECT
  40.         .MCALL  $CREATE
  41.         .MCALL  $DISCONNECT
  42.         .MCALL  $GET
  43.         .MCALL  $OPEN
  44.         .MCALL  $WRITE
  45.         .MCALL  $RAB_STORE
  46.         .MCALL  $FAB_STORE
  47.  
  48.         .SBTTL  Definitions of symbols
  49.  
  50. DWRLUN  =1                              ; Disk read LUN
  51. DWWLUN  =5                              ; Disk write LUN
  52. TRUE    =1                              ; True
  53. FALSE   =0                              ; False
  54. KNORMAL =0                              ; No error
  55. LEFTBYTE=^O377*^O400                    ; All ones in left byte
  56. HEXOFFSET=7                             ; Offset to get to 'A from '9+1
  57. CR      =13.                            ; Carriage return
  58. LF      =10.                            ; Line feed
  59. MAX.MSG =256.                           ; Maximum number of chars from XK
  60. RCV.SOH =^A/:/                          ; Receive start of packet
  61. RCV.EOL =13.                            ; End of line character
  62. MSB     =128.                           ; Most significant bit
  63. ; Packet types currently supported
  64. PKDATA  =00                             ; Data packet code
  65. PKRFM   =255.                           ; Record format
  66. PKRAT   =254.                           ; Record attributes
  67. PKMRS   =253.                           ; Maximum record size
  68. PKALQ   =252.                           ; File length(blocks)
  69. PKFILNM =251.                           ; File name
  70. PKEOF   =250.                           ; End of task file
  71. ;
  72.  
  73.  
  74.         .SBTTL  RMS Data
  75.  
  76.         .PSECT  $PLIT$,LONG
  77.  
  78. DEFALT: .ASCIZ  'SYS$DISK:'             ; System default.
  79. DEFALN  =.-DEFALT                       ; Size of the default device.
  80.         .EVEN
  81.  
  82.         .SBTTL  Data
  83.  
  84.  
  85. M$FILE: .BYTE   CR,LF
  86.         .ASCII  'Please type the file name: '
  87. L$FILE= .-M$FILE
  88.  
  89. M$CRLF: .BYTE   CR,LF                   ; Data for carriage return/line feed
  90. L$CRLF  =.-M$CRLF
  91.  
  92. ;M$AK:
  93. ;       .ASCII  'Y'                     ; Data for aknowledged
  94.  
  95. M$NAK:
  96.         ;.ASCII 'N'                     ; Data for not aknowledged
  97.         .ASCII  'BAD CHECK SUM'         ; Data for not aknowledged
  98. L$NAK   =.-M$NAK
  99.  
  100. M$UN:
  101.         ;.ASCII 'U'                     ; Data for unrecognized code
  102.         .ASCII  'UNKNOWN BLOCK TYPE'    ; Data for unrecognized code
  103. L$UN    =.-M$UN
  104.  
  105. M$RMS:  .BYTE   CR,LF,LF
  106.         .ASCII  'RMS ERROR'
  107. L$RMS   =.-M$RMS
  108.  
  109. M$REC:  .BYTE   CR,LF,LF
  110.         .ASCII  'RECEIVE ERROR - Try again.'
  111. L$REC   =.-M$REC
  112.         .EVEN
  113.  
  114.  
  115.         .SBTTL  Storage locations
  116.  
  117.         .PSECT  $OWN$,LONG
  118.         .ALIGN  LONG
  119.  
  120. MSGDSC: .BLKW   1                       ; Data block for terminal output
  121.         .BYTE   DSC$K_DTYPE_T
  122.         .BYTE   DSC$K_CLASS_S
  123. ADDR:   .ADDRESS ADDR
  124. LNGADR: .BLKL   1
  125.  
  126. INP_STR_D:                              ; Key string desciptor
  127.          .BLKL  1
  128. INP_BUF: .ADDRESS ADDR
  129.  
  130. INP_STR_LEN: .BLKL 1                    ; Key string length
  131.  
  132. WTCOUNT: .BLKL  1                       ; Number of characters written
  133. LENGTH: .BLKL   1                       ; Length of data portion of packet
  134. OPENFL: .BLKL   1                       ; Tells us if the file is open
  135.  
  136. CHKSUM: .BLKL   1                       ; Checksum for the line
  137. ADDRESS: .BLKL  1                       ; Current address
  138. ALQLOC: .BLKW   2                       ; Storage for allocation
  139.  
  140. OUT.N:  .BLKB   28.                     ; Space for output file name
  141. OUT.L   =.-OUT.N                        ; Length of output file name
  142.  
  143. INP.N:  .BLKB   28.                     ; Space for input file name
  144. INP.L   =.-INP.N                        ; Length of input file name
  145.  
  146.         .EVEN                           ; Need to start RDBUF on even boundary
  147. RDBUF:  .BLKB   MAX.MSG                 ; XK read buffer
  148.         .EVEN
  149. WTBUF:  .BLKB   512.                    ; Disk write buffer
  150.         .EVEN
  151.  
  152.  
  153.  
  154.         .SBTTL  RMS Data structures
  155.         .ALIGN  LONG
  156.  
  157. RDFAB:: $FAB    DNA=DEFALT,DNS=DEFALN,FNA=INP.N,FNS=INP.L,-
  158.                 LCH=DWRLUN,FAC=GET,SHR=GET
  159.  
  160.         .ALIGN  LONG
  161. RDRAB:: $RAB    FAB=RDFAB,RAC=SEQ ; Beginning of RAB block.
  162.  
  163.         .ALIGN  LONG
  164. WTFAB:: $FAB    DNA=DEFALT,DNS=DEFALN,FNA=OUT.N,FNS=OUT.L,-
  165.                 LCH=DWWLUN,FAC=PUT,SHR=NIL
  166.  
  167. WTRAB:: $RAB    FAB=WTFAB,RAC=SEQ ; Beginning of RAB block.
  168.  
  169.  
  170.         .SBTTL  Start of program
  171.  
  172.         .PSECT  $CODE$,LONG,EXE
  173.  
  174. DEHEX:: .WORD   ^M<>
  175. FILE:   MOVAB   M$FILE,R11              ; Output the get file name message
  176.         MOVZBL  #L$FILE,R12
  177.         MOVAB   INP.N,R10               ; Get the file name
  178.         MOVZBL  #INP.L,R1
  179.         JSB     READ
  180.         TSTL    R0                      ; Check for no input
  181.         BEQL    FILE                    ; Go back and get some
  182. ;Open the file
  183.         MOVAL   RDFAB,R1                ; Put address of FAB into R1.
  184.         $FAB_STORE FAB=R1,FNS=R0        ; Tell RMS file name length
  185.         $OPEN   #RDFAB                  ; Open the file
  186.         JSB     RMSERR                  ; Check for file error
  187.         MOVAL   RDRAB,R1                ; Put address of RAB into R1.
  188. ; Put address of user buffer and size and record buffer and size in RAB.
  189.         $RAB_STORE RAB=R1,UBF=RDBUF,RBF=RDBUF,USZ=#MAX.MSG,RSZ=#MAX.MSG
  190.         $CONNECT #RDRAB                 ; Connect to record.
  191.         JSB     RMSERR                  ; Check for file error
  192.  
  193.  
  194.         .SBTTL  Do the real work
  195. ;++
  196. ; Do the actual work
  197. ;--
  198. BEGIN:  MOVAL   M$CRLF,R10              ; Get a return/linefeed and output them
  199.         MOVZBL  #L$CRLF,R1
  200.         JSB     WRITE
  201.  
  202. 20$:    CLRL    WTCOUNT                 ; Initialize the pointer
  203.         CLRL    ADDRESS                 ; Initialize the address
  204.         CLRL    OPENFL                  ; Set the file to not open
  205.  
  206.         .SBTTL  Main loop
  207.  
  208. ; Main loop to get data
  209. DOLIN:
  210.         CLRL    CHKSUM                  ; Clear the checksum
  211.         JSB     RECEIVE                 ; Get the line
  212.         JSB     CVTBIN                  ; Convert it to a real number
  213.         MOVL    R10,LENGTH              ; Save the length
  214. NAB:    JSB     CVTBIN                  ;
  215.         BISL    R10,R3                  ; Save a byte of the address
  216.         ASHL    #8.,R3,R3               ; Make room for next byte
  217.         SOBGEQ  LNGADR,NAB              ; If there are more than 2 bytes
  218.         JSB     CVTBIN                  ;
  219.         BISL    R10,R3                  ; Fill in the low byte of address
  220.  
  221. ;ta2 The fix for 1.1.01 converted two more hex values here. As of March
  222. ;    1989, this doesn't appear to be required. The conversion has been
  223. ;    removed.
  224.  
  225.         JSB     CVTBIN                  ;ta2 Pick up the record type code
  226.  
  227.         CMPL    #PKDATA,R10             ; Check to see if this is regular data
  228.         BNEQ    NOTDAT                  ; If not then check the special cases
  229. ; Check for end of hex file
  230.         TSTL    R3                      ; Check to see if the address is all
  231.         BNEQ    DATST                   ;  zero, if not then branch
  232.         TSTL    LENGTH                  ; Check to see if the length is zero
  233.         BNEQ    DATST                   ;  also, if not then branch
  234.         JMP     FINISH                  ; Must be end of hex file so finish up
  235. ; Regular data to put into the file
  236. DATST:  TSTL    OPENFL                  ; Check to see if the file is open yet
  237.         BNEQ    DAT1                    ; If it is then skip the open
  238.         JSB     OPEN                    ; Open the file
  239. DAT1:   CMPL    R3,ADDRESS              ; Check for null compression
  240.         BEQL    10$                     ; If none compressed then continue past
  241.         CLRL    R10                     ; Make a null
  242.         JSB     PUT                     ;  and put it into the file
  243.         INCL    ADDRESS                 ; Point to next address
  244.         BRW     DAT1                    ; Go see if there are any more nulls
  245. ; Go to work on the HEX we got on the line
  246. 10$:    MOVL    LENGTH,R2               ; Get the length
  247.         TSTL    R2                      ; See if there is any data
  248.         BEQL    30$                     ; If not then branch
  249. 25$:    JSB     CVTBIN                  ; Convert it
  250.         JSB     PUT                     ; Put the character in the file
  251.         INCL    ADDRESS                 ; Increment the address
  252.         SOBGTR  R2,25$                  ; Repeat until all done
  253. 30$:    BRW     LINDON                  ; Go finish this line
  254.  
  255.  
  256.  
  257. NOTDAT: MOVAL   WTFAB,R5                ; Get the FAB address
  258.         CMPL    #PKRFM,R10              ; Check to see if this is record fmt
  259.         BNEQ    NOTRFM                  ; If not then don't do this stuff
  260. ; Store the Record format (FIX, VAR, ...)
  261.         JSB     CVTBIN                  ;
  262.         $FAB_STORE FAB=R5,RFM=R10       ; Store the record format
  263.         BRW     LINDON                  ; Go finish this line
  264.  
  265. NOTRFM: CMPL    #PKRAT,R10              ; Check to see if this is record type
  266.         BNEQ    NOTRAT                  ; If not then branch
  267. ; Store the record type (CR, ...)
  268.         JSB     CVTBIN                  ;
  269.         $FAB_STORE FAB=R5,RAT=R10       ; Store the record type
  270.         BRW     LINDON                  ; Go finish this line
  271.  
  272. NOTRAT: CMPL    #PKMRS,R10              ; Check to see if this is max record
  273.         BNEQ    NOTMRS                  ;  size, branch if not
  274. ; Get the maximum record size (512. for tasks)
  275.         JSB     CVTBIN                  ; Convert high order byte
  276.         MOVL    R10,R3                  ; Save it
  277.         ASHL    #8.,R3,R3               ; Shift it to the high order byte
  278.         JSB     CVTBIN                  ; Convert low order byte
  279.         BISL    R10,R3                  ; Put low order word into R3 also
  280.         $FAB_STORE FAB=R5,MRS=R3        ; Store the maximum record size
  281.         BRW     LINDON                  ; Go finish this line
  282.  
  283. NOTMRS: CMPL    #PKALQ,R10              ; Check to see if this is allocation
  284.         BNEQ    NOTALQ                  ; If not then branch
  285. ; Get the file length (in blocks)
  286.         JSB     CVTBIN                  ; Convert high order byte
  287.         MOVL    R10,R3                  ; Save it
  288.         ASHL    #8.,R3,R3               ; Shift it to the high order byte
  289.         JSB     CVTBIN                  ; Convert low order byte
  290.         BISL    R10,R3                  ; Put low order word into R3 also
  291.         MOVZWL  R3,ALQLOC               ; Save it
  292.         $FAB_STORE FAB=R5,ALQ=ALQLOC    ; Store the allocation
  293.         BRW     LINDON                  ; Go finish this line
  294.  
  295. NOTALQ: CMPL    #PKFILNM,R10            ; Check to see if this is file name
  296.         BNEQ    NOTFILNM                ; If not then branch
  297. ; Get the file name
  298.         MOVL    LENGTH,R2               ; Get the length
  299.         $FAB_STORE FAB=R5,FNS=R2        ; Store the file name length
  300.         MOVAB   OUT.N,R3                ; Get the output file name address
  301. 25$:    JSB     CVTBIN                  ; Convert next character of the name
  302.         MOVB    R10,(R3)+               ; Save the character
  303.         SOBGTR  R2,25$                  ; Repeat until all done
  304.         MOVAB   M$CRLF,R10              ;
  305.         MOVZBL  #L$CRLF,R1              ;
  306.         JSB     WRITE                   ; Output a return/line feed
  307.         MOVAB   OUT.N,R10               ;
  308.         MOVL    LENGTH,R1               ;
  309.         JSB     WRITE                   ; Output the file name
  310.         MOVAB   M$CRLF,R10              ;
  311.         MOVZBL  #L$CRLF,R1              ;
  312.         JSB     WRITE                   ; Output a return/line feed
  313.         BRW     LINDON                  ; Go finish this line
  314.  
  315.  
  316.  
  317. NOTFILNM:
  318.         CMPL    #PKEOF,R10              ; Check to see if this is end of task
  319.         BNEQ    NOTPKEOF                ; If not then branch
  320. ; End of ouput file record found
  321.         JSB     CLTSK                   ; Close the task file
  322.         CLRL    WTCOUNT                 ; Initialize the pointer
  323.         CLRL    ADDRESS                 ; Initialize the address
  324.         JMP     LINDON                  ; Go finish this line
  325.  
  326. ; Unknown code
  327. NOTPKEOF:                               ; Since we don't know what the code
  328.         MOVAB   M$UN,R10                ;   just send the unknown code text to
  329.         MOVZBL  #L$UN,R1                ;   the terminal
  330.         JSB     WRITE                   ;
  331.         JMP     DOLIN                   ; Go do next input line
  332.  
  333.  
  334.         .SBTTL  Finished with this line
  335.  
  336. ; Line processed without a problem
  337. LINDON:
  338. ;       MOVAB   M$AK,R10                ; Get the data address of the
  339.                                         ;  single character
  340. ;       MOVZBL  #1,R1                   ; Only write single char to terminal
  341. ;       JSB     WRITE                   ; Write to the terminal
  342.         JMP     DOLIN                   ; Good so do next line
  343.  
  344.  
  345.         .SBTTL  Finish up
  346. ;++
  347. ;Finish up
  348. ;--
  349. FINISH:
  350. ; Close the file(s)
  351.         JSB     CLTSK                   ; Close the task file if it isn't yet
  352.         MOVAL   RDFAB,R1                ; Get FAB for input file
  353.         $CLOSE  R1                      ; Close the input file
  354.         JSB     RMSERR                  ; Check for file error
  355. END:    MOVL    #SS$_NORMAL,R0          ; Set up successful completion
  356.         RET
  357.  
  358.         .SBTTL  Close file
  359.  
  360. ;++
  361. ; Close the output file if there is one open
  362. ;
  363. ; If there is an error the program stops with an RMS error
  364. ;
  365. ; Registers destroyed:  R0, R1
  366. ; The OPENFL state is changed to file not open (OPENFL=0).
  367. ;--
  368.  
  369. CLTSK:  TSTL    OPENFL                  ; See if the task file is open
  370.         BEQL    10$                     ; If not then just return
  371.  
  372. ; Write last buffer if needed
  373.         TSTL    WTCOUNT                 ; See if there is any data not written
  374.         BEQL    8$                      ; If not then branch
  375.         MOVAL   WTRAB,R1                ; Get the RAB address
  376.         $RAB_STORE RAB=R1,RSZ=WTCOUNT   ; Put its size into the RAB.
  377.         $WRITE  R1                      ; Put the buffer of data.
  378.         JSB     RMSERR                  ; Check for file error
  379.  
  380. ; Close the file
  381. 8$:     MOVAL   WTFAB,R1                ; Get FAB for output file
  382.         $CLOSE  R1                      ; Close output file
  383.         JSB     RMSERR                  ; Check for file error
  384.         CLRL    OPENFL                  ; Set the state to file not open
  385. 10$:    RSB                             ; Return to sender
  386.  
  387.  
  388.         .SBTTL  Output and input to/from terminal
  389. ;++
  390. ; Write data to terminal.
  391. ;       R10     Address of data to output
  392. ;       R1      Length of data
  393. ;--
  394. WRITE:
  395.         MOVW    R1,MSGDSC               ; Store the length in the descript blk
  396.         MOVL    R10,ADDR                ; Store the address of the ASCII
  397.         PUSHAQ  MSGDSC                  ; Push the descriptor block address
  398.         CALLS   #1,G^LIB$PUT_OUTPUT     ; Do the output
  399.         RSB                             ; Return to sender
  400.  
  401. ;++
  402. ; Read from the terminal
  403. ;       R10     Address of buffer
  404. ;       R1      Number of characters to read
  405. ;       R11     Input prompt address
  406. ;       R12     Length of prompt
  407. ;
  408. ;Returned:
  409. ;       R0      Number of characters read
  410. ;--
  411. READ:
  412.         MOVL    R1,INP_STR_D            ; Store the buffer length in desc block
  413.         MOVL    R10,INP_BUF             ; Store the buffer address in desc blk
  414.         MOVL    R11,ADDR                ; Store prompt address in desc block
  415.         MOVW    R12,MSGDSC              ; Store length in desctriptor block
  416.         PUSHAB  INP_STR_LEN             ; Address for string length
  417.         PUSHAQ  MSGDSC                  ; Push address of prompt descriptor blk
  418.         PUSHAB  INP_STR_D               ; String buffer descriptor
  419.         CALLS   #3,G^LIB$GET_INPUT      ; Get input string value
  420.         MOVL    INP_STR_LEN,R0          ; Get actual input length back
  421.         RSB                             ; Return to sender
  422.  
  423.  
  424.         .SBTTL  RMS error routine
  425. ;++
  426. ;Check for RMS error
  427. ; Call with:            R0      Status of last RMS call (automatically stored
  428. ;                                 in R0 by RMS after an operation)
  429. ;
  430. ; Returned:             R0      Status
  431. ; Registers destroyed:  R0
  432. ; Program stops after error message is displayed if there is any type of error.
  433. ;--
  434. RMSERR:
  435.         BLBC    R0,60$                  ; If error, go check it out
  436.         MOVL    #KNORMAL,R0             ; Set up a successful return code.
  437.         RSB                             ; Return to caller
  438.  
  439. ; Here if there is an RMS error we don't know how to handle
  440. 60$:    PUSHL   R0                      ; Save the error code
  441.         MOVAB   M$RMS,R10               ; Get the address and length of the
  442.         MOVL    #L$RMS,R1               ;   message to output
  443.         JSB     WRITE                   ; Output it
  444.         POPL    R0                      ; Get the error code back
  445.         RET                             ; Exit program
  446.  
  447.  
  448.         .SBTTL  Open the output file
  449. ;++
  450. ; Create and open the output file and set the file open flag
  451. ;
  452. ; Registers destroyed:  R0, R1
  453. ; Program stops after error message is displayed if there is any type of error.
  454. ;--
  455.  
  456. OPEN:   MOVL    #TRUE,OPENFL            ; State that the file is open
  457.         MOVAL   WTFAB,R1                ; Put address of FAB into R1.
  458.         $FAB_STORE FAB=R1,FAC=<BIO,GET> ; Set the block I/O in FAB.
  459.         ;$FAB_STORE FAB=R1,FOP=CTG      ; Tell RMS to make the task contiguous
  460.         $CREATE #WTFAB                  ; Create the file
  461.         JSB     RMSERR                  ; Check for file error
  462.         MOVAL   WTRAB,R1                ; Put address of RAB into R1.
  463. ; Put address of user buffer and record buffer and sizes into RAB
  464.         $RAB_STORE RAB=R1,UBF=WTBUF,RBF=WTBUF,USZ=#512.,RSZ=#512.
  465.         $CONNECT #WTRAB                 ; Connect to record.
  466.         JSB     RMSERR                  ; Check for file error
  467.         RSB                             ; Return to sender
  468.  
  469.         .SBTTL  Put a character to the file
  470. ;++
  471. ; Put a character to the output file.
  472. ; The buffer is only written when 512. characters have been sent to the routine
  473. ; If the file does not end on a boundary then the buffer will have to be
  474. ; written by some other routine.
  475. ;
  476. ; Call with:            R10     Contains the character to be put into file
  477. ; Registers destroyed:  R1, R10
  478. ;
  479. ; Program stops after error message is displayed if there is any type of error.
  480. ;--
  481.  
  482. PUT:    PUSHL   R10                     ; Save the character
  483.         MOVL    WTCOUNT,R10             ; Get the offset into the buffer
  484.         MOVB    (SP),WTBUF(R10)         ; Put the character
  485.         TSTL    (SP)+                   ; Restore the stack
  486.         INCL    WTCOUNT                 ; Increment the offset into the buffer
  487.         CMPL    WTCOUNT,#512.           ; Check to see if we are past the end
  488.         BNEQ    10$                     ; If not then branch
  489.         MOVAL   WTRAB,R1                ; Get the RAB address
  490.         $RAB_STORE RAB=R1,RSZ=WTCOUNT   ; Put its size into the RAB.
  491.         $WRITE  R1                      ; Put the buffer of data.
  492.         JSB     RMSERR                  ; Check for file error
  493.         CLRL    WTCOUNT                 ; Clear the pointer
  494. 10$:    RSB                             ; Return to sender
  495.  
  496.         .SBTTL   Convert to binary
  497. ;++
  498. ; Convert 2 hexidecimal digits to binary
  499. ; Input is from the input buffer pointed to by R4 (it is incremented twice)
  500. ;
  501. ; Call with:            R4      The pointer into the input buffer
  502. ; Returned:             R10     The binary walue
  503. ; Registers destroyed:  R10,R1
  504. ;--
  505.  
  506. CVTBIN:
  507.         CLRL    R10                     ; Clear R10 for the BISB
  508.         BISB    (R4)+,R10               ; Get the next digit
  509.         JSB     BIN                     ;   in place and convert to binary
  510.         ASHL    #4,R10,R10              ; Multiply the result by 16
  511.         MOVL    R10,R1                  ;  and save it
  512.         CLRL    R10                     ; Clear R10
  513.         BISB    (R4)+,R10               ; Get the next digit
  514.         JSB     BIN                     ; Convert to binary
  515.         BISL    R1,R10                  ; Set the correct bits for high order
  516.         ADDL2   R10,CHKSUM              ; Add the value to the checksum
  517.         RSB                             ; Return to sender
  518.  
  519. BIN:    CMPL    R10,#^A/9/              ; Check to see if above '9
  520.         BLEQ    1$                      ; If not then branch
  521.         SUBL2   #HEXOFFSET,R10          ; Subtract offset to alphabet
  522. 1$:     SUBL2   #48.,R10                ; Make binary
  523.         RSB                             ; Return to sender
  524.  
  525.  
  526.         .SBTTL  Receive a line of data
  527.  
  528. ;++
  529. ; This will get a line of data from the input device
  530. ;
  531. ; Returned:             R4      Address of start of data buffer
  532. ; Registers destroyed:  R0, R1, R3, R4
  533. ;
  534. ; A checksum error will cause a NAK to be sent and input to be read again
  535. ; A real error will cause an error message to be output and the program to stop
  536. ;--
  537.  
  538. RECEIVE:
  539. ; Here to read from a file
  540.         MOVAL   RDRAB,R1                ; Get the RAB address
  541.         $GET    R1                      ; Get the record
  542.         JSB     RMSERR                  ; Check for file error
  543.         MOVZWL  #MAX.MSG,R3             ; Assume we got a full buffer
  544. ; Here to check the data we got
  545. RECCHK: MOVAL   RDBUF,R4                ; Get the address of the information
  546.         CLRL    R1                      ; Clear the data start address
  547. 80$:    BICB    #MSB,(R4)               ; Clear parity bit
  548.         SUBB3   #RCV.SOH,(R4)+,R0       ; Check for start of header
  549.         BLSS    81$                     ; If not, just keep going
  550.         CMPB    R0,#2                   ; There are 3 possible headers
  551.         BGTR    81$                     ; Not a header
  552.         MOVZBL  R0,LNGADR               ; Amount of extra bytes in the address
  553.         MOVL    R4,R1                   ; Start of header so save it
  554. 81$:    SOBGTR  R3,80$                  ; Repeat until done
  555.         TSTL    R1                      ; Check to see if we got a SOH
  556.         BNEQ    85$                     ; If good then skip the jump
  557.         JMP     RECEIVE                 ; If not then re-read
  558. 85$:    MOVL    R1,R4                   ; Move to R4 for use
  559.         PUSHL   R4                      ; Save SOH pointer on stack
  560.  
  561.         JSB     CVTBIN                  ; Convert all to binary to see if
  562.                                         ;   checksum is correct
  563.         MOVL    R10,R3                  ; Get the length of data
  564.         ADDL2   #4,R3                   ; Add the length of address and field
  565.                                         ;   type and checksum
  566.         ADDL2   LNGADR,R3               ; If long address, skip more bytes
  567.         BLSS    94$                     ; If we have a negative number then
  568.                                         ;   must have been a bad length
  569.         CMPL    R3,#MAX.MSG/2-1         ; If we got some length that is out of
  570.         BGEQ    94$                     ;   range then NAK right away
  571. 92$:    JSB     CVTBIN                  ; Convert all to binary to see if
  572.         SOBGTR  R3,92$                  ;   the checksum is OK
  573. 93$:    BICL    #LEFTBYTE,CHKSUM        ; We only want an 8 bit checksum
  574.         TSTL    CHKSUM                  ; Test for a zero checksum
  575.         BEQL    95$                     ; If OK then exit normally
  576. 94$:    CLRL    CHKSUM                  ; Clear the checksum for the line
  577.         MOVAL   M$NAK,R10               ; Get the address of the message
  578.         MOVZBL  #L$NAK,R1               ; Only write the first character to
  579.         JSB     WRITE                   ;   the terminal
  580.         TSTL    (SP)+                   ; Pull the pointer off the stack
  581.         JMP     RECEIVE                 ; Try to get the line again
  582.  
  583. ; Return to sender
  584. 95$:    POPL    R4                      ; Get the pointer back
  585.         RSB                             ; Return to sender
  586.  
  587.  
  588.         .SBTTL  End of the Dehexify
  589.  
  590.         .END    DEHEX
  591.