home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / SIMTEL / CPMUG / CPMUG019.ARK / RM80.ASM < prev    next >
Assembly Source File  |  1985-02-10  |  61KB  |  1,833 lines

  1. ;;;       RM80 V2.0 - RESIDENT MONITOR FOR AN 8080 / Z80 SYSTEM
  2. ;
  3. ;         LAWRENCE E. HUGHES III
  4. ;         8080 SOFTWARE DEVELOPMENT CENTER
  5. ;         1506 MYRICK ROAD
  6. ;         TALLAHASSEE, FLORIDA 32303
  7.  
  8.           ORG    5800H
  9.  TBUF:    DS     1024           ;TAPE BUFFER
  10.  NBUF:    DS     11             ;FILENAME BUFFER
  11.  TUNIT:   DS     1              ;TAPE UNIT BUFFER
  12.  PRN:     DS     1              ;PHYSICAL RECORD NUMBER
  13.  CTPC:    DS     1              ;CASSETTE TAPE PAGE COUNT
  14.  IBUF:    DS     128            ;INPUT BUFFER
  15.  STACK:   DS     64             ;SYSTEM STACK AREA
  16.  PFLAG1:  DS     1              ;PARAMETER FLAGS
  17.  PFLAG2:  DS     1
  18.  PARAM1:  DS     2              ;PARAMETERS
  19.  PARAM2:  DS     2
  20.  CBUF:    DS     6              ;COMMAND BUFFER
  21.  INCH:    DS     1              ;CHARACTER BUFFERS FOR LINK
  22.  OUTCH:   DS     1
  23.  DMPAD:   DS     2              ;DUMP ADDRESS 
  24.  CRC:     DS     2              ;TEMP STORAGE FOR TAPE CRC
  25.  LDERR:   DS     1              ;LOADER ERROR COUNT
  26.  OFLST:   DS     1              ;OBJECT FILE LOADER STATE
  27.  OFLCE:   DS     1              ;OBJECT FILE LOADER CHECKSUM ERROR FLAG
  28.  OFLLA:   DS     2              ;OBJECT FILE LOADER LOAD ADDRESS
  29.  OFLOS:   DS     2              ;OBJECT FILE LOADER OFFSET
  30.  OFLBC:   DS     1              ;OBJECT FILE LOADER BYTE COUNT
  31.  OFLCS:   DS     1              ;OBJECT FILE LOADER CHECKSUM
  32.  OFLBB:   DS     1              ;OBJECT FILE LOADER BYTE BUFFER
  33.  OFLSW:   DS     1              ;OBJECT FILE LOADER SWITCH (NON-ZERO = ON)
  34.  TFLSW:   DS     1              ;TEXT FILE LOADER SWITCH (NON-ZERO = ON)
  35.  TFLFWA:  DS     2              ;TEXT FILE LOADER FIRST WORD ADDRESS
  36.  TFLLWA:  DS     2              ;TEXT FILE LOADER LAST WORD ADDRESS
  37.  TEMP:    DS     3              ;TEMPORARY AREA FOR IN AND OUT COMMANDS
  38.  
  39.  NULL     EQU    00H
  40.  SOH      EQU    01H
  41.  STX      EQU    02H
  42.  ETX      EQU    03H
  43.  BS       EQU    08H 
  44.  LF       EQU    0AH
  45.  CR       EQU    0DH
  46.  DEL      EQU    7FH
  47.  
  48. ;;;       MAIN PROGRAM - GET COMMAND, SCAN IT AND BRANCH
  49.  
  50.           ORG    0C000H
  51.           JMP    RM80
  52.           JMP    RACC           ;READ ASCII CHAR FROM CONSOLE
  53.           JMP    CRDAC          ;CHECK FOR RDA FROM CONSOLE
  54.           JMP    WACC           ;WRITE ASCII CHAR TO CONSOLE
  55.           JMP    CTBEC          ;CHECK FOR TBE FROM CONSOLE
  56.           JMP    RACM           ;READ ASCII CHARACTER FROM MODEM
  57.           JMP    CRDAM          ;CHECK FOR RDA FROM MODEM
  58.           JMP    WACM           ;WRITE ASCII CHARACTER TO MODEM
  59.           JMP    CTBEM          ;CHECK FOR TBE FROM MODEM
  60.           JMP    CTRR           ;READ PHYSICAL RECORD FROM TAPE
  61.           JMP    CTWR           ;WRITE PHYSICAL RECORD TO TAPE
  62.           JMP    MOVEUP         ;MOVE BLOCK OF MEMORY TOWARDS 0000
  63.           JMP    MOVEDN         ;MOVE BLOCK OF MEMORY TOWARDS FFFF
  64.           JMP    DMP            ;DUMP BLOCK OF MEMORY IN HEX/ASCII
  65.           JMP    RASC           ;READ ASCII STRING FROM CONSOLE
  66.           JMP    DHS            ;DECODE HEX STRING
  67.  
  68.  RM80:    LXI    SP,STACK+64
  69.           CALL   INITC          ;INITIALIZE CONSOLE
  70.           CALL   INITM          ;INITIALIZE MODEM
  71.           CALL   INITT          ;INITIALIZE TAPE
  72.           LXI    H,0            ;CLEAR OBJECT FILE LOADER OFFSET
  73.           SHLD   OFLOS
  74.           CALL   WEOLC
  75.           LXI    H,RM80S1       ;PRINT 'RM80 V2.0'
  76.           CALL   WASC
  77.  
  78.  RM801:   MVI    A,')'          ;ISSUE PROMPT CHAR
  79.           CALL   WACC
  80.           LXI    H,IBUF         ;READ COMMAND INTO IBUF
  81.           CALL   RASC
  82.           MVI    M,' '          ;INSURE AT LEAST ONE BLANK AT END
  83.           INX    H
  84.           MVI    M,CR
  85.           LXI    D,IBUF         ;PARSE COMMAND
  86.           LXI    H,CBUF         ;SCAN OFF KEYWORD INTO CBUF
  87.           MVI    C,6            ;MAX KEYWORD SIZE
  88.  RM802:   LDAX   D              ;FETCH NEXT CHAR FROM IBUF
  89.           INX    D
  90.           CPI    61H            ;IF LC, CONVERT TO UC
  91.           JC     $+5
  92.           SUI    20H
  93.           CPI    ' '            ;EXIT AT END-OF-KEYWORD
  94.           JZ     RM803
  95.           MOV    M,A            ;STORE IN CBUF
  96.           INX    H
  97.           DCR    C              ;LOOP IF 5 OR LESS CHARS SO FAR
  98.           JNZ    RM802
  99.           JMP    RM80X          ;ELSE TAKE ERROR EXIT
  100.  RM803:   INR    C              ;BLANK FILL REST OF CBUF
  101.           DCR    C
  102.           JZ     RM804
  103.           MVI    M,' '
  104.           INX    H
  105.           JMP    RM803+1
  106.  RM804:   XRA    A              ;CLEAR PARAMETER FLAGS
  107.           STA    PFLAG1
  108.           STA    PFLAG2
  109.           CALL   DHS            ;DECODE FIRST PARAMETER INTO HL
  110.           JC     RM80X          ;BRANCH ON ERROR
  111.           STA    PFLAG1
  112.           SHLD   PARAM1         ;SAVE FIRST PARAMETER
  113.           CALL   DHS            ;DECODE SECOND PARAMETER
  114.           JC     RM80X          ;BRANCH ON ERROR
  115.           STA    PFLAG2
  116.           SHLD   PARAM2         ;SAVE SECOND PARAMETER
  117.           LDA    PFLAG1         ;IF NO FIRST PARAM, DEFAULT TO 100H
  118.           ORA    A
  119.           JNZ    $+9
  120.           LXI    H,100H
  121.           SHLD   PARAM1
  122.           LDA    PFLAG2         ;IF NO SECOND PARAM, DEFAULT TO PARAM1
  123.           ORA    A
  124.           JNZ    $+9
  125.           LHLD   PARAM1
  126.           SHLD   PARAM2
  127.  RM805:   LXI    H,CTAB         ;LOOKUP KEYWORD IN COMMAND TABLE
  128.  RM806:   LXI    D,CBUF
  129.           MVI    C,5            ;NUMBER OF BYTES TO COMPARE
  130.           MVI    B,1            ;SET MATCH FLAG
  131.  RM807:   LDAX   D              ;FETCH NEXT BYTE OF KEYWORD
  132.           CMP    M              ;COMPARE WITH NEXT BYTE OF TABLE
  133.           JZ     $+5            ;JUMP IF GOOD COMPARE
  134.           MVI    B,0            ;CLEAR MATCH FLAG
  135.           INX    D              ;INCREMENT POINTERS
  136.           INX    H
  137.           DCR    C              ;LOOP THRU ENTIRE KEYWORD
  138.           JNZ    RM807
  139.           DCR    B              ;TEST MATCH FLAG
  140.           JZ     RM808          ;JUMP IF GOOD MATCH
  141.           INX    H              ;ELSE SKIP ADDR FIELD
  142.           INX    H
  143.           MOV    A,M            ;LOOP IF NOT END OF TABLE
  144.           ORA    A
  145.           JNZ    RM806
  146.           LXI    H,RM80S2       ;PRINT 'ILLEGAL COMMAND'
  147.           CALL   WASC
  148.           JMP    RM801          ;AND LOOP
  149.  RM808:   MOV    E,M            ;FETCH ADDR FIELD INTO DE
  150.           INX    H
  151.           MOV    D,M
  152.           LXI    B,RM801        ;CREATE A RETURN ADDRESS
  153.           PUSH   B
  154.           PUSH   D              ;FORCE JUMP ADDR ONTO STACK
  155.           LHLD   PARAM2         ;DE = SECOND PARAMETER
  156.           XCHG
  157.           LHLD   PARAM1         ;HL = FIRST PARAMETER
  158.           RET                   ;WOULD YOU PREFER 'POP    PC'?
  159.  
  160.  RM80X:   LXI    H,RM80S3       ;PRINT 'SYNTAX ERROR'
  161.           CALL   WASC
  162.           JMP    RM801          ;AND LOOP
  163.  
  164.  RM80S1:  DB     'RM80 V2.0',CR,LF,0
  165.  RM80S2:  DB     'ILLEGAL COMMAND',CR,LF,0
  166.  RM80S3:  DB     'SYNTAX ERROR',CR,LF,0
  167.  
  168. ;         COMMAND TABLE
  169.  
  170.  CTAB:    DB     'DUMP '
  171.           DW     DUMP
  172.           DB     'TYPE '
  173.           DW     TYPE
  174.           DB     'ENTER'
  175.           DW     ENTER
  176.           DB     'TEXT '
  177.           DW     TEXT
  178.           DB     'MOVE '
  179.           DW     MOVE
  180.           DB     'FILL '
  181.           DW     FILL
  182.           DB     'GO   '
  183.           DW     GO
  184.           DB     'STORE'
  185.           DW     STORE
  186.           DB     'FETCH'
  187.           DW     FETCH
  188.           DB     'CHECK'
  189.           DW     CHECK
  190.           DB     'UNIT '
  191.           DW     UNIT
  192.           DB     'WRITE'
  193.           DW     WRITE
  194.           DB     'READ '
  195.           DW     READ
  196.           DB     'LOAD '
  197.           DW     LOAD
  198.           DB     'SCAN '
  199.           DW     SCAN
  200.           DB     'LINK '
  201.           DW     LINK
  202.           DB     'SOLO '
  203.           DW     SOLO
  204.           DB     'IN   '
  205.           DW     RIP
  206.           DB     'OUT  '
  207.           DW     WOP
  208.           DB     0              ;END OF COMMAND TABLE
  209.  
  210. ;;        RIP - READ INPUT PORT (AND DISPLAY)
  211.  
  212.  RIP:     MVI    A,0DBH         ;JAM INPUT INSTRUCTION
  213.           STA    TEMP+0
  214.           MOV    A,L            ;PORT ADDRESS
  215.           STA    TEMP+1
  216.           MVI    A,0C9H         ;JAM RETURN INSTRUCTION
  217.           STA    TEMP+2
  218.           CALL   TEMP           ;EXECUTE INPUT COMMAND
  219.           CALL   WHBC           ;WRITE BYTE IN HEX
  220.           JMP    WEOLC          ;EXIT VIA WEOLC
  221.  
  222. ;;        WOP - WRITE OUTPUT PORT
  223.  
  224.  WOP:     MVI    A,0D3H         ;JAM OUTPUT INSTRUCTION
  225.           STA    TEMP+0
  226.           MOV    A,L            ;PORT NUMBER
  227.           STA    TEMP+1
  228.           MVI    A,0C9H         ;JAM RETURN INSTRUCTION
  229.           STA    TEMP+2
  230.           MOV    A,E            ;BYTE TO OUTPUT
  231.           CALL   TEMP           ;EXECUTE OUTPUT COMMAND
  232.           JMP    WEOLC          ;EXIT VIA WEOLC
  233.  
  234. ;;        DUMP - RM80 DUMP COMMAND
  235.  
  236.  DUMP:    LDA    PFLAG1         ;JUMP IF NO PARAMETERS
  237.           ORA    A
  238.           JZ     DUMP1
  239.           CALL   DIFF           ;DE=DE-HL+1
  240.           INX    D
  241.           SHLD   DMPAD          ;SET DUMP ADDRESS TO REAL FWA
  242.           JMP    DMP            ;PERFORM DUMP AND RETURN
  243.  DUMP1:   LXI    H,0            ;SET DUMP ADDRESS TO ZERO
  244.           SHLD   DMPAD
  245.  DUMP2:   LXI    H,TBUF         ;READ NEXT RECORD FROM TAPE
  246.           LXI    B,NBUF
  247.           CALL   CTRR
  248.           CALL   WEOLC
  249.           CALL   CTPH           ;PRINT HEADER INFO (NAME, TYPE, ETC)
  250.           MOV    A,D            ;SAVE PAGE COUNT
  251.           STA    CTPC
  252.           LXI    H,TBUF         ;DUMP RECORD
  253.           CALL   DMP
  254.           LDA    CTPC           ;FETCH PAGE COUNT
  255.           CPI    4              ;LOOP UNLESS SHORT RECORD
  256.           JNC    DUMP2
  257.           RET
  258.  
  259. ;;        TYPE - RM80 TYPE COMMAND
  260.  
  261.  TYPE:    LDA    PFLAG1         ;JUMP IF NO PARAMETERS
  262.           ORA    A
  263.           JZ     TYPE2
  264.           CALL   DIFF           ;DE = DE-HL+1
  265.           INX    D
  266.  TYPE1:   MOV    A,D            ;EXIT WHEN DE=0
  267.           ORA    E
  268.           JZ     WEOLC
  269.           MOV    A,M            ;FETCH NEXT BYTE
  270.           CPI    'Z'-40H        ;EXIT IF END-OF-FILE CHAR
  271.           JZ     WEOLC
  272.           INX    H
  273.           CALL   WACC           ;WRITE IT - USER ASKED FOR IT
  274.           DCX    D              ;DECREMENT COUNT AND LOOP
  275.           JMP    TYPE1
  276.  TYPE2:   LXI    H,TBUF         ;READ NEXT RECORD FROM TAPE
  277.           LXI    B,NBUF
  278.           CALL   CTRR
  279.           MOV    A,D            ;SAVE PAGE COUNT
  280.           STA    CTPC
  281.           LXI    H,TBUF         ;TYPE CONTENTS OF RECORD
  282.  TYPE3:   MOV    A,D            ;EXIT WHEN COUNT=0
  283.           ORA    E
  284.           JZ     TYPE4
  285.           MOV    A,M            ;WRITE NEXT BYTE
  286.           CPI    'Z'-40H        ;EXIT IF END-OF-FILE CHAR
  287.           JZ     WEOLC
  288.           INX    H
  289.           CALL   WACC
  290.           DCX    D              ;DECREMENT COUNT
  291.           JMP    TYPE3
  292.  TYPE4:   LDA    CTPC           ;FETCH PAGE COUNT
  293.           CPI    4              ;LOOP IF NOT SHORT RECORD
  294.           JNC    TYPE2
  295.           JMP    WEOLC          ;WRITE END-OF-LINE AND RETURN
  296.  
  297. ;;        ENTER - RM80 ENTER COMMAND
  298.  
  299.  ENTER:   MOV    A,H            ;PROMPT WITH CURRENT LOAD ADDRESS
  300.           CALL   WHBC
  301.           MOV    A,L
  302.           CALL   WHBC
  303.           MVI    A,'?'
  304.           CALL   WACC
  305.           MVI    A,' '
  306.           CALL   WACC
  307.           PUSH   H              ;SAVE LOAD ADDRESS
  308.           LXI    H,IBUF         ;READ INPUT LINE
  309.           CALL   RASC
  310.           DCR    B              ;EXIT ON EMPTY LINE
  311.           JZ     ENTER3
  312.           LXI    D,IBUF         ;DECODE AND LOAD BYTES ON THIS LINE
  313.  ENTER1:  CALL   DHS            ;DECODE NEXT BYTE
  314.           JC     ENTERX
  315.           ORA    A              ;EXIT AT END OF LINE
  316.           JZ     ENTER2
  317.           MOV    A,L
  318.           POP    H              ;RESTORE LOAD ADDRESS
  319.           MOV    M,A            ;LOAD BYTE INTO MEMORY
  320.           INX    H              ;INCREMENT LOAD ADDRESS
  321.           PUSH   H              ;SAVE LOAD ADDRESS AWAY AGAIN
  322.           JMP    ENTER1         ;LOOP
  323.  ENTER2:  POP    H              ;RESTORE LOAD ADDRESS
  324.           JMP    ENTER          ;AND GO ON WITH NEXT LINE
  325.  ENTER3:  POP    H              ;CLEAR STACK AND EXIT
  326.           JMP    WEOLC
  327.  ENTERX:  POP    H
  328.           LXI    H,ENTERS1
  329.           JMP    WASC
  330.  
  331.  ENTERS1: DB     'ERROR',CR,LF,0
  332.  
  333. ;;        TEXT - RM80 TEXT COMMAND
  334.  
  335.  TEXT:    PUSH   H              ;SAVE LOAD ADDRESS
  336.           MOV    A,H            ;PROMPT WITH CURRENT LOAD ADDRESS
  337.           CALL   WHBC
  338.           MOV    A,L
  339.           CALL   WHBC
  340.           MVI    A,'?'
  341.           CALL   WACC
  342.           MVI    A,' '
  343.           CALL   WACC
  344.           LXI    H,IBUF
  345.           CALL   RASC           ;READ NEXT LINE FROM CONSOLE
  346.           DCR    B              ;EXIT ON EMPTY LINE (JUST CR)
  347.           JZ     TEXT2
  348.           INR    B
  349.           POP    H              ;RESTORE LOAD ADDRESS
  350.           LXI    D,IBUF         ;STORE LINE IN MEMORY
  351.  TEXT1:   LDAX   D              ;FETCH NEXT CHAR FROM IBUF
  352.           INX    D
  353.           MOV    M,A            ;STORE IN MEMORY
  354.           INX    H
  355.           DCR    B              ;DECREMENT COUNT
  356.           JNZ    TEXT1          ;LOOP UNTIL END-OF-LINE
  357.           MVI    M,LF           ;STORE A LINE FEED AFTER CR
  358.           INX    H
  359.           JMP    TEXT           ;LOOP
  360.  TEXT2:   POP    H              ;CLEAR STACK AND RETURN
  361.           RET
  362.  
  363. ;;        MOVE - RM80 MOVE COMMAND
  364.  
  365.  MOVE:    CALL   DIFF           ;DE = DE-HL+1
  366.           INX    D
  367.           PUSH   D
  368.           PUSH   H
  369.           LXI    H,MOVES1       ;PRINT 'TO?'
  370.           CALL   WASC
  371.           LXI    H,IBUF         ;READ RESPONSE
  372.           CALL   RASC
  373.           LXI    D,IBUF         ;DECODE VALUE
  374.           CALL   DHS
  375.           JNC    MOVE0          ;JUMP IF NO ERRORS
  376.           POP    H
  377.           POP    D
  378.           JMP    PERR
  379.  MOVE0:   XCHG                  ;DE = BC = FWA DEST.
  380.           MOV    B,D
  381.           MOV    C,E
  382.           POP    H              ;HL = FWA SOURCE
  383.           CALL   DIFF           ;DE = FWA DEST - FWA SOURCE
  384.           POP    D              ;DE = SOURCE SIZE
  385.           JNC    MOVEDN         ;FWA DEST > FWA SOURCE
  386.           JMP    MOVEUP         ;FWA DEST < FWA SOURCE
  387.  
  388.  MOVES1:  DB     'TO? ',0
  389.  
  390. ;;        FILL - RM80 FILL COMMAND
  391.  
  392.  FILL:    CALL   DIFF
  393.           INX    D
  394.           PUSH   H
  395.           PUSH   D
  396.           LXI    H,FILLS1       ;PRINT 'WITH? '
  397.           CALL   WASC
  398.           LXI    H,IBUF         ;READ ANSWER
  399.           CALL   RASC
  400.           LXI    D,IBUF         ;DECODE IT
  401.           CALL   DHS
  402.           JNC    FILL0          ;JUMP IF OK
  403.           POP    D              ;ELSE CLEAR STACK AND TAKE ERROR EXIT
  404.           POP    H
  405.           JMP    PERR
  406.  FILL0:   MOV    B,L            ;B = FILL BYTE
  407.           POP    D
  408.           POP    H
  409.  FILL1:   MOV    A,D            ;RETURN WHEN COUNT=0
  410.           ORA    E
  411.           RZ
  412.           MOV    M,B            ;STORE FILL BYTE
  413.           INX    H
  414.           DCX    D              ;DECREMENT COUNT AND LOOP
  415.           JMP    FILL1
  416.  
  417.  FILLS1:  DB     'WITH? ',0
  418.  
  419. ;;        GO - RM80 GO COMMAND
  420.  
  421.  GO:      PCHL                  ;SHUFFLE OFF TO PARAM1
  422.  
  423. ;;        STORE - RM80 STORE COMMAND
  424.  
  425.  STORE:   CALL   DIFF           ;DE = DE-HL+1
  426.           INX    D
  427.           LDA    TUNIT          ;TURN ON MOTOR
  428.           OUT    CASSTA
  429.           MVI    B,15           ;WAIT 1.5 SECONDS
  430.           CALL   WTS
  431.           MVI    A,3CH          ;WRITE START BYTE
  432.           CALL   CTWBX
  433.           MVI    A,0E6H         ;WRITE SYNC BYTE
  434.           CALL   CTWBX
  435.           MVI    B,0            ;CLEAR CHECKSUM
  436.  STORE1:  MOV    A,M            ;FETCH NEXT BYTE
  437.           INX    H
  438.           CALL   CTWBX          ;WRITE IT
  439.           DCX    D              ;DECREMENT COUNT
  440.           MOV    A,D            ;LOOP UNTIL COUNT=0
  441.           ORA    E
  442.           JNZ    STORE1
  443.           MOV    A,B            ;WRITE CHECKSUM
  444.           CALL   CTWBX
  445.           MVI    B,5            ;WAIT 0.5 SECONDS
  446.           CALL   WTS
  447.           XRA    A              ;TURN OFF MOTOR
  448.           OUT    CASSTA
  449.           RET
  450.  
  451.  CTWBX:   PUSH   PSW            ;AWAIT TBE (INVERTED)
  452.           IN     CASSTA
  453.           ANI    CASTBE
  454.           JNZ    $-4
  455.           POP    PSW
  456.           OUT    CASDAT         ;WRITE BYTE
  457.           CMA                   ;DISPLAY ON LIGHTS
  458.           OUT    0FFH
  459.           CMA
  460.           PUSH   PSW            ;ADD BYTE INTO CHECKSUM
  461.           ADD    B
  462.           MOV    B,A
  463.           POP    PSW
  464.           RET
  465.  
  466. ;;        FETCH - RM80 FETCH COMMAND
  467.  
  468.  FETCH:   CALL   DIFF           ;DE = DE-HL+1
  469.           INX    D
  470.           LDA    TUNIT          ;TURN ON MOTOR AND ENTER HUNT MODE
  471.           ORI    CASEHM
  472.           OUT    CASSTA
  473.           MVI    B,0            ;CLEAR CHECKSUM
  474.  FETCH1:  CALL   CTRBX          ;READ NEXT BYTE
  475.           MOV    M,A            ;STORE IT
  476.           INX    H
  477.           DCX    D              ;DECREMENT COUNT
  478.           MOV    A,D            ;LOOP UNTIL COUNT=0
  479.           ORA    E
  480.           JNZ    FETCH1
  481.  FETCH2:  MOV    C,B            ;SAVE NEW CHECKSUM
  482.           CALL   CTRBX          ;READ OLD ONE
  483.           MOV    B,A
  484.           XRA    A              ;TURN OFF MOTOR
  485.           OUT    CASSTA
  486.           MOV    A,B            ;RETURN IF CHECKSUMS COMPARE GOOD
  487.           CMP    C
  488.           RZ
  489.           LXI    H,FETCHS1      ;ELSE PRINT 'CHECKSUM ERROR'
  490.           JMP    WASC
  491.  
  492.  FETCHS1: DB     'CHECKSUM ERROR',CR,LF,0
  493.  
  494.  CTRBX:   IN     CASSTA         ;AWAIT RDA (INVERTED)
  495.           ANI    CASRDA
  496.           JNZ    $-4
  497.           IN     CASDAT         ;READ BYTE
  498.           CMA                   ;DISPLAY ON LIGHTS
  499.           OUT    0FFH
  500.           CMA
  501.           PUSH   PSW            ;ADD BYTE INTO CHECKSUM
  502.           ADD    B
  503.           MOV    B,A
  504.           POP    PSW
  505.           RET
  506.  
  507. ;;        CHECK - RM80 CHECK COMMAND
  508.  
  509.  CHECK:   CALL   DIFF           ;DE = DE-HL+1
  510.           INX    D
  511.           LDA    TUNIT          ;TURN ON MOTOR AND ENTER HUNT MODE
  512.           ORI    CASEHM
  513.           OUT    CASSTA
  514.           MVI    B,0            ;CLEAR CHECKSUM
  515.  CHECK1:  CALL   CTRBX          ;READ NEXT BYTE
  516.           DCX    D              ;DECREMENT COUNT
  517.           MOV    A,D            ;LOOP UNTIL COUNT=0
  518.           ORA    E
  519.           JNZ    CHECK1
  520.           JMP    FETCH2         ;REST IS SAME AS FETCH
  521.  
  522. ;;        UNIT - RM80 UNIT COMMAND
  523.  
  524.  UNIT:    MOV    A,L
  525.           STA    TUNIT
  526.           RET
  527.  
  528. ;;        SCAN - RM80 SCAN COMMAND
  529.  
  530.  SCAN:    LXI    H,TBUF         ;READ NEXT RECORD
  531.           LXI    B,NBUF
  532.           CALL   CTRR
  533.           CALL   CTPH           ;PRINT HEADER INFO
  534.           MOV    A,D            ;IF END-OF-FILE, SKIP ONE LINE
  535.           CPI    4
  536.           CC     WEOLC
  537.           JMP    SCAN           ;LOOP (EXIT VIA CONSOLE BREAKIN)
  538.  
  539. ;;        WRITE - RM80 WRITE COMMAND
  540.  
  541.  WRITE:   LDA    PFLAG1         ;JUMP IF 1ST PARAM ABSENT
  542.           ORA    A
  543.           RZ
  544.           LDA    PFLAG2         ;JUMP IF 2ND PARAM PRESNT
  545.           ORA    A
  546.           JNZ    WRITE1
  547.           MOV    D,L            ;DE = (PARAM1+1)*256-1 = LWA
  548.           INR    D
  549.           MVI    E,0
  550.           DCX    D
  551.           LXI    H,100H         ;SET DEFAULT FWA
  552.  WRITE1:  CALL   DIFF           ;DE = DE-HL+1 = FILE SIZE
  553.           INX    D
  554.           PUSH   D
  555.           XRA    A              ;PRN = 0
  556.           STA    PRN
  557.           CALL   GFNC           ;GET CP/M FILE NAME FROM CONSOLE
  558.  WRITE2:  MOV    A,D            ;JUMP IF LESS THAN ONE PRU LEFT
  559.           CPI    4
  560.           JC     WRITE3
  561.           PUSH   D              ;SAVE FILE SIZE
  562.           LXI    D,400H         ;SET PHYS REC SIZE
  563.           LXI    B,NBUF         ;POINT TO NAME BUFFER
  564.           CALL   CTWR           ;WRITE FULL PRU
  565.           POP    D              ;RESTORE FILE SIZE
  566.           MOV    A,D            ;DE = DE - 400H
  567.           SUI    4
  568.           MOV    D,A
  569.           JMP    WRITE2
  570.  WRITE3:  LXI    B,NBUF         ;POINT TO NAME BUFFER
  571.           CALL   CTWR           ;WRITE LAST PRU (SHORT)
  572.           POP    D              ;RESTORE FILE SIZE
  573.           MOV    A,D            ;PRINT FILE SIZE IN HEX
  574.           CALL   WHBC
  575.           MOV    A,E
  576.           CALL   WHBC
  577.           LXI    H,WRITES1      ;PRINT 'BYTES WRITTEN' AND EXIT
  578.           JMP    WASC
  579.  
  580.  WRITES1: DB     ' BYTES WRITTEN',CR,LF,0
  581.  
  582. ;;        READ - RM80 READ COMMAND
  583.  
  584.  READ:    PUSH   H
  585.  READ1:   LXI    H,TBUF         ;READ NEXT RECORD
  586.           LXI    B,NBUF
  587.           CALL   CTRR
  588.           CALL   CTPH
  589.           MOV    A,D            ;SAVE PAGE COUNT
  590.           STA    CTPC
  591.           LXI    H,TBUF
  592.  READ2:   MOV    A,D            ;EXIT WHEN COUNT = 0
  593.           ORA    E
  594.           JZ     READ4
  595.           MOV    A,M            ;FETCH NEXT BYTE FROM TBUF
  596.           INX    H
  597.           XTHL
  598.           MOV    M,A            ;STORE AT LOAD ADDRESS
  599.           INX    H              ;INCREMENT LOAD ADDRESS
  600.           XTHL
  601.           DCX    D              ;DECREMENT COUNT
  602.           JMP    READ2
  603.  READ4:   LDA    CTPC           ;FETCH PAGE COUNT
  604.           CPI    4              ;LOOP IF NOT SHORT RECORD
  605.           JNC    READ1
  606.           POP    H              ;CLEAR STACK
  607.           RET
  608.  
  609. ;;        LOAD - RM80 LOAD COMMAND
  610.  
  611.  LOAD:    XRA    A              ;INIT OBJECT FILE LOADER
  612.           STA    OFLST
  613.           STA    OFLCE
  614.           STA    LDERR          ;CLEAR LOADER ERROR COUNT
  615.  LOAD1:   LXI    H,TBUF
  616.           LXI    B,NBUF
  617.           CALL   CTRR           ;READ NEXT RECORD
  618.           CALL   CTPH
  619.           MOV    A,D            ;SAVE PAGE COUNT
  620.           STA    CTPC
  621.           LXI    H,TBUF
  622.  LOAD2:   MOV    A,D            ;EXIT WHEN COUNT=0
  623.           ORA    E
  624.           JZ     LOAD4
  625.           MOV    A,M            ;FETCH NEXT BYTE
  626.           INX    H
  627.           CALL   OFL            ;INVOKE OBJECT FILE LOADER ON BYTE
  628.           LDA    OFLCE          ;JUMP IF NO CHECKSUM ERROR
  629.           ORA    A
  630.           JZ     LOAD3
  631.           LDA    LDERR          ;INCREMENT LOADER ERROR COUNT
  632.           INR    A
  633.           STA    LDERR
  634.           XRA    A              ;RESET CHECKSUM ERROR FLAG
  635.           STA    OFLCE
  636.  LOAD3:   DCX    D              ;DECREMENT COUNT AND LOOP
  637.           JMP    LOAD2
  638.  LOAD4:   LDA    CTPC           ;FETCH PAGE COUNT
  639.           CPI    4              ;LOOP IF NOT SHORT RECORD
  640.           JNC    LOAD1
  641.           LXI    H,LOADS1       ;PRINT 'ERROR COUNT = '
  642.           CALL   WASC
  643.           LDA    LDERR          ;PRINT ERROR COUNT
  644.           CALL   WHBC
  645.           JMP    WEOLC          ;EXIT VIA WEOLC
  646.  
  647.  LOADS1:  DB     'ERROR COUNT = ',0
  648.  
  649. ;;        LINK - RM80 LINK COMMAND
  650.  
  651.  LINK:    XRA    A              ;CLEAR CHAR BUFFERS
  652.           STA    INCH
  653.           STA    OUTCH
  654.           STA    OFLSW          ;START WITH OBJECT FILE LOADER OFF
  655.           STA    TFLSW          ;START WITH TEXT FILE LOADER OFF
  656.           SHLD   TFLFWA         ;SET FWA FOR TEXT FILE LOADER
  657.           SHLD   TFLLWA         ;SET LWA FOR TEXT FILE LOADER
  658.  LINK1:   CALL   CRDAC          ;ANYTHING FROM CONSOLE?
  659.           JNC    LINK2          ;JUMP IF NOT
  660.           CALL   RACC           ;ELSE READ CHAR FROM CONSOLE
  661.           CPI    20H            ;IF CONTROL CODE TYPED, CALL PCC
  662.           CC     PCC
  663.           JC     LINK2          ;JUMP IF CODE PROCESSED
  664.           ORI    80H            ;SAVE IT AWAY FOR LATER
  665.           STA    OUTCH
  666.  LINK2:   CALL   CTBEC          ;CONSOLE READY FOR DATA?
  667.           JNC    LINK3          ;JUMP IF NOT
  668.           LDA    INCH           ;DO WE GOT ANY GOODIES FOR IT?
  669.           ORA    A
  670.           JP     LINK3          ;JUMP IF NOT
  671.           ANI    7FH            ;ELSE WRITE CHAR TO CONSOLE
  672.           CALL   WACC
  673.           XRA    A              ;CLEAR INPUT CHAR BUFFER
  674.           STA    INCH
  675.  LINK3:   CALL   CRDAM          ;ANYTHING FROM MODEM?
  676.           JNC    LINK4          ;JUMP IF NOT
  677.           CALL   RACM           ;ELSE READ CHAR FROM MODEM
  678.           MOV    B,A            ;IF OFL ENABLED, CALL OFL
  679.           LDA    OFLSW
  680.           ORA    A
  681.           MOV    A,B
  682.           JZ     $+12
  683.           PUSH   PSW
  684.           CALL   OFL
  685.           POP    PSW
  686.           CMA
  687.           OUT    0FFH
  688.           CMA
  689.           MOV    B,A            ;IF TFL ENABLED, CALL TFL
  690.           LDA    TFLSW
  691.           ORA    A
  692.           MOV    A,B
  693.           JZ     $+10
  694.           CALL   TFL
  695.           CMA
  696.           OUT    0FFH
  697.           CMA
  698.           ORI    80H            ;SAVE IT AWAY FOR LATER
  699.           STA    INCH
  700.  LINK4:   CALL   CTBEM          ;MODEM READY FOR MORE DATA?
  701.           JNC    LINK5          ;JUMP IF NOT
  702.           LDA    OUTCH          ;DO WE GOT ANY GOODIES FOR IT
  703.           ORA    A
  704.           JP     LINK5          ;JUMP IF NOT
  705.           ANI    7FH            ;ELSE WRITE CHAR TO MODEM
  706.           CALL   WACM
  707.           XRA    A              ;CLEAR OUTPUT CHAR BUFFER
  708.           STA    OUTCH
  709.  LINK5:   JMP    LINK1          ;LOOP
  710.  
  711.  PCC:     CPI    'X'-40H        ;JUMP IF NOT CONTROL-X
  712.           JNZ    PCC1
  713.           POP    H              ;CLEAR STACK AND EXIT
  714.           JMP    WEOLC
  715.  PCC1:    CPI    'O'-40H        ;JUMP IF NOT CTRL-O
  716.           JNZ    PCC2
  717.           MVI    A,1            ;ENABLE OBJECT FILE LOADER
  718.           STA    OFLSW
  719.           STC
  720.           RET
  721.  PCC2:    CPI    'N'-40H        ;JUMP IF NOT CTRL-N
  722.           JNZ    PCC3
  723.           XRA    A              ;DISABLE OBJECT FILE LOADER
  724.           STA    OFLSW
  725.           STC
  726.           RET
  727.  PCC3:    CPI    'R'-40H        ;JUMP IF NOT CTRL-R
  728.           JNZ    PCC4
  729.           MVI    A,1            ;ENABLE TEXT FILE LOADER
  730.           STA    TFLSW
  731.           STC
  732.           RET
  733.  PCC4:    CPI    'Q'-40H        ;JUMP IF NOT CTRL-Q
  734.           JNZ    PCC5
  735.           XRA    A              ;DISABLE TEXT FILE LOADER
  736.           STA    TFLSW
  737.           LHLD   TFLLWA         ;WRITE MEMORY BUFFER TO TAPE
  738.           DCX    H
  739.           XCHG
  740.           LHLD   TFLFWA
  741.           CALL   WRITE1
  742.           STC
  743.           RET
  744.  PCC5:    CPI    'S'-40H        ;JUMP IF NOT CTRL-S
  745.           JNZ    PCC6
  746.           JMP    TFS            ;SEND TEXT FILE (FROM TAPE)
  747.  PCC6:    STC                   ;FESS UP THAT WE DON'T KNOW BOUT THIS ONE
  748.           CMC
  749.           RET
  750.  
  751.  TFL:     ORA    A              ;IGNORE NULLS
  752.           RZ
  753.           PUSH   H
  754.           LHLD   TFLLWA
  755.           MOV    M,A
  756.           INX    H
  757.           SHLD   TFLLWA
  758.           POP    H
  759.           RET
  760.  
  761.  TFS:     LXI    H,TBUF         ;READ NEXT RECORD
  762.           LXI    B,NBUF
  763.           CALL   CTRR
  764.           MOV    A,D
  765.           STA    CTPC
  766.           LXI    H,TBUF
  767.  TFS1:    MOV    A,D            ;EXIT WHEN COUNT=0
  768.           ORA    E
  769.           JZ     TFS3
  770.           MOV    A,M            ;FETCH NEXT CHARACTER
  771.           INX    H
  772.           CPI    'Z'-40H        ;EXIT IF CNTRL-Z
  773.           JZ     TFS4
  774.           ORA    A
  775.           JZ     TFS2
  776.           CPI    LF             ;DO NOT SEND LINE FEEDS
  777.           JZ     TFS2
  778.           CALL   WACM           ;WRITE CHAR TO MODEM
  779.           CALL   WACC           ;WRITE CHAR TO CONSOLE
  780.           CPI    CR             ;JUMP IF NOT CR
  781.           JNZ    TFS2
  782.           CALL   RACM           ;AWAIT LINE FEED
  783.           CPI    LF
  784.           JNZ    $-5
  785.           CALL   WACC           ;ECHO LINE FEED TO CONSOLE
  786.  TFS2:    CALL   CRDAC          ;CHECK FOR CONSOLE BREAKIN
  787.           JNC    $+11           ;JUMP IF NOT PRESENT
  788.           CALL   RACC           ;READ CHARACTER
  789.           CPI    'T'-40H        ;EXIT IF CTRL-T
  790.           JZ     TFS4
  791.           DCX    D              ;DECREMENT COUNT AND LOOP
  792.           JMP    TFS1
  793.  TFS3:    LDA    CTPC           ;FETCH PAGE COUNT
  794.           CPI    4              ;LOOP IF NOT SHORT RECORD
  795.           JNC    TFS
  796.  TFS4:    CALL   WEOLC
  797.           STC
  798.           RET
  799.  
  800. ;;        SOLO - RM80 SOLO COMMAND
  801.  
  802.  SOLO:    SHLD   OFLOS
  803.           RET
  804.  
  805. ;;;       GENERAL PURPOSE UTILITIES
  806. ;
  807. ;         LAWRENCE E. HUGHES III
  808. ;         8080 SOFTWARE DEVELOPMENT CENTER
  809. ;         1506 MYRICK ROAD
  810. ;         TALLAHASSEE, FLORIDA 32303
  811.  
  812. ;;        MOVEUP - MOVE BLOCK OF MEMORY TOWARDS ZERO
  813. ;
  814. ;         ENTRY CONDITIONS
  815. ;            HL........FWA OF SOURCE
  816. ;            BC........FWA OF DEST
  817. ;            DE........NUMBER OF BYTES TO MOVE
  818.  
  819.  MOVEUP:  MOV    A,D
  820.           ORA    E
  821.           RZ
  822.           MOV    A,M
  823.           INX    H
  824.           STAX   B
  825.           INX    B
  826.           DCX    D
  827.           JMP    MOVEUP
  828.  
  829. ;;        MOVEDN - MOVE BLOCK OF MEMORY TOWARDS FFFF
  830. ;
  831. ;         ENTRY CONDITIONS
  832. ;            HL........FWA OF SOURCE
  833. ;            BC........FWA OF DEST
  834. ;            DE........NUMBER OF BYTES TO MOVE
  835.  
  836.  MOVEDN:  DAD    D
  837.           MOV    A,C
  838.           ADD    E
  839.           MOV    C,A
  840.           MOV    A,B
  841.           ADC    D
  842.           MOV    B,A
  843.  MOVEDN1: MOV    A,D
  844.           ORA    E
  845.           RZ
  846.           DCX    H
  847.           MOV    A,M
  848.           DCX    B
  849.           STAX   B
  850.           DCX    D
  851.           JMP    MOVEDN1
  852.  
  853. ;;        PERR - PRINT 'ERROR'
  854.  
  855.  PERR:    LXI    H,PERRS1
  856.           JMP    WASC
  857.  
  858.  PERRS1:  DB     'ERROR',CR,LF,0
  859.  
  860. ;;        DIFF - DE = DE - HL
  861.  
  862.  DIFF:    MOV    A,E
  863.           SUB    L
  864.           MOV    E,A
  865.           MOV    A,D
  866.           SBB    H
  867.           MOV    D,A
  868.           RET
  869.  
  870. ;;        GFNC - GET FILE NAME FROM CONSOLE
  871.  
  872.  GFNC:    PUSH   H
  873.           PUSH   D
  874.           CALL   WEOLC
  875.           LXI    H,GFNS1        ;PRINT 'FILENAME?'
  876.           CALL   WASC
  877.           LXI    H,IBUF         ;READ RESPONSE INTO IBUF
  878.           CALL   RASC
  879.           LXI    D,IBUF         ;DECODE FILE NAME INTO NBUF
  880.           LXI    H,NBUF
  881.           CALL   DFN
  882.           POP    D
  883.           POP    H
  884.           RET
  885.  
  886.  GFNS1:   DB     'FILENAME? ',0
  887.  
  888. ;;        DFN - DECODE FILE NAME (CP/M FORMAT)
  889. ;
  890. ;         ENTRY CONDITIONS
  891. ;            DE........FWA OF STRING TO DECODE
  892. ;            HL........FWA OF BUFFER TO ACCEPT DECODED FILENAME
  893. ;
  894. ;         EXIT CONDITIONS
  895. ;            C-FLAG....SET IFF ERRORS OCCURRED (FIELD TOO LONG)
  896.  
  897.  DFN:     MVI    C,9            ;DECODE NAME FIELD
  898.  DFN1:    LDAX   D              ;FETCH NEXT BYTE FROM STRING
  899.           INX    D
  900.           CPI    61H            ;IF LC, CONVERT TO UC
  901.           JC     $+5
  902.           SUI    20H
  903.           CPI    CR             ;JUMP IF END OF STRING
  904.           JZ     DFN2
  905.           CPI    ' '            ;JUMP IF END OF FIELD
  906.           JZ     DFN2
  907.           CPI    '.'            ;JUMP IF END OF NAME
  908.           JZ     DFN2
  909.           DCR    C              ;EXIT IF NAME TOO LONG
  910.           JZ     DFNX
  911.           MOV    M,A            ;STORE BYTE IN NAME FIELD OF BUFFER
  912.           INX    H
  913.           JMP    DFN1           ;LOOP
  914.  DFN2:    DCR    C              ;BLANK FILL REST OF NAME FIELD OF BUFFER
  915.           JZ     DFN3
  916.           MVI    M,' '
  917.           INX    H
  918.           JMP    DFN2
  919.  DFN3:    MVI    C,4
  920.           CPI    '.'            ;JUMP IF NO TYPE FIELD IN STRING
  921.           JNZ    DFN5
  922.  DFN4:    LDAX   D              ;FETCH NEXT BYTE FROM STRING
  923.           INX    D
  924.           CPI    61H            ;IF LC, CONVERT TO UC
  925.           JC     $+5
  926.           SUI    20H
  927.           CPI    CR             ;JUMP IF END OF STRING
  928.           JZ     DFN5
  929.           CPI    ' '            ;JUMP IF END OF FIELD
  930.           JZ     DFN5
  931.           DCR    C              ;EXIT IF TYPE TOO LONG
  932.           JZ     DFNX
  933.           MOV    M,A            ;STORE BYTE IN TYPE FIELD OF BUFFER
  934.           INX    H
  935.           JMP    DFN4           ;LOOP
  936.  DFN5:    DCR    C              ;BLANK FILL REST OF TYPE FIELD OF BUFFER
  937.           JZ     DFN6
  938.           MVI    M,' '
  939.           INX    H
  940.           JMP    DFN5
  941.  DFN6:    STC                   ;NORMAL EXIT
  942.           CMC
  943.           RET
  944.  DFNX:    STC                   ;ERROR EXIT
  945.           RET
  946.  
  947. ;;        OFL - INTEL HEX OBJECT FILE LOADER (FINITE STATE MACHINE)
  948. ;
  949. ;         ENTRY CONDITIONS
  950. ;            A.........OBJECT FILE BYTE
  951. ;            OFLST.....STATE COUNTER (INIT BY USER TO ZERO)
  952. ;            OFLLA.....LOAD ADDRESS
  953. ;            OFLBC.....BYTE COUNT
  954. ;            OFLCS.....CHECKSUM
  955. ;            OFLCE.....CHECKSUM ERROR - INIT BY USER TO ZERO
  956. ;                      SET NON-ZERO IF ERROR OCCURS, MUST BE
  957. ;                      RE-CLEARED TO ZERO BY USER
  958.  
  959.  OFL:     PUSH   PSW
  960.           LDA    OFLST          ;JUMP IF STATE >= 1
  961.           CPI    1
  962.           JNC    OFL1
  963.           POP    PSW
  964.           CPI    ':'            ;IGNORE ALL CHARS UNTIL COLON FOUND
  965.           RNZ
  966.           MVI    A,1            ;ADVANCE TO STATE 1
  967.           STA    OFLST
  968.           XRA    A              ;CLEAR CHECKSUM
  969.           STA    OFLCS
  970.           RET
  971.  
  972.  OFL1:    CPI    2              ;JUMP IF STATE >= 2
  973.           JNC    OFL2
  974.           INR    A
  975.           STA    OFLST
  976.           CALL   OFLCB          ;CLEAR BYTE BUFFER
  977.           POP    PSW
  978.           JMP    OFLAD          ;ACCUM. 1ST DIGIT OF BYTE COUNT
  979.  
  980.  OFL2:    CPI    3              ;JUMP IF STATE >= 3
  981.           JNC    OFL3
  982.           INR    A
  983.           STA    OFLST
  984.           POP    PSW
  985.           CALL   OFLAD          ;ACCUM. 2ND DIGIT OF BYTE COUNT
  986.           STA    OFLBC          ;SAVE RESULT AS BYTE COUNT
  987.           JMP    OFLUC          ;ADD RESULT INTO CHECKSUM
  988.  
  989.  OFL3:    CPI    4              ;JUMP IF STATE >= 4
  990.           JNC    OFL4
  991.           INR    A
  992.           STA    OFLST
  993.           CALL   OFLCB          ;CLEAR BYTE BUFFER
  994.           POP    PSW
  995.           JMP    OFLAD          ;ACCUM. 1ST DIGIT OF HI ADDR
  996.  
  997.  OFL4:    CPI    5              ;JUMP IF STATE >= 5
  998.           JNC    OFL5
  999.           INR    A
  1000.           STA    OFLST
  1001.           POP    PSW
  1002.           CALL   OFLAD          ;ACCUM 2ND DIGIT OF HI ADDR
  1003.           STA    OFLLA+1        ;SAVE HI BYTE OF LOAD ADDRESS
  1004.           JMP    OFLUC          ;ADD RESULT INTO CHECKSUM
  1005.  
  1006.  OFL5:    CPI    6              ;JUMP IF STATE >= 6
  1007.           JNC    OFL6
  1008.           INR    A
  1009.           STA    OFLST
  1010.           CALL   OFLCB          ;CLEAR BYTE BUFFER
  1011.           POP    PSW            ;ACCUM. 1ST DIGIT OF LO ADDR
  1012.           JMP    OFLAD
  1013.  
  1014.  OFL6:    CPI    7              ;JUMP IF STATE >= 7
  1015.           JNC    OFL7
  1016.           INR    A
  1017.           STA    OFLST
  1018.           POP    PSW
  1019.           CALL   OFLAD          ;ACCUM. 2ND DIGIT OF LO ADDR
  1020.           STA    OFLLA          ;SAVE LO BYTE OF LOAD ADDRESS
  1021.           PUSH   H
  1022.           PUSH   D
  1023.           LHLD   OFLLA          ;ADD IN OFFSET
  1024.           XCHG
  1025.           LHLD   OFLOS
  1026.           DAD    D
  1027.           SHLD   OFLLA
  1028.           POP    D
  1029.           POP    H
  1030.           JMP    OFLUC          ;ADD RESULT INTO CHECKSUM
  1031.  
  1032.  OFL7:    CPI    9              ;JUMP IF STATE >= 9
  1033.           JNC    OFL8
  1034.           INR    A
  1035.           STA    OFLST
  1036.           POP    PSW            ;IGNORE NEXT DIGIT OF REC TYPE
  1037.           RET
  1038.  
  1039.  OFL8:    CPI    10             ;JUMP IF STATE >= 10
  1040.           JNC    OFL10
  1041.           INR    A
  1042.           STA    OFLST
  1043.           LDA    OFLBC          ;EXIT IF BYTE COUNT = 0
  1044.           ORA    A
  1045.           JZ     OFL9
  1046.           CALL   OFLCB          ;CLEAR BYTE BUFFER
  1047.           POP    PSW
  1048.           JMP    OFLAD          ;ACCUM. 1ST DIGIT OF NEXT DATA BYTE
  1049.  
  1050.  OFL9:    MVI    A,11           ;SET STATE TO 12 (ALL DATA BYTES READ)
  1051.           STA    OFLST
  1052.           JMP    OFL11
  1053.  
  1054.  OFL10:   CPI    11             ;JUMP IF STATE >= 11
  1055.           JNC    OFL11
  1056.           DCR    A
  1057.           STA    OFLST
  1058.           POP    PSW
  1059.           CALL   OFLAD          ;ACCUM. 2ND DIGIT OF NEXT DATA BYTE
  1060.           PUSH   H              ;LOAD BYTE AT LOAD ADDRESS
  1061.           LHLD   OFLLA
  1062.           MOV    M,A
  1063.           INX    H              ;INCREMENT LOAD ADDRESS
  1064.           SHLD   OFLLA
  1065.           POP    H
  1066.           CALL   OFLUC          ;ADD BYTE INTO CHECKSUM
  1067.           LDA    OFLBC          ;DECREMENT BYTE COUNT
  1068.           DCR    A
  1069.           STA    OFLBC
  1070.           RET
  1071.  
  1072.  OFL11:   CPI    12             ;JUMP IF STATE >= 12
  1073.           JNC    OFL12
  1074.           INR    A
  1075.           STA    OFLST
  1076.           CALL   OFLCB          ;CLEAR BYTE BUFFER
  1077.           POP    PSW
  1078.           JMP    OFLAD          ;ACCUM. 1ST DIGIT OF CHECKSUM
  1079.  
  1080.  OFL12:   POP    PSW
  1081.           CALL   OFLAD          ;ACCUM. 2ND DIGIT OF CHECKSUM
  1082.           CALL   OFLUC          ;ADD INTO NEW CHECKSUM (SHOULD YIELD ZERO)
  1083.           STA    OFLCE          ;STORE RESULT AS CHECKSUM ERROR FLAG
  1084.           XRA    A              ;RETURN TO STATE ZERO
  1085.           STA    OFLST
  1086.           RET
  1087.  
  1088. ;;        OFLCB - CLEAR BYTE BUFFER
  1089.  
  1090.  OFLCB:   XRA    A
  1091.           STA    OFLBB
  1092.           RET
  1093.  
  1094. ;;        OFLAD - ACCUMULATE (HEX) DIGIT
  1095.  
  1096.  OFLAD:   SUI    '0'            ;SUBTRACT ASCII BIAS
  1097.           CPI    10             ;JUMP IF 0-9
  1098.           JC     $+5
  1099.           SUI    7              ;ADJUST A-F
  1100.           PUSH   B
  1101.           MOV    B,A
  1102.           LDA    OFLBB          ;FETCH BYTE BUFFER
  1103.           ADD    A              ;MULTIPLY BY 16
  1104.           ADD    A
  1105.           ADD    A
  1106.           ADD    A
  1107.           ADD    B              ;ADD IN NEW DIGIT
  1108.           STA    OFLBB          ;REPLACE RESULT
  1109.           POP    B
  1110.           RET
  1111.  
  1112. ;         OFLUC - UPDATE CHECKSUM
  1113.  
  1114.  OFLUC:   PUSH   H
  1115.           LXI    H,OFLCS        ;POINT TO CHECKSUM
  1116.           ADD    M              ;ADD IN NEW BYTE
  1117.           MOV    M,A
  1118.           POP    H
  1119.           RET
  1120.  
  1121. ;;        DMP - DUMP MEMORY IN HEX AND ASCII TO CONSOLE
  1122. ;
  1123. ;         ENTRY CONDITIONS
  1124. ;            HL........FWA OF BLOCK TO DUMP
  1125. ;            DE........NUMBER OF BYTES TO DUMP
  1126. ;            DMPAD.....ADDR PRINTED AT START OF EACH LINE,
  1127. ;                      INIT BY USER, INCREMENTED BY DMP
  1128.  
  1129.  DMP:     MOV    A,D            ;EXIT VIA WEOLC IF DE=0
  1130.           ORA    E
  1131.           JZ     WEOLC
  1132.           CALL   CRDAC          ;CHECK FOR CONSOLE RDA
  1133.           JNC    DMP0           ;IF NO RDA, JUMP
  1134.           CALL   RACC           ;ELSE DISCARD CHAR TYPED
  1135.           JMP    WEOLC          ;AND EXIT VIA WEOLC
  1136.  DMP0:    CALL   WEOLC          ;START NEW LINE
  1137.           LDA    DMPAD+1        ;WRITE DUMP ADDR IN HEX
  1138.           CALL   WHBC
  1139.           LDA    DMPAD
  1140.           CALL   WHBC
  1141.           PUSH   H              ;SAVE FWA
  1142.           PUSH   D              ;SAVE BYTE COUNT
  1143.           MVI    C,16           ;NUMBER OF BYTES PER LINE
  1144.  DMP1:    MOV    A,D            ;JUMP IF DONE
  1145.           ORA    E
  1146.           JZ     DMP2
  1147.           MVI    A,' '          ;PRINT 1 BLANK
  1148.           CALL   WACC
  1149.           MOV    A,M            ;FETCH NEXT BYTE
  1150.           INX    H
  1151.           CALL   WHBC           ;WRITE TO CONSOLE IN HEX
  1152.           PUSH   H              ;DMPAD = DMPAD + 1
  1153.           LHLD   DMPAD
  1154.           INX    H
  1155.           SHLD   DMPAD
  1156.           POP    H
  1157.           DCX    D              ;DECREMENT COUNT
  1158.           DCR    C              ;CONTINUE UNTIL 16 BYTES DUMPED
  1159.           JNZ    DMP1
  1160.           JMP    DMP3           ;GO DUMP BYTES IN ASCII
  1161.  DMP2:    INR    C              ;EXIT WHEN C=0
  1162.           DCR    C
  1163.           JZ     DMP3
  1164.           MVI    A,' '          ;PRINT 3 SPACES
  1165.           CALL   WACC
  1166.           CALL   WACC
  1167.           CALL   WACC
  1168.           JMP    DMP2+1         ;CONTINUE
  1169.  DMP3:    POP    D              ;RESTORE BYTE COUNT
  1170.           POP    H              ;RESTORE POINTER
  1171.           MVI    A,' '          ;PRINT 2 SPACES
  1172.           CALL   WACC
  1173.           CALL   WACC
  1174.           MVI    C,16           ;NUMBER OF BYTES PER LINE
  1175.  DMP4:    MOV    A,D            ;EXIT VIA WEOLC IF DONE
  1176.           ORA    E
  1177.           JZ     WEOLC
  1178.           MOV    A,M            ;FETCH NEXT BYTE
  1179.           INX    H
  1180.           ANI    7FH            ;DISCARD PARITY BIT
  1181.           CPI    20H            ;SUBSTITUTE PERIOD FOR CTRL CHARS
  1182.           JNC    $+5
  1183.           MVI    A,'.'
  1184.           CPI    7FH
  1185.           JC     $+5
  1186.           MVI    A,'.'
  1187.           CALL   WACC           ;PRINT BYTE IN ASCII
  1188.           DCX    D              ;DECREMENT COUNT
  1189.           DCR    C              ;CONTINUE UNTIL C = 0
  1190.           JNZ    DMP4
  1191.           JMP    DMP            ;PROCEED TO NEXT LINE
  1192.  
  1193. ;;        WHBC - WRITE HEX BYTE TO CONSOLE
  1194. ;
  1195. ;         ENTRY CONDITIONS 
  1196. ;            A.........BYTE TO WRITE IN HEX
  1197.  
  1198.  WHBC:    PUSH   PSW            ;PRINT FIRST DIGIT
  1199.           RRC
  1200.           RRC
  1201.           RRC
  1202.           RRC
  1203.           CALL   WHDC
  1204.           POP    PSW            ;PRINT SECOND DIGIT
  1205.           PUSH   PSW
  1206.           CALL   WHDC
  1207.           POP    PSW
  1208.           RET
  1209.  
  1210. ;;        WHDC - WRITE HEX DIGIT TO CONSOLE
  1211. ;
  1212. ;         ENTRY CONDITIONS
  1213. ;            A.........BITS 3-0 CONTAIN BINARY VALUE OF DIGIT
  1214.  
  1215.  WHDC:    ANI    0FH            ;DISCARD TOP 4 BITS
  1216.           CPI    10             ;ADJUST 10-15
  1217.           JC     $+5
  1218.           ADI    7
  1219.           ADI    '0'            ;CONVERT TO ASCII
  1220.           JMP    WACC           ;GO PRINT DIGIT AND RETURN
  1221.  
  1222. ;;        WEOLC - WRITE END OF LINE TO CONSOLE
  1223.  
  1224.  WEOLC:   PUSH   PSW
  1225.           MVI    A,CR
  1226.           CALL   WACC
  1227.           MVI    A,LF
  1228.           CALL   WACC
  1229.           POP    PSW
  1230.           RET
  1231.  
  1232. ;;        WASC - WRITE ASCII STRING TO CONSOLE
  1233. ;      
  1234. ;         ENTRY CONDITIONS
  1235. ;            HL........FWA OF STRING, TERMINATED BY ZERO BYTE
  1236.  
  1237.  WASC:    MOV    A,M            ;FETCH NEXT BYTE IN STRING
  1238.           INX    H
  1239.           ORA    A              ;RETURN IF END-OF-STRING
  1240.           RZ
  1241.           CALL   WACC           ;PRINT CHAR
  1242.           JMP    WASC
  1243.  
  1244. ;;        WASCX - WRITE ASCII STRING TO CONSOLE
  1245. ;
  1246. ;         ENTRY CONDITIONS
  1247. ;            HL........FWA OF STRING
  1248. ;            B.........NUMBER OF CHARS TO WRITE
  1249.  
  1250.  WASCX:   INR    B
  1251.           DCR    B
  1252.           RZ
  1253.           MOV    A,M
  1254.           INX    H
  1255.           CALL   WACC
  1256.           JMP    WASCX+1
  1257.  
  1258. ;;        RASC - READ ASCII STRING FROM CONSOLE
  1259. ;
  1260. ;         ENTRY CONDITIONS
  1261. ;            HL........FWA OF 128 BYTE BUFFER TO READ INTO
  1262. ;
  1263. ;         EXIT CONDITIONS
  1264. ;            HL........POINTS TO LAST CHAR STORED (CR)
  1265. ;            B.........NUMBER OF BYTES STORED
  1266.  
  1267.  RASC:    PUSH   H              ;SAVE BUFFER POINTER
  1268.           MVI    B,0            ;COUNT = 0
  1269.  RASC1:   CALL   RACC           ;READ NEXT CHAR FROM CONSOLE
  1270.           CPI    'U'-40H        ;JUMP IF NOT CTRL-U
  1271.           JNZ    RASC2
  1272.           CALL   WEOLC          ;ABORT OLD LINE
  1273.           POP    H              ;RESTORE BUFFER POINTER
  1274.           JMP    RASC           ;START OVER
  1275.  RASC2:   CPI    BS
  1276.           JZ     RASC25
  1277.           CPI    DEL
  1278.           JNZ    RASC3
  1279.  RASC25:  INR    B
  1280.           DCR    B
  1281.           JZ     RASC1
  1282.           DCX    H              ;DELETE CHAR
  1283.           DCR    B
  1284.           MVI    A,BS
  1285.           CALL   WACC
  1286.           JMP    RASC1
  1287.  RASC3:   MOV    M,A            ;STORE CHAR IN BUFFER
  1288.           INR    B              ;INCREMENT COUNT
  1289.           MOV    A,B            ;JUMP IF STILL ROOM IN BUFFER
  1290.           ORA    A
  1291.           JP     RASC4
  1292.           MVI    M,CR           ;FORCE A CR INTO LAST BYTE OF BUFFER
  1293.           POP    H              ;RESTORE BUFFER POINTER
  1294.           RET
  1295.  RASC4:   MOV    A,M            ;FETCH CHAR BACK INTO A
  1296.           CPI    CR             ;EXIT IF CHAR = CR
  1297.           JZ     RASC5
  1298.           INX    H              ;NOW INCREMENT BUFFER POINTER
  1299.           CALL   WACC           ;ECHO CHAR TO CONSOLE AND LOOP
  1300.           JMP    RASC1
  1301.  RASC5:   INX    SP             ;CLEAR TOP OF STACK
  1302.           INX    SP
  1303.           JMP    WEOLC
  1304.  
  1305. ;;        DHS - DECODE HEX STRING (TERM. BY BLANK OR CR)
  1306. ;
  1307. ;         ENTRY CONDITIONS
  1308. ;            DE........FWA OF STRING TO DECODE
  1309. ;
  1310. ;         EXIT CONDITIONS
  1311. ;            HL........VALUE OF HEX STRING
  1312. ;            A.........NUMBER OF LEGAL DIGITS FOUND
  1313. ;            DE........POINTS TO LAST CHAR SCANNED
  1314. ;            C-FLAG....SET IFF ERRORS
  1315.  
  1316.  DHS:     LXI    H,0            ;HL = 0
  1317.           PUSH   B
  1318.           MVI    B,0            ;CLEAR 'DIGITS FOUND' COUNT
  1319.  DHS1:    LDAX   D              ;SKIP LEADING BLANKS, IF ANY
  1320.           CPI    CR             ;CHECK FOR END-OF-LINE
  1321.           JZ     DHS5
  1322.           INX    D
  1323.           CPI    ' '
  1324.           JZ     DHS1
  1325.  DHS2:    DAD    H              ;HL = HL * 16
  1326.           DAD    H
  1327.           DAD    H
  1328.           DAD    H
  1329.           CPI    61H            ;IF LC, CONVERT TO UC
  1330.           JC     $+5
  1331.           SUI    20H
  1332.           SUI    '0'            ;CONVERT TO BINARY
  1333.           JC     DHSX
  1334.           CPI    10             ;JUMP IF DIGIT < 10
  1335.           JC     $+5
  1336.           SUI    7              ;ADJUST FOR A-F
  1337.           CPI    16
  1338.           JNC    DHSX
  1339.           ADD    L              ;HL = HL + NEW DIGIT
  1340.           MOV    L,A
  1341.           JNC    $+4
  1342.           INR    H
  1343.           INR    B              ;INCREMENT 'DIGITS FOUND' COUNT
  1344.           LDAX   D
  1345.           CPI    CR
  1346.           JZ     DHS5
  1347.           CPI    ' '
  1348.           JZ     DHS5
  1349.           INX    D
  1350.           JMP    DHS2
  1351.  DHS5:    LDAX   D              ;NORMAL EXIT
  1352.           MOV    A,B
  1353.           POP    B
  1354.           STC
  1355.           CMC
  1356.           RET
  1357.  DHSX:    DCX    D              ;ERROR EXIT
  1358.           LDAX   D
  1359.           POP    B
  1360.           STC
  1361.           RET
  1362.  
  1363. ;;;       CONSOLE DRIVER (IMSAI SIO-2 PORT A)
  1364. ;
  1365. ;         LAWRENCE E. HUGHES III
  1366. ;         8080 SOFTWARE DEVELOPMENT CENTER
  1367. ;         1506 MYRICK ROAD
  1368. ;         TALLAHASSEE, FLORIDA 32303
  1369.  
  1370.  CONDAT   EQU    12H            ;DATA PORT
  1371.  CONSTA   EQU    13H            ;STATUS PORT
  1372.  CONRDA   EQU    02H            ;READ-DATA-AVAILABLE MASK
  1373.  CONTBE   EQU    01H            ;TRANSMIT-BUFFER-EMPTY MASK
  1374.  
  1375. ;;        RACC - READ ASCII CHAR FROM CONSOLE
  1376. ;
  1377. ;         EXIT CONDITIONS
  1378. ;            A.........7-BIT ASCII CHARACTER (D7=0)
  1379.  
  1380.  RACC:    CALL   CRDAC          ;LOOP UNTIL CONSOLE RDA OCCURS
  1381.           JNC    $-3
  1382.           IN     CONDAT         ;READ DATA BYTE
  1383.           ANI    7FH            ;CLEAR TOP BIT
  1384.           RET
  1385.  
  1386. ;;        CRDAC - CHECK FOR RDA ON CONSOLE
  1387. ;
  1388. ;         EXIT CONDITIONS
  1389. ;            C-FLAG....SET IFF RDA OCCURED
  1390.  
  1391.  CRDAC:   IN     CONSTA         ;READ STATUS PORT
  1392.           ANI    CONRDA         ;MASK OFF RDA FLAG
  1393.           JZ     $+5            ;JUMP IF NOT PRESENT
  1394.           STC                   ;ELSE SET CARRY AND RETURN
  1395.           RET
  1396.           STC                   ;CLEAR CARRY AND RETURN
  1397.           CMC
  1398.           RET
  1399.  
  1400. ;;        WACC - WRITE ASCII CHARACTER TO CONSOLE
  1401. ;
  1402. ;         ENTRY CONDITIONS
  1403. ;            A.........ASCII CHARACTER TO WRITE
  1404.  
  1405.  WACC:    PUSH   PSW            ;SAVE CHAR
  1406.           CALL   CTBEC          ;LOOP UNTIL CONSOLE TBE OCCURS
  1407.           JNC    $-3
  1408.           POP    PSW            ;RESTORE CHAR
  1409.           OUT    CONDAT         ;WRITE CHAR AND RETURN
  1410.           RET
  1411.  
  1412. ;;        CTBEC - CHECK FOR TBE ON CONSOLE
  1413. ;
  1414. ;         EXIT CONDITIONS
  1415. ;            C-FLAG...SET IF TBE OCCURRED
  1416.  
  1417.  CTBEC:   IN     CONSTA         ;READ STATUS PORT
  1418.           ANI    CONTBE         ;MASK OFF TBE FLAG
  1419.           JZ     $+5            ;JUMP IF NOT PRESENT
  1420.           STC                   ;ELSE SET CARRY AND RETURN
  1421.           RET
  1422.           STC                   ;CLEAR CARRY AND RETURN
  1423.           CMC
  1424.           RET
  1425.  
  1426. ;;        INITC - INITIALIZE CONSOLE PORT
  1427.  
  1428.  INITC:   XRA    A              ;CLEAR USART
  1429.           OUT    CONSTA
  1430.           OUT    CONSTA
  1431.           OUT    CONSTA
  1432.           MVI    A,40H          ;DO AN INTERNAL RESET
  1433.           OUT    CONSTA
  1434.           MVI    A,6EH          ;SELECT ASYNC, ETC
  1435.           OUT    CONSTA
  1436.           MVI    A,27H          ;ISSUE CTS, DSR, ENABLE RX AND TX
  1437.           OUT    CONSTA
  1438.           IN     CONDAT         ;CLEAR READ BUFFERS IN CHIP
  1439.           IN     CONDAT
  1440.           RET
  1441.  
  1442. ;;;       MODEM DRIVER (IMSAI SIO-2 PORT B)
  1443. ;
  1444. ;         LAWRENCE E. HUGHES III
  1445. ;         8080 SOFTWARE DEVELOPMENT CENTER
  1446. ;         1506 MYRICK ROAD
  1447. ;         TALLAHASSEE, FLORIDA 32303
  1448.  
  1449.  MODDAT   EQU    14H            ;DATA PORT
  1450.  MODSTA   EQU    15H            ;STATUS PORT
  1451.  MODRDA   EQU    02H            ;READ-DATA AVAILABLE MASK
  1452.  MODTBE   EQU    01H            ;TRANSMIT-BUFFER-EMPTY MASK
  1453.  
  1454. ;;        RACM - READ ASCII CHAR FROM MODEM
  1455. ;
  1456. ;         EXIT CONDITIONS
  1457. ;            A.........7-BIT ASCII CHARACTER (D7 = 0)
  1458.  
  1459.  RACM:    CALL   CRDAM          ;LOOP UNTIL MODEM RDA OCCURS
  1460.           JNC    $-3
  1461.           IN     MODDAT         ;READ DATA BYTE
  1462.           ANI    7FH            ;CLEAR TOP BIT
  1463.           RET
  1464.  
  1465. ;;        CRDAM - CHECK FOR RDA ON MODEM
  1466. ;
  1467. ;         EXIT CONDITIONS
  1468. ;            C-FLAG....SET IFF RDA OCCURRED
  1469.  
  1470.  CRDAM:   IN     MODSTA         ;READ STATUS PORT
  1471.           ANI    MODRDA         ;MASK IFF RDA FLAG
  1472.           JZ     $+5            ;JUMP IF NOT PRESENT
  1473.           STC                   ;ELSE SET CARRY FLAG AND RETURN
  1474.           RET
  1475.           STC                   ;CLEAR CARRY AND RETURN
  1476.           CMC
  1477.           RET
  1478.  
  1479. ;;        WACM - WRITE ASCII CHARACTER TO MODEM
  1480. ;
  1481. ;         ENTRY CONDITIONS
  1482. ;            A.........ASCII CHAR TO WRITE
  1483.  
  1484.  WACM:    PUSH   PSW            ;SAVE CHAR
  1485.           CALL   CTBEM          ;LOOP UNTIL MODEM TBE OCCURS
  1486.           JNC    $-3
  1487.           POP    PSW            ;RESTORE CHAR
  1488.           OUT    MODDAT         ;WRITE CHAR AND RETURN
  1489.           RET
  1490.  
  1491. ;;        CTBEM - CHECK FOR TBE ON MODEM
  1492. ;
  1493. ;         EXIT CONDITIONS
  1494. ;            C-FLAG....SET IFF TBE OCCURRED
  1495.  
  1496.  CTBEM:   IN     MODSTA         ;READ STATUS PORT
  1497.           ANI    MODTBE         ;MASK OFF TBE FLAG
  1498.           JZ     $+5            ;JUMP IF NOT PRESENT
  1499.           STC                   ;ELSE SET CARRY FLAG AND RETURN
  1500.           RET
  1501.           STC                   ;CLEAR CARRY FLAG AND RETURN
  1502.           CMC
  1503.           RET
  1504.  
  1505. ;;        INITM - INITIALIZE MODEM PORT
  1506.  
  1507.  INITM:   XRA    A              ;CLEAR USART
  1508.           OUT    MODSTA
  1509.           OUT    MODSTA
  1510.           OUT    MODSTA
  1511.           MVI    A,40H          ;DO AN INTERNAL RESET
  1512.           OUT    MODSTA
  1513.           MVI    A,6EH           ;SELECT ASYNC, ETC.
  1514.           OUT    MODSTA
  1515.           MVI    A,27H           ;ISSUE RTS, DSR, ENABLE RX AND TX
  1516.           OUT    MODSTA
  1517.           IN     MODDAT         ;CLEAR READ BUFFERS IN CHIP
  1518.           IN     MODDAT
  1519.           RET
  1520.  
  1521. ;;;       CASSETTE TAPE DRIVER (MODIFIED TARBELL INTERFACE)
  1522. ;
  1523. ;         LAWRENCE E. HUGHES III
  1524. ;         8080 SOFTWARE DEVELOPMENT CENTER
  1525. ;         1506 MYRICK ROAD
  1526. ;         TALLAHASSEE, FLORIDA 32303
  1527.  
  1528.  CASDAT   EQU    6FH            ;DATA PORT
  1529.  CASSTA   EQU    6EH            ;STATUS PORT
  1530.  CASRDA   EQU    10H            ;READ-DATA-AVAILABLE MASK (INVERTED)
  1531.  CASTBE   EQU    20H            ;TRANSMIT-BUFFER-EMPTY MASK (INVERTED)
  1532.  CASEHM   EQU    10H            ;ENTER HUNT MODE COMMAND
  1533.  CASCRC   EQU    8005H          ;CRC POLYNOMIAL (CRC-16)
  1534.  
  1535. ;;        INITT - INITIALIZE TAPE INTERFACE
  1536.  
  1537.  INITT:   XRA    A
  1538.           OUT    CASSTA
  1539.           MVI    A,1            ;DEFAULT TO TAPE UNIT 1
  1540.           STA    TUNIT
  1541.           RET
  1542.  
  1543. ;;        CTRR - READ PHYSICAL RECORD FROM CASSETTE TAPE
  1544. ;
  1545. ;         ENTRY CONDITIONS
  1546. ;            HL........ADDR OF BUFFER TO ACCEPT DATA
  1547. ;            BC........ADDR OF 11 BYTE BUFFER TO ACCEPT FILENAME
  1548. ;            TUNIT.....UNIT NO. SPECIFIER (1 OR 2)
  1549. ;
  1550. ;         EXIT CONDITIONS
  1551. ;            DE........PHYSICAL RECORD SIZE (BYTES)
  1552. ;            PRN.......PHYSICAL RECORD NUMBER
  1553. ;            C-FLAG....SET MEANS READ ERROR OCCURRED
  1554.  
  1555.  CTRR:    LDA    TUNIT          ;GET UNIT NUMBER
  1556.           ORI    CASEHM         ;OR IN HUNT MODE BIT
  1557.           OUT    CASSTA         ;TURN ON SELECTED UNIT'S MOTOR
  1558.           CALL   CTRB           ;READ BYTE FROM TABLE
  1559.           JC     RM80           ;EXIT ON CONSOLE BREAKIN
  1560.           CPI    SOH            ;LOOP IF NOT SOH (NOISE)
  1561.           JNZ    CTRR
  1562.  CTRR1:   PUSH   H              ;SAVE BUFFER ADDR
  1563.           LXI    H,0            ;CLEAR CRC
  1564.           SHLD   CRC
  1565.           MOV    H,B            ;READ FILENAME INTO BUFFER
  1566.           MOV    L,C
  1567.           LXI    D,11
  1568.           CALL   CTRS
  1569.           CALL   CTRB           ;READ PHYSICAL RECORD NUMBER INTO PRN
  1570.           STA    PRN
  1571.           CALL   CTRB           ;READ PHYSICAL RECORD SIZE INTO DE
  1572.           MOV    D,A
  1573.           CALL   CTRB
  1574.           MOV    E,A
  1575.           CALL   CTRB           ;ERROR EXIT IF NEXT BYTE NOT STX
  1576.           CPI    STX
  1577.           JNZ    CTRR2
  1578.           POP    H              ;RESTORE DATA BUFFER ADDR
  1579.           PUSH   D              ;SAVE PHYS REC SIZE
  1580.           CALL   CTRS           ;READ DATA BYTES
  1581.           CALL   CTRB           ;ERROR EXIT IF NEXT BYTE NOT ETX
  1582.           CPI    ETX
  1583.           JNZ    CTRR2
  1584.           CALL   CTRB           ;READ TAPE CRC
  1585.           CALL   CTRB
  1586.           LHLD   CRC            ;OUR CRC SHOULD NOW BE ZERO
  1587.           MOV    A,H
  1588.           ORA    L
  1589.           JNZ    CTRR2
  1590.           POP    D              ;RESTORE PHYS REC SIZE
  1591.           XRA    A              ;TURN OFF MOTOR
  1592.           OUT    CASSTA
  1593.           STC                   ;CLEAR ERROR FLAG AND RETURN
  1594.           CMC
  1595.           RET
  1596.  CTRR2:   POP    D              ;RESTORE PHYS REC SIZE
  1597.           XRA    A              ;TURN OFF MOTOR
  1598.           OUT    CASSTA
  1599.           STC                   ;SET ERROR FLAG AND RETURN
  1600.           RET
  1601.  
  1602. ;;        CTRS - READ STRING FROM CASSETTE TAPE
  1603. ;
  1604. ;         ENTRY CONDITIONS
  1605. ;            HL........FWA TO READ INTO
  1606. ;            DE........NUMBER OF BYTES TO READ
  1607.  
  1608.  CTRS:    MOV    A,D            ;RETURN IF COUNT=0
  1609.           ORA    E
  1610.           RZ
  1611.           CALL   CTRB           ;READ NEXT BYTE
  1612.           JC     RM80           ;EXIT ON CONSOLE BREAKIN
  1613.           MOV    M,A            ;STORE IN MEMORY
  1614.           INX    H
  1615.           DCX    D              ;DECREMENT COUNT AND LOOP
  1616.           JMP    CTRS
  1617.  
  1618. ;;        CTRB - READ BYTE FROM CASSETTE TAPE
  1619. ;
  1620. ;         EXIT CONDITIONS
  1621. ;            C-FLAG....SET IFF CONSOLE BREAKIN
  1622.  
  1623.  CTRB:    CALL   CRDAC          ;EXIT ON CONSOLE BREAKIN
  1624.           RC
  1625.           IN     CASSTA         ;CHECK FOR RDA (INVERTED)
  1626.           ANI    CASRDA
  1627.           JNZ    CTRB
  1628.           IN     CASDAT         ;READ BYTE
  1629.           CMA                   ;DISPLAY ON LIGHTS
  1630.           OUT    0FFH
  1631.           CMA
  1632.           JMP    UCRC           ;UPDATE CRC AND RETURN
  1633.  
  1634. ;;        CTWR - WRITE PHYSICAL RECORD TO CASSETTE TAPE
  1635. ;
  1636. ;         ENTRY CONDITIONS
  1637. ;            TUNIT.....UNIT NUMBER TO WRITE TO
  1638. ;            HL........ADDR OF BUFFER TO BE WRITTEN
  1639. ;            DE........NUMBER OF BYTES TO WRITE (PHYS REC SIZE)
  1640. ;            PRN.......PHYSICAL RECORD NUMBER (INIT TO ZERO BY USER,
  1641. ;                      INCREMENTED BY CTWR AUTOMATICALLY)
  1642. ;            BC........ADDR OF BUFFER CONTAINING FILENAME
  1643.  
  1644.  CTWR:    PUSH   H              ;SAVE DATA BUFFER ADDR
  1645.           PUSH   D              ;SAVE PHYS REC SIZE
  1646.           PUSH   B              ;SAVE FILENAME BUFFER ADDR
  1647.           LDA    TUNIT          ;TURN ON MOTOR
  1648.           OUT    CASSTA
  1649.           MVI    B,15           ;WAIT 1.5 SECONDS
  1650.           CALL   WTS
  1651.           MVI    A,3CH          ;WRITE START BYTE
  1652.           CALL   CTWB
  1653.           MVI    A,0E6H         ;WRITE SYNC BYTE
  1654.           CALL   CTWB
  1655.           MVI    A,SOH          ;WRITE SOH
  1656.           CALL   CTWB
  1657.           LXI    H,0            ;CLEAR CRC
  1658.           SHLD   CRC
  1659.           POP    H              ;RESTORE FILENAME BUFFER ADDR
  1660.           LXI    D,11           ;WRITE FILENAME TO TAPE
  1661.           CALL   CTWS
  1662.           LDA    PRN            ;WRITE PHYSICAL RECORD NUMBER
  1663.           CALL   CTWB
  1664.           INR    A              ;INCREMENT PRN
  1665.           STA    PRN
  1666.           POP    D              ;RESTORE PHYS REC SIZE
  1667.           MOV    A,D            ;WRITE PHYS REC SIZE
  1668.           CALL   CTWB
  1669.           MOV    A,E
  1670.           CALL   CTWB
  1671.           MVI    A,STX          ;WRITE STX
  1672.           CALL   CTWB
  1673.           POP    H              ;RESTORE BUFFER POINTER
  1674.           PUSH   D              ;SAVE PHYS REC SIZE
  1675.           CALL   CTWS           ;WRITE DATA BYTES
  1676.           MVI    A,ETX          ;WRITE ETX
  1677.           CALL   CTWB
  1678.           PUSH   H              ;SAVE THE UPDATED BUFFER POINTER
  1679.           LHLD   CRC            ;WRITE CRC WE'VE BEEN CREATING
  1680.           MOV    A,H
  1681.           CALL   CTWB
  1682.           MOV    A,L
  1683.           CALL   CTWB
  1684.           POP    H              ;RESTORE THE UPDATED BUFFER POINTER
  1685.           XRA    A              ;SEND A NULL
  1686.           CALL   CTWB
  1687.           POP    D              ;RESTORE PHYS REC SIZE
  1688.           XRA    A              ;TURN OFF MOTOR
  1689.           OUT    CASSTA
  1690.           MVI    B,5            ;WAIT 0.5 SECONDS AND RETURN
  1691.           JMP    WTS
  1692.  
  1693. ;;        CTWS - WRITE STRING TO CASSETTE TAPE
  1694. ;
  1695. ;         ENTRY CONDITIONS
  1696. ;            HL........FWA OF STRING TO WRITE
  1697. ;            DE........NUMBER OF BYTES TO WRITE
  1698.  
  1699.  CTWS:    MOV    A,D            ;RETURN IF COUNT = 0
  1700.           ORA    E
  1701.           RZ
  1702.           MOV    A,M            ;FETCH NEXT BYTE
  1703.           INX    H
  1704.           CALL   CTWB           ;WRITE IT
  1705.           DCX    D              ;DECREMENT COUNT AND LOOP
  1706.           JMP    CTWS
  1707.  
  1708. ;;        CTWB - WRITE BYTE TO CASSETTE TAPE
  1709. ;
  1710. ;         ENTRY CONDITIONS
  1711. ;            A.........BYTE TO WRITE
  1712.  
  1713.  CTWB:    PUSH   PSW
  1714.           IN     CASSTA         ;AWAIT TBE (INVERTED)
  1715.           ANI    CASTBE
  1716.           JNZ    $-4
  1717.           POP    PSW
  1718.           OUT    CASDAT         ;WRITE BYTE
  1719.           CMA                   ;DISPLAY ON LIGHTS, FALL THRU TO UCRC
  1720.           OUT    0FFH
  1721.           CMA
  1722.           JMP    UCRC
  1723.  
  1724. ;;        CTPH - PRINT HEADER INFO
  1725.  
  1726.  CTPH:    PUSH   H
  1727.           PUSH   B
  1728.           PUSH   PSW
  1729.           LXI    H,CTPHS1       ;PRINT 'NAME = '
  1730.           CALL   WASC
  1731.           LXI    H,NBUF         ;PRINT NAME
  1732.           MVI    B,8
  1733.           CALL   WASCX
  1734.           LXI    H,CTPHS2       ;PRINT '  TYPE = '
  1735.           CALL   WASC
  1736.           LXI    H,NBUF+8       ;PRINT TYPE
  1737.           MVI    B,3
  1738.           CALL   WASCX
  1739.           LXI    H,CTPHS3       ;PRINT '  SIZE = '
  1740.           CALL   WASC
  1741.           MOV    A,D            ;PRINT SIZE (IN HEX)
  1742.           CALL   WHBC
  1743.           MOV    A,E
  1744.           CALL   WHBC
  1745.           LXI    H,CTPHS4       ;PRINT '  PRN = '
  1746.           CALL   WASC
  1747.           LDA    PRN            ;PRINT PRN (IN HEX)
  1748.           CALL   WHBC
  1749.           LXI    H,CTPHS5       ;PRINT '  CRC = '
  1750.           CALL   WASC
  1751.           LXI    H,CTPHS6       ;PRINT CRC STATUS
  1752.           POP    PSW
  1753.           PUSH   PSW
  1754.           JNC    $+6
  1755.           LXI    H,CTPHS7
  1756.           CALL   WASC
  1757.           CALL   WEOLC
  1758.           POP    PSW
  1759.           POP    B
  1760.           POP    H
  1761.           RET
  1762.  
  1763.  CTPHS1:  DB     'NAME = ',0
  1764.  CTPHS2:  DB     '    TYPE = ',0
  1765.  CTPHS3:  DB     '    SIZE = ',0
  1766.  CTPHS4:  DB     '    PRN = ',0
  1767.  CTPHS5:  DB     '    CRC = ',0
  1768.  CTPHS6:  DB     'GOOD',0
  1769.  CTPHS7:  DB     'BAD',0
  1770.  
  1771. ;;        UCRC - UPDATE CRC
  1772. ;
  1773. ;         ENTRY CONDITIONS
  1774. ;            A.........NEW DATA BYTE
  1775. ;            CRC.......2 BYTE BUFFER CONTAINING CRC
  1776.  
  1777.  UCRC:    PUSH   PSW            ;SAVE REGS
  1778.           PUSH   B
  1779.           PUSH   D
  1780.           PUSH   H
  1781.           MOV    B,A            ;SAVE DATA BYTE
  1782.           MVI    C,8            ;LOOP COUNT
  1783.  UCRC1:   ANI    80H            ;MASK OFF MSB OF DATA BYTE
  1784.           LHLD   CRC            ;FETCH CRC INTO HL
  1785.           XRA    H              ;XOR MSB OF DATA BYTE INTO CRC
  1786.           MOV    H,A
  1787.           DAD    H              ;LEFT SHIFT CRC 1 BIT
  1788.           JNC    UCRC2          ;JUMP IF NO CARRY
  1789.           MOV    A,H            ;HL = HL XOR CRC POLYNOMIAL
  1790.           XRI    CASCRC SHR 8
  1791.           MOV    H,A
  1792.           MOV    A,L
  1793.           XRI    CASCRC AND 0FFH
  1794.           MOV    L,A
  1795.  UCRC2:   SHLD   CRC            ;REPLACE CRC
  1796.           DCR    C              ;DECREMENT LOOP COUNT
  1797.           JZ     UCRC3          ;EXIT WHEN ENTIRE BYTE PROCESSED
  1798.           MOV    A,B            ;SHIFT DATA BYTE LEFT 1 BIT
  1799.           ADD    A
  1800.           MOV    B,A
  1801.           JMP    UCRC1          ;LOOP
  1802.  UCRC3:   POP    H              ;RESTORE REGS AND RETURN
  1803.           POP    D
  1804.           POP    B
  1805.           POP    PSW
  1806.           STC
  1807.           CMC
  1808.           RET
  1809.  
  1810. ;;        WTS - WAIT TENTHS OF A SECOND
  1811. ;
  1812. ;         ENTRY CONDITIONS
  1813. ;            B - NUMBER OF TENTHS TO WAIT
  1814.  
  1815.  WTS:     INR    B              ;EXIT WHEN B=0
  1816.           DCR    B
  1817.           RZ
  1818.           PUSH   H              ;WAIT ONE TENTH SECOND
  1819.           LXI    H,8330
  1820.  WTS1:    DCX    H
  1821.           MOV    A,H
  1822.           ORA    L
  1823.           JNZ    WTS1
  1824.           POP    H
  1825.           DCR    B              ;DECREMENT COUNT AND LOOP
  1826.           JMP    WTS
  1827.  
  1828.           END
  1829. ERT TO BINARY
  1830.           JC     DHSX
  1831.           CPI    10             ;JUMP IF DIGIT < 10
  1832.           JC     $+5
  1833.           SUI