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