home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / archives / decpro300.zip / prodeh.mac < prev    next >
Text File  |  1988-08-16  |  24KB  |  812 lines

  1.     .TITLE    DEHEX
  2.     .SBTTL    Stuart Hecht
  3.  
  4.     .IDENT    /1.0.00/
  5.     .LIBRARY /LB:[1,5]RMSMAC/
  6.     .ENABLE    LC
  7.     .NLIST    BEX
  8.  
  9.  
  10. ;++
  11. ;This will take a set hexidecimal strings created by the hexify program and 
  12. ;  recreate the source file(s).
  13. ;--
  14.  
  15.     .MCALL    QIOW$C,QIO$C,QIOW$S,QIO$S,QIOW$,ALUN$S,EXIT$S
  16.     .MCALL    FAB$B                ; RMS calls
  17.     .MCALL    RAB$B
  18.     .MCALL    $CLOSE
  19.     .MCALL    $CONNECT
  20.     .MCALL    $CREATE
  21.     .MCALL    $DISCONNECT
  22.     .MCALL    $GET
  23.     .MCALL    $OPEN
  24.     .MCALL    $FETCH
  25.     .MCALL    $WRITE
  26.     .MCALL    $STORE
  27.     .MCALL    $SET
  28.     .MCALL    ORG$
  29.     .MCALL    POOL$B
  30.  
  31.     .SBTTL    Definitions of symbols
  32.  
  33. TERLUN    =7                ; Terminal LUN
  34. XKLUN    =8.                ; XK LUN
  35. TTEFN    =1                ; Terminal Event Flag
  36. XKREFN    =2                ; XK read Event Flag
  37. XKWEFN    =3                ; XK write Event Flag
  38. DWRLUN    =1                ; Disk read LUN
  39. DWWLUN    =5                ; Disk write LUN
  40. TRUE    =1                ; True
  41. FALSE    =0                ; False
  42. NULL    =0                ; Null byte
  43. KNORMAL    =0                ; No error
  44. RMS11    =1                ; RMS error
  45. LEFTBYTE=377*400            ; All ones in left byte
  46. RIGHTBYTE=377                ; All ones in right byte
  47. HEXOFFSET=7                ; Offset to get to 'A from '9+1
  48. MAX.MSG    =256.                ; Maximum number of chars from XK
  49. RCV.SOH    =':                ; Receive start of packet
  50. RCV.EOL    =13.                ; End of line character
  51. UPPER    ='a-'A                ; Bit to clear for upper case
  52. MSB    =128.                ; Most significant bit
  53. ; Packet types currently supported
  54. PKDATA    =00                ; Data packet code
  55. PKRFM    =255.                ; Record format
  56. PKRAT    =254.                ; Record attributes
  57. PKMRS    =253.                ; Maximum record size
  58. PKALQ    =252.                ; File length(blocks)
  59. PKFILNM    =251.                ; File name
  60. PKEOF    =250.                ; End of task file
  61. ;
  62.  
  63.  
  64.     .SBTTL    RMS Initialization
  65.  
  66.     POOL$B                ; Allocate static pool for RMS
  67.     P$RAB    5            ; For internal RABs
  68.     P$BDB    5            ; For buffer descriptor blocks
  69.     P$FAB    4            ; For internal FABs
  70.     P$BUF    2048.            ; Buffer space
  71.     POOL$E                ; End of pool declarations
  72.  
  73.     ORG$    SEQ            ; $Open a sequential file
  74.  
  75.  
  76.     .SBTTL    RMS 11 Data
  77.  
  78.     .PSECT    $PLIT$,RO,D
  79.  
  80. DEFALT:    .ASCIZ    'SY:'            ; System default.
  81. DEFALN    =.-DEFALT            ; Size of the default device.
  82.     .EVEN
  83.  
  84.     .SBTTL    Data
  85.  
  86. M$PORT:    .BYTE    CR,LF
  87.     .ASCII    'Please choose device to use:'
  88.     .BYTE    CR,LF
  89.     .ASCII    '1.  Communications port'
  90.     .BYTE    CR,LF
  91.     .ASCII    '2.  Printer port'
  92.     .BYTE    CR,LF
  93.     .ASCII    '3.  Disk file'
  94.     .BYTE    CR,LF
  95.     .ASCII    '    CHOICE (1-3): '
  96. L$PORT=    .-M$PORT
  97.  
  98. M$FILE:    .BYTE    CR,LF
  99.     .ASCII    'Please type the file name: '
  100. L$FILE=    .-M$FILE
  101.  
  102. M$SET:    .BYTE    CR,LF
  103.     .ASCII    'Is the port already setup correctly(baud rate)? '
  104. L$SET=    .-M$SET
  105.  
  106. M$BAUD:    .BYTE    CR,LF
  107.     .ASCII    'Choose a baud rate:'
  108.     .BYTE    CR,LF
  109.     .ASCII    '1.   300'
  110.     .BYTE    CR,LF
  111.     .ASCII    '2.  1200'
  112.     .BYTE    CR,LF
  113.     .ASCII    '3.  2400'
  114.     .BYTE    CR,LF
  115.     .ASCII    '4.  4800'
  116.     .BYTE    CR,LF
  117.     .ASCII    '5.  9600'
  118.     .BYTE    CR,LF
  119.     .ASCII    '    CHOICE (1-5): '
  120. L$BUAD    =.-M$BAUD
  121.  
  122. D$BAUD:    .BYTE    S.300,S.1200,S.2400,S.4800,S.9600    ; Baud rate code table
  123.                     ;   for set multiple characteristics
  124.  
  125.  
  126.  
  127. M$CRLF:    .BYTE    CR,LF            ; Data for carriage return/line feed
  128. L$CRLF    =.-M$CRLF
  129.  
  130. M$AK:    .BYTE    LF            ; Data for aknowledged
  131.     .ASCII    'Y'
  132.     .BYTE    CR
  133. L$AK    =.-M$AK
  134.  
  135. M$NAK:    .BYTE    LF            ; Data for not aknowledged
  136.     .ASCII    'N'
  137.     .BYTE    CR
  138. L$NAK    =.-M$NAK
  139.  
  140. M$UN:    .BYTE    LF            ; Data for unrecognized code
  141.     .ASCII    'U'
  142.     .BYTE    CR
  143. L$UN    =.-M$UN
  144.  
  145. M$RMS:    .BYTE    CR,LF,LF
  146.     .ASCII    'RMS ERROR'
  147. L$RMS    =.-M$RMS
  148.  
  149. M$INIT:    .BYTE    CR,LF,LF
  150.     .ASCII    'Port in use - Try again when free.'
  151. L$INIT    =.-M$INIT
  152.  
  153. M$REC:    .BYTE    CR,LF,LF
  154.     .ASCII    'RECEIVE ERROR - Try again.'
  155. L$REC    =.-M$REC
  156.     .EVEN
  157.  
  158.  
  159.     .SBTTL    Data for set multiple characteristics
  160.  
  161.     .PSECT    $OWN$
  162.  
  163. T$SMC:    .BYTE    TC.RSP                ; Receive speed
  164. RSP:    .BLKB    1
  165.     .BYTE    TC.XSP                ; Transmit speed
  166. XSP:    .BLKB    1
  167.     .BYTE    TC.PAR,0            ; No parity
  168.     .BYTE    TC.FSZ,8.            ; Frame size
  169. L$SMC    =.-T$SMC
  170.  
  171.  
  172.     .SBTTL    Storage locations
  173.  
  174. IOSTAT:    .BLKW    1            ; QIO status
  175. STAT1:    .BLKW    1            ; Second word of status
  176.  
  177. WTCOUNT: .BLKW    1            ; Number of characters written
  178. LENGTH:    .BLKW    1            ; Length of data portion of packet
  179. OPENFL:    .BLKW    1            ; Tells us if the file is open
  180. FILEFL:    .BLKW    1            ; Flag that is set when reading from 
  181.                     ;  a file
  182. LPFLAG:    .BLKW    1            ; Flag that is set when reading from 
  183.                     ;  the printer port
  184.  
  185. CHKSUM:    .BLKW    1            ; Checksum for the line
  186. ADDRESS: .BLKW    1            ; Current address
  187. ALQLOC:    .BLKW    2            ; Storage for allocation
  188.  
  189. OUT.N:    .BLKB    28.            ; Space for output file name
  190. OUT.L    =.-OUT.N            ; Length of output file name
  191.  
  192. INP.N:    .BLKB    28.            ; Space for input file name
  193. INP.L    =.-INP.N            ; Length of input file name
  194.  
  195.     .EVEN                ; Need to start RDBUF on even boundary
  196. RDBUF:    .BLKB    MAX.MSG            ; XK read buffer
  197.     .EVEN
  198. WTBUF:    .BLKB    512.            ; Disk write buffer
  199.     .EVEN
  200.  
  201.  
  202.  
  203.     .SBTTL    RMS 11 Data structures
  204.  
  205. RDFAB::    FAB$B
  206.     F$DNA    DEFALT            ; Address of default device.
  207.     F$DNS    DEFALN            ; Default length field.
  208.     F$FNA    INP.N            ; Address of file name
  209.     F$FNS    INP.L            ; Length of file name
  210.     F$LCH    DWRLUN            ; Logical channel to use
  211.     FAB$E
  212.     .EVEN
  213.  
  214. RDRAB::    RAB$B                ; Beginning of RAB block.
  215.     R$FAB    RDFAB            ; Chain to FAB block.
  216.     R$RAC    RB$SEQ            ; Set the sequential access flag.
  217.     RAB$E                ; End RAB block.
  218.     .EVEN
  219.  
  220.  
  221. WTFAB::    FAB$B
  222.     F$DNA    DEFALT            ; Address of default device.
  223.     F$DNS    DEFALN            ; Default length field.
  224.     F$FNA    OUT.N            ; Address of file name
  225.     F$FNS    OUT.L            ; Length of file name
  226.     F$LCH    DWWLUN            ; Logical channel to use
  227.     FAB$E
  228.     .EVEN
  229.  
  230. WTRAB::    RAB$B                ; Beginning of RAB block.
  231.     R$FAB    WTFAB            ; Chain to FAB block.
  232.     R$RAC    RB$SEQ            ; Set the sequential access flag.
  233.     RAB$E                ; End RAB block.
  234.     .EVEN
  235.  
  236.  
  237.     .SBTTL    Start of program
  238.  
  239.     .PSECT    $CODE$,RO,I
  240.  
  241. DEHEX::
  242.     ALUN$S    #TERLUN,#"TI,#0        ; Assign terminal LUN
  243. 1$:    MOV    #M$PORT,R0        ; Output the port option list    
  244.     MOV    #L$PORT,R1
  245.     JSR    PC,WRITE
  246.     MOV    #RDBUF,R0        ; Input the port the user wants
  247.     MOV    #2,R1
  248.     JSR    PC,READ
  249.     CLR    FILEFL            ; Set flag to say we are reading from
  250.     CLR    LPFLAG            ;  some port(assume correct)
  251.     CMPB    RDBUF,#'1        ; Check and see if choice is XK
  252.     BNE    3$            ; No so branch
  253.     ALUN$S    #XKLUN,#"XK,#0        ; Assign the LUN
  254.     BR    6$            ; Continue with program (set port)
  255. 3$:    CMPB    RDBUF,#'2        ; Check and see if choice is LP
  256.     BNE    4$            ; If no then branch
  257.     ALUN$S    #XKLUN,#"TT,#2        ; Assign the LUN
  258.     MOV    #TRUE,LPFLAG        ; Set flag we're reading from LP
  259.     BR    BEGIN            ; Continue with program
  260. 4$:    CMPB    RDBUF,#'3        ; Make sure its the remaining choice
  261.     BNE    1$            ; If not then try again
  262.     JMP    FILE            ; Go do the disk file
  263. ; Set up XK port
  264. 6$:    JSR    PC,XKINIT        ; Get the XK port
  265. 7$:    MOV    #M$SET,R0        ; Output the is port set up message
  266.     MOV    #L$SET,R1
  267.     JSR    PC,WRITE
  268.     MOV    #RDBUF,R0        ; Get response
  269.     MOV    #2,R1
  270.     JSR    PC,READ
  271.     TST    R0            ; Check for input
  272.     BEQ    7$            ; If none then reprompt
  273.     BICB    #UPPER,RDBUF        ; Convert to upper case
  274.     CMPB    RDBUF,#'Y        ; Check to see if afirmative
  275.     BNE    8$            ; If not then set it up
  276.     JMP    BEGIN            ; Port already set so don't do it
  277. 8$:    MOV    #M$BAUD,R0        ; Output baud rate message
  278.     MOV    #L$BUAD,R1
  279.     JSR    PC,WRITE
  280.     MOV    #RDBUF,R0        ; Get response
  281.     MOV    #2,R1
  282.     JSR    PC,READ
  283.     TST    R0            ; Check for input
  284.     BEQ    7$            ; If none then reprompt
  285.     MOVB    RDBUF,R0        ; Get the answer
  286.     SUB    #'1,R0            ; Subtract off ASCII
  287.     MOVB    D$BAUD(R0),RSP        ; Set the baud rate
  288.     MOVB    D$BAUD(R0),XSP
  289. ; Set the characteristics
  290.     QIO$C    SF.SMC,XKLUN,XKWEFN,,IOSTAT,,<T$SMC,L$SMC>,$CODE$
  291.     BR    BEGIN            ; Go do real stuff
  292.  
  293.  
  294.  
  295. ; If here then we're doing a file
  296. FILE:    MOV    #M$FILE,R0        ; Output the get file name message
  297.     MOV    #L$FILE,R1
  298.     JSR    PC,WRITE
  299.     MOV    #INP.N,R0        ; Get the file name
  300.     MOV    #INP.L,R1
  301.     JSR    PC,READ
  302.     TST    R0            ; Check for no input
  303.     BEQ    FILE            ; Go back and get some
  304. ;Open the file
  305.     MOV    #RDFAB,R1        ; Put address of FAB into R1.
  306.     $STORE    R0,FNS,R1        ; Tell RMS file name length
  307.     $OPEN    #RDFAB            ; Open the file
  308.     JSR    PC,RMSERR        ; Check for file error
  309.     MOV    #RDRAB,R1        ; Put address of RAB into R1.
  310.     $STORE    #RDBUF,UBF,R1        ; Put address of user buffer in RAB.
  311.     $STORE    #RDBUF,RBF,R1        ; Put record buffer address in RAB
  312.     $STORE    #MAX.MSG,USZ,R1        ; Put size of user buffer into RAB.
  313.     $STORE    #MAX.MSG,RSZ,R1        ; Put record buffer size in RAB
  314.     $CONNECT #RDRAB            ; Connect to record.
  315.     JSR    PC,RMSERR        ; Check for file error
  316.     MOV    #TRUE,FILEFL        ; Set flag to file reading
  317.  
  318.  
  319.     .SBTTL    Do the real work
  320. ;++
  321. ; Do the actual work
  322. ;--
  323. BEGIN:    MOV    #M$CRLF,R0        ; Get a return/linefeed and output them
  324.     MOV    #L$CRLF,R1
  325.     JSR    PC,WRITE
  326.  
  327. 20$:    CLR    WTCOUNT            ; Initialize the pointer
  328.     CLR    ADDRESS            ; Initialize the address
  329.     CLR    OPENFL            ; Set the file to not open
  330. ; Say we're ready for data
  331.     MOV    #M$AK,R0        ; Get the address of stuff to send
  332.     MOV    #L$AK,R1        ; Get the length
  333.     JSR    PC,SEND            ; Tell host that we got it
  334.  
  335.     .SBTTL    Main loop
  336.  
  337. ; Main loop to get data
  338. DOLIN:
  339.     CLR    CHKSUM            ; Clear the checksum
  340.     JSR    PC,RECEIVE        ; Get the line
  341.     JSR    PC,CVTBIN        ; Convert it to a real number
  342.     MOV    R0,LENGTH        ; Save the length
  343.     JSR    PC,CVTBIN        ; 
  344.     MOV    R0,R3            ; Save high order of address
  345.     SWAB    R3            ; Shift to correct spot
  346.     JSR    PC,CVTBIN        ; 
  347.     BIS    R0,R3            ; Fill in the low order of address
  348.     JSR    PC,CVTBIN        ; 
  349.  
  350.     CMP    #PKDATA,R0        ; Check to see if this is regular data
  351.     BNE    NOTDAT            ; If not then check the special cases
  352. ; Check for end of hex file
  353.     TST    R3            ; Check to see if the address is all
  354.     BNE    DATST            ;  zero, if not then branch
  355.     TST    LENGTH            ; Check to see if the length is zero
  356.     BNE    DATST            ;  also, if not then branch
  357.     MOV    #M$AK,R0        ; Send an AK for this line since we
  358.     MOV    #L$AK,R1        ;   never reach the place we normally
  359.     JSR    PC,SEND            ;   do this
  360.     JMP    FINISH            ; Must be end of hex file so finish up
  361. ; Regular data to put into the file
  362. DATST:    TST    OPENFL            ; Check to see if the file is open yet
  363.     BNE    DAT1            ; If it is then skip the open
  364.     JSR    PC,OPEN            ; Open the file
  365. DAT1:    CMP    R3,ADDRESS        ; Check for null compression
  366.     BEQ    10$            ; If none compressed then continue past
  367.     CLR    R0            ; Make a null
  368.     JSR    PC,PUT            ;  and put it into the file
  369.     INC    ADDRESS            ; Point to next address
  370.     BR    DATST            ; Go see if there are any more nulls
  371. ; Go to work on the HEX we got on the line
  372. 10$:    MOV    LENGTH,R2        ; Get the length
  373.     TST    R2            ; See if there is any data
  374.     BEQ    30$            ; If not then branch
  375. 25$:    JSR    PC,CVTBIN        ; Convert it
  376.     JSR    PC,PUT            ; Put the character in the file
  377.     INC    ADDRESS            ; Increment the address
  378.     SOB    R2,25$            ; Repeat until all done
  379. 30$:    BR    LINDON            ; Go finish this line
  380.  
  381.  
  382.  
  383. NOTDAT:    MOV    #WTFAB,R5        ; Get the FAB address
  384.     CMP    #PKRFM,R0        ; Check to see if this is record fmt
  385.     BNE    NOTRFM            ; If not then don't do this stuff
  386. ; Store the Record format (FIX, VAR, ...)
  387.     JSR    PC,CVTBIN        ;
  388.     $STORE    R0,RFM,R5        ; Store the record format
  389.     BR    LINDON            ; Go finish this line
  390.  
  391. NOTRFM:    CMP    #PKRAT,R0        ; Check to see if this is record type
  392.     BNE    NOTRAT            ; If not then branch
  393. ; Store the record type (CR, ...)
  394.     JSR    PC,CVTBIN        ;
  395.     $STORE    R0,RAT,R5        ; Store the record type
  396.     BR    LINDON            ; Go finish this line
  397.  
  398. NOTRAT:    CMP    #PKMRS,R0        ; Check to see if this is max record
  399.     BNE    NOTMRS            ;  size, branch if not
  400. ; Get the maximum record size (512. for tasks)
  401.     JSR    PC,CVTBIN        ; Convert high order byte
  402.     MOV    R0,R3            ; Save it
  403.     SWAB    R3            ; Shift it to the high order byte
  404.     JSR    PC,CVTBIN        ; Convert low order byte
  405.     BIS    R0,R3            ; Put low order word into R3 also
  406.     $STORE    R3,MRS,R5        ; Store the maximum record size
  407.     BR    LINDON            ; Go finish this line
  408.  
  409. NOTMRS:    CMP    #PKALQ,R0        ; Check to see if this is allocation
  410.     BNE    NOTALQ            ; If not then branch
  411. ; Get the file length (in blocks)
  412.     JSR    PC,CVTBIN        ; Convert high order byte
  413.     MOV    R0,R3            ; Save it
  414.     SWAB    R3            ; Shift it to the high order byte
  415.     JSR    PC,CVTBIN        ; Convert low order byte
  416.     BIS    R0,R3            ; Put low order word into R3 also
  417.     MOV    R3,ALQLOC        ; Save it
  418.     CLR     ALQLOC+2        ; clear out high word
  419.     $STORE    ALQLOC,ALQ,R5        ; Store the allocation
  420.     BR    LINDON            ; Go finish this line
  421.  
  422. NOTALQ:    CMP    #PKFILNM,R0        ; Check to see if this is file name
  423.     BNE    NOTFILNM        ; If not then branch
  424. ; Get the file name
  425.     MOV    LENGTH,R2        ; Get the length
  426.     $STORE    R2,FNS,R5        ; Store the file name length
  427.     MOV    #OUT.N,R3        ; Get the output file name address
  428. 25$:    JSR    PC,CVTBIN        ; Convert next character of the name
  429.     MOVB    R0,(R3)+        ; Save the character
  430.     SOB    R2,25$            ; Repeat until all done
  431.     MOV    #M$CRLF,R0        ;
  432.     MOV    #L$CRLF,R1        ;
  433.     JSR    PC,WRITE        ; Output a return/line feed
  434.     MOV    #OUT.N,R0        ;
  435.     MOV    LENGTH,R1        ;
  436.     JSR    PC,WRITE        ; Output the file name
  437.     MOV    #M$CRLF,R0        ;
  438.     MOV    #L$CRLF,R1        ;
  439.     JSR    PC,WRITE        ; Output a return/line feed
  440.     BR    LINDON            ; Go finish this line
  441.  
  442.  
  443.  
  444. NOTFILNM:
  445.     CMP    #PKEOF,R0        ; Check to see if this is end of task
  446.     BNE    NOTPKEOF        ; If not then branch
  447. ; End of ouput file record found
  448.     JSR    PC,CLTSK        ; Close the task file
  449.     CLR    WTCOUNT            ; Initialize the pointer
  450.     CLR    ADDRESS            ; Initialize the address
  451.     JMP    LINDON            ; Go finish this line
  452.  
  453. ; Unknown code
  454. NOTPKEOF:                ; Since we don't know what the code
  455.     MOV    #M$UN+1,R0        ;   just send the unknown code text to
  456.     MOV    #1,R1            ;   the terminal and the port
  457.     JSR    PC,WRITE        ;
  458.     DEC    R0            ; Move to beginning of data
  459.     MOV    #L$UN,R1        ;
  460.     JSR    PC,SEND            ;
  461.     JMP    DOLIN            ; Go do next input line
  462.     
  463.  
  464.     .SBTTL    Finished with this line
  465.  
  466. ; Line processed without a problem
  467. LINDON:
  468.     MOV    #M$AK+1,R0        ; Get the data address of the 
  469.                     ;  single character
  470.     MOV    #1,R1            ; Only write single char to terminal
  471.     JSR    PC,WRITE        ; Write to the terminal
  472.     DEC    R0            ; Get to beginning of data
  473.     MOV    #L$AK,R1        ; Get the length of the data
  474.     JSR    PC,SEND            ; Send the aknowledgement to the port
  475.     JMP    DOLIN            ; Good so do next line
  476.  
  477.  
  478.     .SBTTL    Finish up
  479. ;++
  480. ;Finish up
  481. ;--
  482. FINISH:
  483. ; Close the file(s)
  484.     JSR    PC,CLTSK        ; Close the task file if it isn't yet
  485.     TST    FILEFL            ; See if we read from a file
  486.     BEQ    10$            ; If not then branch
  487.     MOV    #RDFAB,R1        ; Get FAB for input file
  488.     $CLOSE    R1            ; Close the input file
  489.     JSR    PC,RMSERR        ; Check for file error
  490.     BR    END            ; Go exit
  491. 10$:    JSR    PC,XK.SHT        ; Shut down the XK port if we didn't
  492.                     ;   read from a file
  493. END:    EXIT$S
  494.  
  495.     .SBTTL    Close file
  496.  
  497. ;++
  498. ; Close the output file if there is one open
  499. ;
  500. ; If there is an error the program stops with an RMS error
  501. ;
  502. ; Registers destroyed:    R0, R1
  503. ; The OPENFL state is changed to file not open (OPENFL=0).
  504. ;--
  505.  
  506. CLTSK:    TST    OPENFL            ; See if the task file is open
  507.     BEQ    10$            ; If not then just return
  508.  
  509. ; Write last buffer if needed
  510.     TST    WTCOUNT            ; See if there is any data not written
  511.     BEQ    8$            ; If not then branch
  512.     MOV    #WTRAB,R1        ; Get the RAB address
  513.     $STORE    WTCOUNT,RSZ,R1        ; Put its size into the RAB.
  514.     $WRITE    R1            ; Put the buffer of data.
  515.     JSR    PC,RMSERR        ; Check for file error
  516.  
  517. ; Close the file
  518. 8$:    MOV    #WTFAB,R1        ; Get FAB for output file
  519.     $CLOSE    R1            ; Close output file
  520.     JSR    PC,RMSERR        ; Check for file error
  521.     CLR    OPENFL            ; Set the state to file not open
  522. 10$:    RTS    PC            ; Return to sender    
  523.     
  524.  
  525.     .SBTTL    Output and input to/from terminal
  526. ;++
  527. ; Write data to terminal.
  528. ; Call with:        R0    Address of data to output
  529. ;            R1    Length of data
  530. ; Registers destroyed:    NONE
  531. ;--
  532. WRITE:
  533.     QIOW$S    #IO.WVB,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
  534.     RTS    PC
  535. ;++
  536. ; Read from the terminal
  537. ; Call with:        R0    Address of buffer
  538. ;            R1    Number of characters to read
  539. ;
  540. ; Returned:        R0    Number of characters read
  541. ; Registers destroyed:    R0
  542. ;--
  543. READ:    QIOW$S    #IO.RVB!TF.ESQ,#TERLUN,#TTEFN,,#IOSTAT,,<R0,R1>
  544.     MOV    STAT1,R0        ; Get the number of character read
  545.     RTS    PC
  546.  
  547.  
  548.     .SBTTL    RMS error routine
  549. ;++
  550. ;Check for RMS error
  551. ; Call with:        R1    RMS FAB address
  552. ;
  553. ; Returned:        R0    Status
  554. ; Registers destroyed:    R0
  555. ; Program stops after error message is displayed if there is any type of error.
  556. ;--
  557. RMSERR:    $FETCH    R0,STS,R1        ; Get the status and put it in R0
  558.     TST    R0            ; Test the status code for success.
  559.     BMI    60$            ; If negative then branch.
  560.     MOV    #KNORMAL,R0        ; Set up a successful return code.
  561.     RTS    PC            ; Return to caller
  562.  
  563. ; Here if there is an RMS error we can't recover from
  564. 60$:    MOV    #M$RMS,R0        ; Get the RMS error message
  565.     MOV    #L$RMS,R1        ;  address and length
  566.     JSR    PC,WRITE        ; Output the error message
  567.     EXIT$S                ; Exit since we can not recover
  568.  
  569.  
  570.     .SBTTL    Open the output file
  571. ;++
  572. ; Create and open the output file and set the file open flag
  573. ;
  574. ; Registers destroyed:    R0, R1
  575. ; Program stops after error message is displayed if there is any type of error.
  576. ;--
  577.  
  578. OPEN:    MOV    #TRUE,OPENFL        ; State that the file is open
  579.     MOV    #WTFAB,R1        ; Put address of FAB into R1.
  580.     $SET    #FB$WRT,FAC,R1        ; Set the block write in FAB.
  581.     $STORE    #FB$CTG,FOP,R1        ; Tell RMS to make the task contiguous
  582.     $CREATE    #WTFAB            ; Create the file
  583.     JSR    PC,RMSERR        ; Check for file error
  584.     MOV    #WTRAB,R1        ; Put address of RAB into R1.
  585.     $STORE    #WTBUF,UBF,R1        ; Put address of user buffer in RAB.
  586.     $STORE    #WTBUF,RBF,R1        ; Put record buffer address in RAB
  587.     $STORE    #512.,USZ,R1        ; Put size of user buffer into RAB.
  588.     $STORE    #512.,RSZ,R1        ; Put record buffer size in RAB
  589.     $CONNECT #WTRAB            ; Connect to record.
  590.     JSR    PC,RMSERR        ; Check for file error
  591.     RTS    PC            ; Return to sender
  592.  
  593.     .SBTTL    Put a character to the file
  594. ;++
  595. ; Put a character to the output file.
  596. ; The buffer is only written when 512. characters have been sent to the routine
  597. ; If the file does not end on a boundary then the buffer will have to be 
  598. ; written by some other routine.
  599. ; Call with:        R0    Contains the character to be put into file
  600. ; Registers destroyed:    R0, R1
  601. ;
  602. ; Program stops after error message is displayed if there is any type of error.
  603. ;--
  604.  
  605. PUT:    MOV    R0,-(SP)        ; Save the character
  606.     MOV    WTCOUNT,R0        ; Get the offset into the buffer
  607.     MOVB    (SP)+,WTBUF(R0)        ; Put the character
  608.     INC    WTCOUNT            ; Increment the offset into the buffer
  609.     CMP    WTCOUNT,#512.        ; Check to see if we are past the end
  610.     BNE    10$            ; If not then branch
  611.     MOV    #WTRAB,R1        ; Get the RAB address
  612.     $STORE    WTCOUNT,RSZ,R1        ; Put its size into the RAB.
  613.     $WRITE    R1            ; Put the buffer of data.
  614.     JSR    PC,RMSERR        ; Check for file error
  615.     CLR    WTCOUNT            ; Clear the pointer
  616. 10$:    RTS    PC            ; Return to sender
  617.  
  618.     .SBTTL     Convert to binary
  619. ;++
  620. ; Convert 2 hexidecimal digits to binary
  621. ; Input is from the input buffer pointed to by R4 (it is incremented twice)
  622. ;
  623. ; Call with:        R4    The pointer into the input buffer
  624. ; Returned:        R0    The binary walue
  625. ; Registers destroyed:    R0,R1
  626. ;--
  627.  
  628. CVTBIN:
  629.     CLR    R0            ; Clear R0 for the BISB
  630.     BISB    (R4)+,R0        ; Get the next digit
  631.     JSR    PC,BIN            ;   in place and convert to binary
  632.     ASH    #4,R0            ; Multiply the result by 16
  633.     MOV    R0,R1            ;  and save it
  634.     CLR    R0            ; Clear R0
  635.     BISB    (R4)+,R0        ; Get the next digit
  636.     JSR    PC,BIN            ; Convert to binary
  637.     BIS    R1,R0            ; Set the correct bits for high order
  638.     ADD    R0,CHKSUM        ; Add the value to the checksum
  639.     RTS    PC            ; Return to sender
  640.  
  641. BIN:    CMP    R0,#'9            ; Check to see if above '9
  642.     BLE    1$            ; If not then branch
  643.     SUB    #HEXOFFSET,R0        ; Subtract offset to alphabet
  644. 1$:    SUB    #48.,R0            ; Make binary
  645.     RTS    PC            ; Return to sender
  646.  
  647.  
  648.     .SBTTL    Initialize the port
  649. XKINIT:
  650. ;++
  651. ; Attach to the port so that no one else can be screwing around
  652. ; with it behind our backs.
  653. ;
  654. ; Registers destroyed:    R0
  655. ;
  656. ; If there is an error the error message will be output and the program 
  657. ; will stop.
  658. ;--
  659.  
  660.     QIO$S    #IO.ATT,#XKLUN,#XKREFN,,#IOSTAT    ; Grab the device
  661.  
  662.     MOVB    IOSTAT,R0        ; Get the status
  663.     BLE    BAD            ; Branch if bad
  664. ; Set the characteristics
  665.     RTS    PC            ; Return good try
  666. ; Here if we can't get the XK port
  667. BAD:    MOV    #M$INIT,R0        ; Get the INIT error message
  668.     MOV    #L$INIT,R1        ;  address and length
  669.     JSR    PC,WRITE        ; Output the error message
  670.     QIOW$C    IO.KIL,XKLUN,XKWEFN,,,,,$CODE$    ; Kill pending I/O queues.
  671.     EXIT$S                ; Exit since we can not recover
  672.  
  673. XK.SHT:    QIOW$C    IO.KIL,XKLUN,XKWEFN,,,,,$CODE$    ; Kill pending I/O queues.
  674.     QIOW$C    IO.DET,XKLUN,XKWEFN,,,,,$CODE$    ; Detach the device
  675.     RTS    PC                ; And return
  676.  
  677.  
  678.     .SBTTL    Receive a line of data
  679.  
  680. ;++
  681. ; This will get a line of data from the input device
  682. ;
  683. ; Returned:        R4    Address of start of data buffer
  684. ; Registers destroyed:    R0, R1, R3, R4
  685. ;
  686. ; A checksum error will cause a NAK to be sent and input to be read again
  687. ; A real error will cause an error message to be output and the program to stop
  688. ;--
  689.  
  690. RECEIVE:
  691.     TST    FILEFL            ; See if we're reading from a file
  692.     BEQ    10$            ; If not then don't read from the file
  693.  
  694. ; Here if we're reading from a file
  695.     MOV    #RDRAB,R1        ; Get the RAB address
  696.     $GET    R1            ; Get the record
  697.     JSR    PC,RMSERR        ; Check for file error
  698.     MOV    #MAX.MSG,R3        ; Assume we got a full buffer
  699.     BR    RECCHK            ; Check the data we got
  700. ; Here so reading from one of the ports
  701. 10$:    TST    LPFLAG            ; See if we're reading from LP:
  702.     BNE    RECLP            ; If so then use that routine
  703.  
  704. ; Here if we're reading from the XK port
  705.     MOV    #RDBUF,R1        ; Point at first byte of buffer
  706.     CLR    R3            ; Clear count of chars we have seen
  707.  
  708.     QIOW$S    #IO.RAL!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<R1,#1.>
  709.     TST    IOSTAT            ; Test for error
  710.     BMI    85$            ; If we got an error, return it
  711.     BICB    #MSB,(R1)        ; Clear most significant bit
  712.     CMPB    (R1)+,#RCV.SOH        ; Check for start of header
  713.     BNE    10$            ; If not, check timeout and try again
  714.     INC    R3            ; Increment the counter
  715.  
  716. ; Here after we have gotten the start of packet character.  Now pick up the
  717. ;rest
  718. 20$:    QIOW$S    #IO.RAL!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<R1,#1.>
  719.     TST    IOSTAT            ; Test for error
  720.     BMI    85$            ; If we got an error, return it
  721.  
  722.     BICB    #MSB,(R1)        ; Clear most significant bit
  723.     CMPB    @R1,#RCV.SOH        ; Check for start of header
  724.     BEQ    10$            ; Restart buffer if so
  725.  
  726.     INC    R3            ; Count the character
  727.  
  728.     CMPB    (R1)+,#RCV.EOL        ; Get end of line character?
  729.     BEQ    RECCHK            ; Yes, go return
  730.  
  731.     CMP    R3,#MAX.MSG        ; Fill buffer completly yet?
  732.     BNE    20$            ; If not, just get next character
  733.  
  734.     DEC    R1            ; Otherwise, back up one character
  735.     BR    20$            ; And try again
  736.  
  737. ; Here if we got some error that makes it impossible to continue the transfer
  738. 85$:    MOV    #M$REC,R0        ; Get the receive error message
  739.     MOV    #L$REC,R1        ;  address and length
  740.     JSR    PC,WRITE        ; Output the error message
  741.     EXIT$S                ; Exit since we can not recover
  742.  
  743. ; Here to read from LP port(TT2:)
  744. RECLP:
  745.     QIOW$S    #IO.RVB!TF.RNE,#XKLUN,#XKREFN,,#IOSTAT,,<#RDBUF,#MAX.MSG>
  746.     MOV    STAT1,R3        ; Get number of characters read
  747.  
  748.  
  749.  
  750. ; Here to check the data we got from any type of receive routine
  751. RECCHK:    MOV    #RDBUF,R4        ; Get the address of the information
  752.     CLR    R1            ; Clear the data start address 
  753. 80$:    BICB    #MSB,(R4)        ; Clear parity bit
  754.     CMPB    (R4)+,#RCV.SOH        ; Check for start of header
  755.     BNE    81$            ; If not the just keep going
  756.     MOV    R4,R1            ; Start of header so save it
  757. 81$:    SOB    R3,80$            ; Repeat until done
  758.     TST    R1            ; Check to see if we got a SOH
  759.     BNE    85$            ; If good then skip the jump
  760.     JMP    RECEIVE            ; If not then re-read
  761. 85$:    MOV    R1,R4            ; Move to R4 for use
  762.     MOV    R4,-(SP)        ; Save SOH pointer on stack
  763.  
  764.     JSR    PC,CVTBIN        ; Convert all to binary to see if
  765.     MOV    R0,R3            ; Get the length of data
  766.     ADD    #4,R3            ; Add the length of address and field
  767.                     ;   type and checksum
  768.     BMI    94$            ; If we have a negative number then 
  769.                     ;   must have been a bad length
  770.     CMP    R3,#MAX.MSG/2-1        ; If we got some length that is out of
  771.     BGE    94$            ;   range then NAK right away
  772. 92$:    JSR    PC,CVTBIN        ; Convert all to binary to see if
  773.     SOB    R3,92$            ;   the checksum is OK
  774. 93$:    BIC    #LEFTBYTE,CHKSUM    ; We only want an 8 bit checksum
  775.     TST    CHKSUM            ; Test for a zero checksum
  776.     BEQ    95$            ; If OK then exit normally
  777. 94$:    CLR    CHKSUM            ; Clear the checksum for the line
  778.     MOV    #M$NAK+1,R0        ; Get the address of the message
  779.     MOV    #1,R1            ; Only write the first character to
  780.     JSR    PC,WRITE        ;   the terminal
  781.     DEC    R0            ; Move to beginning of data
  782.     MOV    #L$NAK,R1        ; Get the whole message length for port
  783.     JSR    PC,SEND            ; Send a NAK to the port
  784.     TST    (SP)+            ; Pull to pointer off the stack
  785.     JMP    RECEIVE            ; Try to get the line again
  786.  
  787. ; Return to sender
  788. 95$:    MOV    (SP)+,R4        ; Get the pointer back
  789.     RTS    PC            ; Return to sender
  790.  
  791.  
  792.     .SBTTL    Send a line to the host
  793.  
  794. ;++
  795. ; Send the buffer to the host if we aren't reading from a file
  796. ; If reading from a file just return
  797. ;
  798. ; Registers destroyed:    None
  799. ;--
  800.  
  801. SEND:
  802.     TST    FILEFL            ; See if we're reading from a file
  803.     BNE    20$            ; If so then don't send to the port
  804.     QIOW$S    #IO.WLB,#XKLUN,#XKWEFN,,#IOSTAT,,<R0,R1>
  805. 20$:    RTS    PC            ; Return to sender
  806.  
  807.     .SBTTL    End of the Dehexify
  808.  
  809.     .END    DEHEX
  810.  
  811.