home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / decpro300 / prohex.mac < prev    next >
Text File  |  2020-01-01  |  17KB  |  565 lines

  1.     .TITLE    HEXIFY
  2.     .SBTTL    Stuart Hecht
  3.  
  4.     .LIBRARY /LB:[1,5]RMSMAC/
  5.     .ENABLE    LC
  6.     .NLIST    BEX
  7.  
  8.     .IDENT    /1.0.00/
  9.  
  10. ;++
  11. ;This will take a task file and turn it into hexidecimal strings
  12. ;--
  13.  
  14.     .MCALL    QIOW$S,QIOW$,ALUN$S,EXIT$S
  15.     .MCALL    FAB$B            ; RMS calls
  16.     .MCALL    RAB$B
  17.     .MCALL    $CLOSE
  18.     .MCALL    $CONNECT
  19.     .MCALL    $CREATE
  20.     .MCALL    $DISCONNECT
  21.     .MCALL    $READ
  22.     .MCALL    $OPEN
  23.     .MCALL    $FETCH
  24.     .MCALL    $PUT
  25.     .MCALL    $STORE
  26.     .MCALL    $SET
  27.     .MCALL    ORG$
  28.     .MCALL    POOL$B
  29.  
  30.     .SBTTL    Definitions of symbols
  31.  
  32. TERLUN    =7                ; Terminal LUN
  33. TTEFN    =1                ; Terminal Event Flag
  34. DWRLUN    =1                ; Disk read LUN
  35. DWWLUN    =5                ; Disk write LUN
  36. TRUE    =1                ; True
  37. FALSE    =0                ; False
  38. KNORMAL    =0                ; No error
  39. RMS11    =1                ; RMS error
  40. EOF    =-1                ; End of file error code
  41. LEFTBYTE=377*400            ; All one in left byte
  42. HEXOFFSET=7                ; Offset to get to 'A from '9+1
  43.  
  44. ; Packet types currently created
  45. PKDATA    =0                ; Data packet code
  46. PKRFM    =255.                ; Record format
  47. PKRAT    =254.                ; Record attributes
  48. PKMRS    =253.                ; Maximum record size
  49. PKALQ    =252.                ; File length(blocks)
  50. PKFILNM    =251.                ; File name
  51. PKEOF    =250.                ; End of file
  52. ;
  53.  
  54.     .SBTTL    RMS Initialization
  55.  
  56.     POOL$B                ; Allocate static pool for RMS
  57.     P$RAB    5            ; For internal RABs
  58.     P$BDB    5            ; For buffer descriptor blocks
  59.     P$FAB    4            ; For internal FABs
  60.     P$BUF    2048.            ; Buffer space
  61.     POOL$E                ; End of pool declarations
  62.  
  63.     ORG$    SEQ            ; $Open a sequential file
  64.  
  65.  
  66.     .SBTTL    Data
  67.  
  68.     .PSECT    $PLIT$,RO,D
  69.  
  70. M$FILN:    .BYTE    CR,LF,LF
  71.     .ASCII    'Input file name: '
  72. L$FILN    =.-M$FILN
  73.  
  74. M$OFLN:    .BYTE    CR,LF,LF
  75.     .ASCII    'Output file name (or return for the default): '
  76. L$OFLN    =.-M$OFLNM
  77.  
  78. M$NEXF:    .BYTE    CR,LF,LF
  79.     .ASCII    'Press return to finish or type the name of another file'
  80.     .BYTE    CR,LF
  81.     .ASCII    'to append to the HEX file: '
  82. L$NEXF    =.-M$NEXF
  83.  
  84. M$RMS:    .BYTE    CR,LF,LF
  85.     .ASCII    'RMS ERROR'
  86. L$RMS    =.-M$RMS
  87.     .EVEN
  88.  
  89.     .SBTTL    RMS 11 Data
  90.  
  91. DEFALT:    .ASCIZ    'SY:'            ; System default.
  92. DEFALN    =.-DEFALT            ; Size of the default device.
  93.     .EVEN
  94.  
  95.  
  96.     .SBTTL    Storage locations
  97.  
  98.     .PSECT    $OWN$
  99.  
  100. IOSTAT:    .BLKW    1            ; QIO status
  101. STAT1:    .BLKW    1            ; Second word of status
  102.  
  103. BUCOUNT: .BLKW    1            ; Number of character available in the
  104.                     ;   buffer (returned from RMS)
  105. RDCOUNT: .BLKW    1            ; Number of characters read from buffer
  106. WTCOUNT: .BLKW    1            ; Number of characters written
  107. CHCOUNT: .BLKW    1            ; Number of characters written to buff.
  108. NULCOUNT: .BLKW    1            ; Number of nulls not yet written
  109.  
  110. CHKSUM:    .BLKW    1            ; Checksum for the line
  111. ADDRESS: .BLKW    1            ; Current address
  112.  
  113. INP.N:    .BLKB    28.            ; Space for input file name
  114. INP.L    =.-INP.N            ; Length of input file name
  115. OUT.N:    .BLKB    28.            ; Space for output file name
  116. OUT.L    =.-OUT.N            ; Length of input file name
  117.  
  118. RDBUF:    .BLKB    512.            ; Disk read buffer
  119. WTBUF:    .BLKB    512.            ; Disk write buffer
  120.     .EVEN
  121.  
  122.  
  123.  
  124.     .SBTTL    RMS 11 Data structures
  125.  
  126. RDFAB::    FAB$B
  127.     F$DNA    DEFALT            ; Address of default device.
  128.     F$DNS    DEFALN            ; Default length field.
  129.     F$FNA    INP.N            ; Address of file name
  130.     F$FNS    INP.L            ; Length of file name
  131.     F$LCH    DWRLUN            ; Logical channel to use
  132.     FAB$E
  133.     .EVEN
  134.  
  135. RDRAB::    RAB$B                ; Beginning of RAB block.
  136.     R$FAB    RDFAB            ; Chain to FAB block.
  137.     R$RAC    RB$SEQ            ; Set the sequential access flag.
  138.     RAB$E                ; End RAB block.
  139.     .EVEN
  140.  
  141.  
  142.  
  143. WTFAB::    FAB$B
  144.     F$DNA    DEFALT            ; Address of default device.
  145.     F$DNS    DEFALN            ; Default length field.
  146.     F$FNA    OUT.N            ; Address of file name
  147.     F$FNS    OUT.L            ; Length of file name
  148.     F$LCH    DWWLUN            ; Logical channel to use
  149.     FAB$E
  150.     .EVEN
  151.  
  152. WTRAB::    RAB$B                ; Beginning of RAB block.
  153.     R$FAB    WTFAB            ; Chain to FAB block.
  154.     R$RAC    RB$SEQ            ; Set the sequential access flag.
  155.     RAB$E                ; End RAB block.
  156.     .EVEN
  157.  
  158.  
  159.     .SBTTL    Main line code
  160.  
  161.     .PSECT    $CODE$,RO,I
  162.  
  163. HEXIFY::
  164.     ALUN$S    #TERLUN,#"TI,#0        ; Assign terminal LUN
  165. NOINP:    MOV    #M$FILN,R0        ; Get the address and length of the
  166.     MOV    #L$FILN,R1        ;   message to output
  167.     JSR    PC,WRITE        ; Output it
  168.     MOV    #INP.N,R0        ; Get address of input and length
  169.     MOV    #INP.L,R1        ;
  170.     JSR    PC,READ            ; Read the input file name
  171.     TST    R0            ; See if we got anything
  172.     BEQ    NOINP            ; If no input then try again
  173.     MOV    R0,R5            ; Save length
  174.  
  175.     MOV    #M$OFLN,R0        ; Get the address and length of the
  176.     MOV    #L$OFLN,R1        ;  message to output
  177.     JSR    PC,WRITE        ; Output it
  178.     MOV    #OUT.N,R0        ; Get address of output file name
  179.     MOV    #OUT.L,R1        ;  and length
  180.     JSR    PC,READ            ; Read the output file name
  181.     MOV    R0,R3            ; Save length
  182.     TST    R3            ; See if we got any input
  183.     BNE    GOTFIL            ; Yes so branch
  184.  
  185. ; Here so use the default output file name
  186.     MOV    R5,R0            ; Get the input file length back
  187.     MOV    #INP.N,R2        ; Get input address
  188.     MOV    #OUT.N,R3        ; Point at buffer
  189. 2$:    CMPB    (R2),#'.        ; Check for an extension
  190.     BEQ    10$            ; If an extension then ignore rest
  191.                     ;   of line
  192.     MOVB    (R2)+,(R3)+        ; Move into the output file name
  193.     SOB    R0,2$            ; Branch until done
  194.  
  195. 10$:    MOVB    #'.,(R3)+        ; Write the extension for output file
  196.     MOVB    #'H,(R3)+        ;
  197.     MOVB    #'E,(R3)+        ;
  198.     MOVB    #'X,(R3)+        ;
  199.     SUB    #OUT.N,R3        ; Make final count
  200.  
  201. ;++
  202. ;Open files
  203. ;--
  204. GOTFIL:
  205. ;Create output file
  206.     MOV    #WTFAB,R1        ; Put address of FAB into R1.
  207.     $SET    #FB$CR,RAT,R1        ; Set the record handling mask.
  208.     $STORE    R3,FNS,R1        ; Tell RMS file name length
  209.     $CREATE    #WTFAB            ; Create the file
  210.     JSR    PC,RMSERR        ; Check for file error
  211.     MOV    #WTRAB,R1        ; Put address of RAB into R1.
  212.     $STORE    #WTBUF,UBF,R1        ; Put address of user buffer in RAB.
  213.     $STORE    #WTBUF,RBF,R1        ; Put record buffer address in RAB
  214.     $STORE    #512.,USZ,R1        ; Put size of user buffer into RAB.
  215.     $STORE    #512.,RSZ,R1        ; Put record buffer size in RAB
  216.     $CONNECT #WTRAB            ; Connect to record.
  217.     JSR    PC,RMSERR        ; Check for file error
  218. ;Open input file
  219. AGAINSAM:
  220.     MOV    #RDFAB,R1        ; Put address of FAB into R1.
  221.     $SET    #FB$REA,FAC,R1        ; Set the block read in FAB.
  222.     $STORE    R5,FNS,R1        ; Tell RMS file name length
  223.     $OPEN    #RDFAB            ; Open the file
  224.     JSR    PC,RMSERR        ; Check for file error
  225.     MOV    #RDRAB,R1        ; Put address of RAB into R1.
  226.     $STORE    #RDBUF,UBF,R1        ; Put address of user buffer in RAB.
  227.     $STORE    #RDBUF,RBF,R1        ; Put record buffer address in RAB
  228.     $STORE    #512.,USZ,R1        ; Put size of user buffer into RAB.
  229.     $STORE    #512.,RSZ,R1        ; Put record buffer size in RAB
  230.     $CONNECT #RDRAB            ; Connect to record.
  231.     JSR    PC,RMSERR        ; Check for file error
  232.  
  233.  
  234. ;++
  235. ;Do the actual work
  236. ;--
  237.     MOV    #512.,RDCOUNT        ; Initialize buffer pointers
  238.     MOV    #512.,BUCOUNT        ;
  239.     CLR    WTCOUNT            ;
  240.     CLR    ADDRESS            ; Initialize the address
  241.     CLR    NULCOUNT        ; Initialize the number of nulls
  242.     MOV    #RDFAB,R5        ; Get the FAB address
  243. ;Get the Record format (FIX, VAR, ...)
  244.     MOV    #PKRFM,R0        ; Set packet type to record format
  245.     JSR    PC,HEADER        ; Output the header
  246.     $FETCH    R0,RFM,R5        ; Get the record format
  247.     JSR    PC,CVTH            ; Put the record format code into buff
  248.     INC    CHCOUNT            ; Increment counter
  249.     JSR    PC,PUTLIN        ; Write the line out
  250. ;Get the record type (CR, ...)
  251.     MOV    #PKRAT,R0        ; Set packet type to record type
  252.     JSR    PC,HEADER        ; Output the header
  253.     $FETCH    R0,RAT,R5        ; Get the record type
  254.     JSR    PC,CVTH            ; Put the record type into buffer
  255.     INC    CHCOUNT            ; Increment counter
  256.     JSR    PC,PUTLIN        ; Write the line out
  257. ;Get the maximum record size (512. for tasks)
  258.     MOV    #PKMRS,R0        ; Set packet type to max record size
  259.     JSR    PC,HEADER        ; Output the header
  260.     $FETCH    R0,MRS,R5        ; Get the maximum record size
  261.     MOV    R0,-(SP)        ; Save for low order
  262.     SWAB    R0            ; Get high order byte
  263.     JSR    PC,CVTH            ; Put the record size into buffer
  264.     INC    CHCOUNT            ; Increment counter
  265.     MOV    (SP)+,R0        ; Get size back
  266.     JSR    PC,CVTH            ; Put the record size into buffer
  267.     INC    CHCOUNT            ; Increment counter
  268.     JSR    PC,PUTLIN        ; Write the line out
  269. ;Get the file length (in blocks)
  270.     MOV    #PKALQ,R0        ; Set packet type to file length
  271.     JSR    PC,HEADER        ; Output the header
  272.     $FETCH    R0,ALQ,R5        ; Get the allocation
  273.     MOV    R0,-(SP)        ; Save for low order
  274.     SWAB    R0            ; Get high order byte
  275.     JSR    PC,CVTH            ; Put the allocation into buffer
  276.     INC    CHCOUNT            ; Increment counter
  277.     MOV    (SP)+,R0        ; Get allocation back
  278.     JSR    PC,CVTH            ; Put the low order into the buffer
  279.     INC    CHCOUNT            ; Increment counter
  280.     JSR    PC,PUTLIN        ; Write the line out
  281. ;Get the file name
  282.     MOV    #PKFILNM,R0        ; Set packet type to file name
  283.     JSR    PC,HEADER        ; Output the header
  284.     $FETCH    R4,FNS,R5        ; Get the file name length
  285.     MOV    #INP.N,R3        ; Get the input file name address
  286. 25$:    MOVB    (R3)+,R0        ; Get the next character
  287.     JSR    PC,CVTH            ; Buffer the next character of the name
  288.     INC    CHCOUNT            ; Increment counter
  289.     SOB    R4,25$            ; Repeat until all done
  290.     JSR    PC,PUTLIN        ; Write the line out
  291.  
  292.  
  293. ;++
  294. ; Start moving real data
  295. ;--
  296. NEXLIN:
  297.     JSR    PC,GET            ; Get a character from the buffer
  298.     CMP    R0,#EOF            ; Check for end of file
  299.     BEQ    FINISH            ; If at end the finish up
  300.     TST    R0            ; Check for null character
  301.     BNE    DOLIN            ; Not null so just do regular stuff
  302.     INC    ADDRESS            ; Point to next location
  303.     BR    NEXLIN            ;  save space and try again
  304. DOLIN:    MOV    R0,-(SP)        ; Save the character we have
  305.     MOV    #PKDATA,R0        ; Set packet type to plain old data
  306.     JSR    PC,HEADER        ; Put the standard header into buffer
  307.  
  308.     MOV    (SP)+,R0        ; Get the original character back
  309. LINAGA:    JSR    PC,CVTHEX        ; Convert the character to hex codes
  310.     INC    ADDRESS            ; Point to next location
  311.     INC    CHCOUNT            ; Increment the character count
  312.     CMP    CHCOUNT,#36        ; Check to see if we should finish
  313.     BNE    LINMOR            ;  this line
  314.     JSR    PC,PUTLIN        ; Put the whole line to disk
  315.     BR    NEXLIN            ; Go do the next line
  316.  
  317. LINMOR:    JSR    PC,GET            ; Get the next character
  318.     CMP    R0,#EOF            ; Is it an end of file?
  319.     BNE    LINAGA            ; No, then just handle normally
  320. ;    JSR    PC,PUTLIN        ; Yes, write the current line
  321.     DEC    ADDRESS            ; Reset address to correct value
  322.     BR    FIN1            ; Finish up
  323.  
  324.  
  325.     .SBTTL    Finish up
  326.  
  327. ;++
  328. ;Finish up
  329. ;--
  330. FINISH:
  331.     MOV    #PKDATA,R0        ; Set packet type to plain old data
  332.     JSR    PC,HEADER        ; Insert the header so the extra
  333.                     ;  nulls are seen
  334. FIN1:    TST    NULCOUNT        ; See if no nulls left
  335.     BEQ    FIN            ; If none then branch
  336.     CLR    R0            ; Get a null
  337.     DEC    NULCOUNT        ; Decrement the counter
  338.     JSR    PC,CVTH            ; Convert to HEX (w/o null compression)
  339. FIN:    JSR    PC,PUTLIN        ; Put the current buffer to disk
  340. ; Write out the end of task file line
  341.     CLR    CHCOUNT            ; Clear character count
  342.     MOV    #PKEOF,R0        ; Get end of task file packet type
  343.     JSR    PC,HEADER        ; Make the header
  344.     JSR    PC,PUTLIN        ; Write the line
  345. ; Close the input (task) file
  346.     MOV    #RDFAB,R1        ; Get the FAB for input file
  347.     $CLOSE    R1            ; Close input file
  348.     JSR    PC,RMSERR        ; Check for file error
  349. ; See about another file to append
  350.     MOV    #M$NEXF,R0        ; See if another file should be
  351.     MOV    #L$NEXF,R1        ;   appended to the HEX file
  352.     JSR    PC,WRITE        ;
  353.     MOV    #INP.N,R0        ; Get address of input and length
  354.     MOV    #INP.L,R1        ;
  355.     JSR    PC,READ            ; Read the input file name
  356.     TST    R0            ; See if we got anything
  357.     BEQ    LEAVE            ; If no input then leave
  358.     MOV    R0,R5            ; Put the length in R5 for the open
  359.     JMP    AGAINSAM        ; Repeat process for this file
  360. ; Write out end of hex file line        
  361. LEAVE:    CLR    CHKSUM            ; Clear the checksum for this line
  362.     CLR    CHCOUNT            ; Clear character count
  363.     MOV    #':,R0            ; Get the start character
  364.     JSR    PC,BUFFER        ; Put it into the buffer
  365.     MOV    #8.,R5            ; Get the number of nulls needed
  366. FINREP:    MOV    #'0,R0            ; Set the character to 'null'
  367.     JSR    PC,BUFFER        ; Put it into the buffer
  368.     SOB    R5,FINREP        ; Repeat if not done
  369.     JSR    PC,PUTLIN        ; Write the buffer to disk
  370. ; Close the HEX file
  371.     MOV    #WTFAB,R1        ; Get FAB for output file
  372.     $CLOSE    R1            ; Close output file
  373.     JSR    PC,RMSERR        ; Check for file error
  374.  
  375. END:    EXIT$S
  376.  
  377.     .SBTTL    Put a data line
  378. ;++
  379. ;Finish a line up by inserting the length and the checksum and doing a PUT
  380. ;--
  381.  
  382. PUTLIN:
  383.     MOV    CHCOUNT,R0        ; Get the actual character count
  384.     SUB    NULCOUNT,R0        ; Don't include the nulls since we
  385.                     ;  won't write them
  386.     CLR    NULCOUNT        ; Clear the null count since the
  387.                     ;  address will serve to insert nulls
  388.     MOV    WTCOUNT,-(SP)        ; Save it on the stack
  389.     MOV    #1,WTCOUNT        ; Move a one into the char count to get
  390.     JSR    PC,CVTH            ;  to the length and then put length in
  391.     MOV    (SP)+,WTCOUNT        ; Restore the correct count
  392.  
  393.     MOV    CHKSUM,R0        ; Get the checksum
  394.     NEG    R0            ; Negate it
  395.     JSR    PC,CVTH            ; Put the negative checksum into buffer
  396.  
  397.     JSR    PC,PUT            ; Put the line to disk
  398.     RTS    PC            ; Return to sender
  399.  
  400.  
  401.     .SBTTL    Create the header for the data line
  402. ;++
  403. ;This routine will put the starting stuff into the buffer
  404. ;R0 contains the record type
  405. ;--
  406.  
  407. HEADER:    CLR    CHKSUM            ; Clear the checksum for this line
  408.     CLR    CHCOUNT            ; Clear character count
  409.     MOV    R0,-(SP)        ; Save the record type
  410.     MOV    #':,R0            ; Move a colon into first char position
  411.     JSR    PC,BUFFER        ;   of the buffer
  412.     CLR    R0            ; Move a fake length into the buffer
  413.     JSR    PC,CVTH            ;
  414.     MOVB    ADDRESS+1,R0        ; Get the high order word of the
  415.     JSR    PC,CVTH            ;  address and put into the buffer
  416.     MOVB    ADDRESS,R0        ; Get low order word of address and
  417.     JSR    PC,CVTH            ;  buffer it
  418.     MOV    (SP)+,R0        ; Get the line record type
  419.     JSR    PC,CVTH            ;  and buffer the code
  420.     RTS    PC            ; Return to sender
  421.  
  422.     .SBTTL    Output and input to/from terminal
  423. ;++
  424. ; Write data to terminal.
  425. ;    R0    Address of data to output
  426. ;    R1    Length of data
  427. ;--
  428. WRITE:
  429.     QIOW$S    #IO.WVB,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
  430.     RTS    PC
  431.  
  432. ;++
  433. ; Read from the terminal
  434. ;    R0    Address of buffer
  435. ;    R1    Number of characters to read
  436. ;
  437. ;Returned:
  438. ;    R0    Number of characters read
  439. ;--
  440. READ:    QIOW$S    #IO.RVB!TF.ESQ,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
  441.     MOV    STAT1,R0        ; Get the number of character read
  442.     RTS    PC
  443.  
  444.     .SBTTL    RMS error routine
  445. ;++
  446. ;Check for RMS error
  447. ;--
  448. RMSERR:    $FETCH    R0,STS,R1        ; Get the status and put it in R0
  449.     TST    R0            ; Test the status code for success.
  450.     BMI    60$            ; If negative then branch.
  451.     MOV    #KNORMAL,R0        ; Set up a successful return code.
  452.     RTS    PC            ; Return to caller
  453.  
  454. ; Here if there is an error
  455. 60$:    CMP    #ER$EOF,R0        ; Check for EOF
  456.     BNE    70$            ; If not then branch
  457.     MOV    #EOF,R0            ; Tell sender we have end of file
  458.     RTS    PC            ; Return
  459.  
  460. ; Here if there is an RMS error we don't know how to handle
  461. 70$:    MOV    #M$RMS,R0        ; Get the address and length of the
  462.     MOV    #L$RMS,R1        ;   message to output
  463.     JSR    PC,WRITE        ; Output it
  464.     EXIT$S                ; Exit since we can't finish
  465.  
  466.  
  467.     .SBTTL    Get a character from the file
  468. ;++
  469. ;Get a character from the input file.
  470. ;
  471. ;    Returned:
  472. ;        R0    Contains the character if not at end of file
  473. ;            Contains #EOF if at end of file
  474. ;--
  475.  
  476. GET:    MOV    RDCOUNT,R0        ; Get the offset into the buffer
  477.     CMP    R0,BUCOUNT        ; Check to see if we are past the end
  478.     BNE    10$            ; If not then branch
  479.     MOV    #RDRAB,R1        ; Get the RAB address
  480.     $READ    R1            ; Get the next buffer of data.
  481.     JSR    PC,RMSERR        ; Check for file error
  482.     CMP    R0,#EOF            ; Check for end of file error
  483.     BNE    5$            ; If not then branch
  484.     RTS    PC            ; Return with error code
  485. 5$:    $FETCH    R0,RSZ,R1        ; Get the record size and put it in R0
  486.     MOV    R0,BUCOUNT        ; Save the record size
  487.     CLR    R0            ; Clear the pointer
  488.     CLR    RDCOUNT            ; . . . 
  489. 10$:    MOVB    RDBUF(R0),R0        ; Get the next character
  490.     INC    RDCOUNT            ; Increment the offset into the buffer
  491.     BIC    #LEFTBYTE,R0        ; Clear high order byte of R0
  492.     RTS    PC            ; Return to sender
  493.  
  494.     .SBTTL    Buffer a character of the data line
  495. ;++
  496. ; Buffer the character in R0
  497. ;--
  498.  
  499. BUFFER:    MOV    R0,-(SP)        ; Save the character on the stack
  500.     MOV    WTCOUNT,R0        ; Get the offset into the buffer
  501.     MOVB    (SP)+,WTBUF(R0)        ; Move the character to the buffer
  502.     INC    WTCOUNT            ; Increment the pointer
  503. BUFRTS:    RTS    PC            ; Return to sender
  504.  
  505.  
  506.     .SBTTL    Put a record to the file
  507. ;++
  508. ;Write the record
  509. ;--
  510.  
  511. PUT:
  512.     MOV    WTCOUNT,R0        ; Get the count
  513.     MOV    #WTRAB,R1        ; Get the RAB address
  514.     $STORE    R0,RSZ,R1        ; Put its size into the RAB.
  515.     $PUT    R1            ; Output the record
  516.     JSR    PC,RMSERR        ; Check for file error
  517.     CLR    WTCOUNT            ; Clear the counter for next record
  518.     RTS    PC            ; Return
  519.  
  520.  
  521.     .SBTTL    Convert to Hexadecimal ASCII digits
  522. ;++
  523. ; Convert a word to 2 ASCII hexadecimal digits
  524. ;--
  525.  
  526. CVTHEX:
  527.     TST    R0            ; See if this is a null
  528.     BNE    CVTH            ; If not then just branch
  529.     INC    NULCOUNT        ; A null so just increment the count
  530.     RTS    PC            ;  for later and leave
  531.  
  532. ; Convert a word to 2 ASCII hexadecimal digits without null compression
  533. CVTH:    MOV    R0,-(SP)        ; Save the character on the stack
  534. 10$:    TST    NULCOUNT        ; Check to see if there are nulls
  535.     BEQ    20$            ; If not then just branch
  536.     CLR    R0            ; Put a null in R0
  537.     JSR    PC,CVT1            ; Put the null in the buffer
  538.     DEC    NULCOUNT        ; Decrement null counter
  539.     BR    10$            ; Repeat
  540. 20$:    MOV    (SP)+,R0        ; Get the original value back
  541.  
  542. CVT1:    ADD    R0,CHKSUM        ; Add the value to the checksum
  543.     MOV    R0,R1            ; Save the value
  544.     BIC    #17+LEFTBYTE,R0        ; Leave only left Hex digit
  545.     ASH    #-4,R0            ; Shift right to get first digit
  546.     JSR    PC,HEX            ;   in place and convert to Hex
  547.     JSR    PC,BUFFER        ; Buffer the Hex character
  548.     MOV    R1,R0            ; Get the original value back
  549.     BIC    #17*20+LEFTBYTE,R0    ; Get right Hex digit
  550.     JSR    PC,HEX            ; Convert to Hex
  551.     JSR    PC,BUFFER        ; Buffer the Hex character
  552.     RTS    PC            ; Return to sender
  553.  
  554. HEX:    MOV    R0,R2            ; Move the base to R2 
  555.     CMP    R2,#9.            ; Check to see if above '9
  556.     BLE    1$            ; If not then branch
  557.     ADD    #HEXOFFSET,R0        ; Add offset to alphabet
  558. 1$:    ADD    #48.,R0            ; Make ASCII
  559.     RTS    PC            ; Return to sender
  560.  
  561.  
  562.     .SBTTL    End of Hexify
  563.  
  564.     .END    HEXIFY
  565.