home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol141 / bbsystem.zq0 / BBSYSTEM.Z80
Encoding:
Text File  |  1985-02-10  |  62.1 KB  |  2,964 lines

  1. ;*************************************************
  2. ;*                         *
  3. ;* BIGBOARD MONITOR ROM, NON-RELOCATABLE VERSION *
  4. ;*        61 K version             *
  5. ;*  Original outline: Russell Smith, 2-Aug-80     *
  6. ;*  Rewritten by Trevor Marshall, Feb-Mar 81     *
  7. ;*    for self-contained WAIT-AID BIOS     *
  8. ;*                         *
  9. ;*************************************************
  10. ;
  11. ;
  12. TRUE    EQU    -1
  13. FALSE    EQU    0
  14. ;
  15. IS5MHZ    EQU    TRUE
  16. ROM:    EQU    FALSE
  17. SIO.POLLED EQU    TRUE
  18. SIO.INTERRUPT EQU NOT SIO.POLLED
  19. PARALLEL EQU    TRUE
  20. SERIAL     EQU    FALSE
  21. CACHE    EQU    TRUE
  22. ;
  23. ROMLOC:    EQU    0F000H        ;START OF 2K ROM
  24. ;
  25.     ORG    ROMLOC-10H    ; at 0 on reset,100 if disk
  26. ;
  27.     DI
  28.  
  29.     IF    NOT ROM
  30.     LD    HL,110H    ;Where the code will be loaded
  31.     ENDIF    ;NOT ROM
  32.  
  33.     IF    ROM
  34.     LD    HL,10H ;Where code is in ROM
  35.     ENDIF    ;ROM
  36.  
  37.     LD    DE,ROMLOC    ;Where we want it put
  38.     LD    BC,0FF0H ;remaining Length of this ROM
  39.             ;and the next
  40.     LDIR
  41.     JP    INIT    ;Initialize all parameters
  42.     NOP        ;To use up 16 bytes
  43. ;
  44. ;************************************************
  45. ;*                        *
  46. ;*   COLD START INITIALIZATION ROUTINE FOR    *
  47. ;*   CONFIGURING THE SYSTEM AFTER A POWER-ON    *
  48. ;*    OR PUSHBUTTON RESET.            *
  49. ;*                18-Oct-80    *
  50. ;*                        *
  51. ;************************************************
  52. ;
  53. ;
  54. ; CP/M Equates
  55. CPMBASE    EQU    0D800H    ;CP/M base address
  56. CCP    EQU    CPMBASE ;CONSOLE COMMAND PROCESSOR
  57. BDOS    EQU    806H+CPMBASE ;OPERATING SYSTEM ENTRY POINT
  58. CBIOS    EQU    1600H+CPMBASE ;BASE OF CUSTOM BIOS
  59.  
  60. ;
  61. ;    -- MONITOR ENTRY POINT TABLE --
  62. ;
  63. ; We need to catch all the external calls to the BIOS
  64. ;   so that we can restore registers upon error
  65. ;   and handle stack imbalance from error control
  66. ; BIOS FUNCTION CALLING TABLE
  67. COLD:    JP    COLDBOOT ;COLD
  68.     JP    WARMBOOT ;WARM
  69.     JP      CPMST     ;CONST
  70.     JP      CPMIN     ;CONIN
  71.     JP      CPMOUT    ;CONOUT
  72.     JP    LIST    ;LIST
  73.     JP      CPMOUT    ;PUNCH
  74.     JP      KBDIN     ;READER
  75.     CALL    BIOSGO    ;HOME
  76.     CALL    BIOSGO    ;SELDSK
  77.     CALL    BIOSGO    ;SETTRK
  78.     JP    SETSEC    ;SETSEC
  79.     JP    SETDMA    ;SETDMA
  80.     CALL    BIOSGO    ;READ
  81.     CALL    BIOSGO    ;WRITE
  82.     JP      LSTST     ;LSTST
  83.     JP      SECTRAN    ;SECTRAN
  84. ; A few extra easily accessible subroutines
  85.     JP    INIT
  86.  
  87.     IF    ROM
  88.     JP    PROMPT
  89.     ENDIF    ;ROM
  90.  
  91. ;Now we need a jump table for the routines
  92. BIOSTBL: JP    COLDBOOT
  93.     JP    WARMBOOT
  94.     JP    CPMST
  95.     JP    CPMIN
  96.     JP    CPMOUT
  97.     JP    LIST
  98.     JP    CPMOUT    ;Punch
  99.     JP    KBDIN    ;Reader
  100.     JP    HOME
  101.     JP    SELECT
  102.     JP    SEEK
  103.     JP    SETSEC
  104.     JP    SETDMA
  105.     JP    READ
  106.     JP    WRITE
  107. ;
  108. BIOSGO:    LD    (HLSAV),HL    ;Save all registers
  109.     LD    (DESAV),DE
  110.     LD    (BCSAV),BC
  111.     POP    HL    ;Get calling address in HL
  112.     LD    A,L    ;Arithmetic with L only is OK
  113.     SUB    A,3    ;Point at start of CALL
  114.     LD    L,A    ;with HL
  115.     LD    (OFFSET),A ;Save function number
  116.     LD    (SPSAV),SP ; Save Stack Pointer at entry
  117.     LD    DE,BIOSTBL-COLD ;Add the table length to first table
  118.     ADD    HL,DE        ;To point to corresponding entry
  119.     LD    (ROUTINE.ADDRESS),HL ;Save it for error rentry
  120.     LD    DE,ERROR.HANDLER ;Fake a return to Error Handler
  121.     PUSH    DE
  122.     LD    DE,(DESAV) ;REstore DE
  123. ; Trying JP(IX) BLEW DEBUG
  124.     JP    (HL)    ;Go to BIOS routine
  125.     
  126.  
  127. ERROR.HANDLER: PUSH    HL ;Save return status, acc.
  128. ;Is error status zero?
  129.     PUSH    AF
  130.     OR    A
  131.     JR    Z,RET9    ;Return if no error indicated
  132.     CALL    PNEXT    ;Output an error message
  133.     DB    0DH,0AH,7,'***** Disk I/O error, trk/sec ',EOT
  134.     LD    A,(TRACK)
  135.     CALL    PUT2HX
  136.     LD    A,'/'
  137.     CALL    CONOUT
  138.     LD    A,(SECTOR)
  139.     CALL    PUT2HX
  140.     CALL    PNEXT
  141.     DB    ', FDC status ',EOT
  142.     POP    AF
  143.     PUSH    AF    ;Get status
  144.     CALL    PUT2HS    ;Put it in HEX
  145.     CALL    CONIN
  146.     AND    5FH    ;LC -> UC
  147.     CP    'R'
  148.     JR    Z,TRYAGAIN
  149.     CP    'I'
  150.     JR    Z,IGNORE
  151. ;Else drop through to RET9 and return error status
  152.     CALL    PNEXT
  153.     DB    'continue',EOT
  154. RET9:
  155. ;If functions return values in HL, trap the HL restore
  156.     POP    AF
  157.     POP    HL    ;get HL
  158.     PUSH    AF    ;acc destroyed below
  159.     LD    A,(OFFSET)
  160.     CP    1BH        ;SELDSK
  161.     JR    EQ,RET10
  162.     LD    HL,(HLSAV)
  163. RET10:    LD    DE,(DESAV)
  164.     LD    BC,(BCSAV)
  165.     POP    AF    ;retrieve accumulator
  166. ;    LD    SP,(SPSAV)
  167.     RET
  168.  
  169. TRYAGAIN: CALL    PNEXT
  170.     DB    'retry',EOT
  171.     LD    A,(TRACK)    ;save TRK #
  172.     LD    HL,PARAM1    ;in scratch
  173.     LD    (HL),A
  174.     INC    HL
  175.     LD    A,(SECTOR)
  176.     LD    (HL),A
  177.     CALL    HOME    ;Recalibrate the drive
  178. ;Disregard any errors here, easier to handle them upon return
  179.     LD    HL,PARAM1
  180.     LD    C,(HL)
  181.     CALL    SEEK
  182.     LD    A,(PARAM1+1)    ;Restore original sector
  183.     LD    (SECTOR),A    ;Effectively CALL SETSEC
  184.     LD    BC,(BCSAV)    ;Restore relevant calling data
  185.     LD    HL,(ROUTINE.ADDRESS)
  186.     LD    SP,(SPSAV)    ;where we began
  187.     LD    DE,ERROR.HANDLER
  188.     PUSH    DE    ;Fake a return to the handler
  189.     JP    (HL)
  190. ;
  191. IGNORE:    CALL    PNEXT
  192.     DB    'ignore',EOT
  193. ;
  194.     POP    AF
  195.     XOR    A    ;make error status = 0 and return
  196.     PUSH    AF
  197.     JR    RET9
  198. ;
  199. ; Indirect call to subroutines, modifying code
  200. CPMOUT:    LD    A,C
  201. CONOUT:    JP    CRTOUT    ;Modified by SWITCH routines
  202. CPMIN:
  203. CONIN:    JP    KBDIN
  204. CPMST:
  205. CONST:    JP    KBDST
  206. ;
  207. LSTST:
  208.     IF    NOT ROM
  209.  
  210.     IN    A,PIOBDAT    ;Is printer busy?
  211.     CPL
  212.     AND    2    ;if LO, busy
  213.     RET    Z    ;if so ret Zero
  214.  
  215.     ENDIF    ;NOT ROM
  216.  
  217.     LD    A,0FFH
  218.     RET
  219. ;
  220. LIST:
  221.     IF    NOT ROM
  222.  
  223.     PUSH    AF
  224. LP1Z:    CALL    LSTST
  225.     JR    Z,LP1Z
  226.     POP    AF
  227.     OUT    PIOADAT,A
  228.     IN    A,PIOBDAT    ;Strobe port B bit 7
  229.     RES    7,A
  230.     OUT    PIOBDAT,A
  231.     SET    7,A
  232.     OUT    PIOBDAT,A
  233.  
  234.     ENDIF    ;NOT ROM
  235.  
  236.     RET
  237. ;
  238. ;The CCP jumps to coldboot if there is an boot error
  239. COLDBOOT: XOR    A
  240.     LD    (0003H),A ;RESET IOBYTE TO ZEROS
  241. ;CCP uses location 4 as a store for user & drive
  242.     LD    (4),A ;Select User 0 & A: on COLDboot
  243.     JR    GOCPM
  244. ;
  245. ;
  246. WARMBOOT: LD    SP,STACK
  247. ; We will select in the CCP ROM by writing
  248. ;  a 1 to port 1C bit 7
  249.     IN    A,(BITDAT)
  250.     SET    7,A
  251.     OUT    (BITDAT),A
  252. ; the PROM is in socket 3, 1000H up
  253.     LD    BC,800H ;move prom contents
  254.     LD    DE,CCP
  255.     LD    HL,1000H
  256.     LDIR
  257. ;
  258.     IN    A,(BITDAT)    ;Deselect PROM
  259.     RES    7,A
  260.     OUT    (BITDAT),A
  261. ;
  262. ;We must zero the bottom bytes of BDOS
  263. ;So that the serial numbers match
  264.     LD    B,6
  265.     XOR    A
  266.     LD    HL,BDOS-6    ;or CPMBASE + 800H
  267. LPP3:    LD    (HL),A
  268.     INC    HL
  269.     DJNZ    LPP3
  270. ;
  271. ;Zero all the allocation vector tables
  272. GOCPM:    LD    BC,VECTORS.LENGTH-1
  273.     LD    DE,ALLOCATION.VECTORS+1
  274.     LD    HL,ALLOCATION.VECTORS
  275.     LD    (HL),A
  276.     LDIR
  277. ; Zero our BIOS logged disks
  278.     CALL    LOGOFF
  279. ;
  280.     LD    A,0C3H    ;STORE JUMP VECTORS IN RAM
  281.     LD    (00H),A
  282.     LD    HL,CBIOS+3 ;JUMP TO CBIOS WARM BOOT AT 00H
  283.     LD    (01H),HL
  284.     LD    (05H),A
  285.     LD    HL,BDOS    ;JUMP TO BDOS GOES AT 05H
  286.     LD    (06H),HL
  287.  
  288.     IF    ROM
  289.     LD    (38H),A
  290.     LD    HL,BKPT  ;JUMP TO Breakpoint GOES AT 38H
  291.     LD    (39H),HL
  292.     ENDIF    ;ROM
  293.  
  294.     LD    HL,FILTER ;Jump to filter replaces that in BDOS
  295.     LD    (BDOS+1),HL
  296.  
  297.     LD    BC,0080H
  298.     CALL    SETDMA     ;MAKE DISK BUFFER=0080H
  299.  
  300. ;The CCP takes in C   | User# | Drive# |
  301.  
  302.     LD    A,(4)    ;Get current user/drive value
  303.     LD    C,A    ;into C for CCP
  304. ;
  305.     JP    CCP
  306. ;
  307. ;
  308. LOGOFF: ;Log off both disks
  309.     LD    HL,UNIT    ;Point to TRKTAB-1
  310.     LD    A,-1    ;'CLEAR' it
  311.     LD    (HL),A
  312.     INC    HL
  313.     LD    (HL),A
  314.     INC    HL
  315.     LD    (HL),A     ;=== 2 Disk system
  316.     RET
  317. ;
  318. ;********************************************************
  319. ;* Entry point at initialization            *
  320. ;********************************************************
  321. ;
  322. ;DO A SHORT POST-RESET TIME DELAY. ALSO INITIALIZES THE
  323. ;STACK POINTER AND ZEROES THE MONITOR SCRATCH RAM.
  324. INIT:    DI
  325.     LD    HL,MEM    ;POINT TO START OF MONITOR RAM
  326. INIT1:    LD    (HL),0    ;FILL 256 BYTE SPACE WITH ZEROS
  327.     LD    SP,HL    ;DO SOMETHING USEFUL & ADD DELAY
  328.     INC    L    ;On exit SP points to top of RAM
  329.     JR    NZ,INIT1 ;LOOP TAKES ABOUT 4 msecs
  330. ;
  331. ;    INITIALIZE THE Z-80 FOR INTERRUPT MODE #2
  332.     LD    A,H
  333.     LD    I,A ;LOAD I REG WITH MSB OF VECTOR TABLE
  334.     IM    2    ; AND SELECT INTERRUPT MODE 2
  335. ;
  336.     CALL    CLRSCN    ;FILL THE CRT MEMORY WITH BLANKS
  337.     IN    A,(BITDAT) ;Deselect CRT Bank
  338.     RES    7,A
  339.     OUT    (BITDAT),A
  340. ;
  341. ; STORE ANY NON-ZERO VALUES FOR VARIABLES IN MEMORY
  342. ;
  343.     LD    HL,INTAB ;POINT TO DEFAULT VARIABLE TABLE
  344. INIT2:    LD    B,0
  345.     LD    C,(HL)    ;BC=DATA BLOCK BYTECOUNT
  346.     INC    HL
  347.     LD    E,(HL)    ;DE=DESTINATION FOR DATA
  348.     INC    HL
  349.     LD    D,(HL)
  350.     INC    HL
  351.     LDIR        ;COPY DATA @ HL TO VARIABLES @ DE
  352.     BIT    7,(HL)
  353.     JR    Z,INIT2    ;LOOP AGAIN IF NOT AT END OF TABLE
  354. ;
  355. ; INITIALIZE THE PROGRAMMABLE I/O DEVICES
  356.     LD    DE,110H    ;For copyright routine
  357. ;
  358.     INC    HL    ;POINT TO I/O INIT DATA TABLE
  359. INIT3:    LD    B,(HL)    ;B=INIT LOOP BYTECOUNT
  360.     INC    HL
  361.     LD    C,(HL)    ;C=DEVICE CONTROL PORT#
  362.     INC    HL
  363.     OTIR        ;SEND DATA @ HL TO PORT @ C
  364.     BIT    7,(HL)    ;TEST FOR TABLE END MARKER
  365.     JR    Z,INIT3    ;LOOP AGAIN IF NOT AT END
  366. ;
  367. ;    LD    BC,80H
  368. ;    CALL    SETDMA
  369. ;
  370. ;Now check the copyright integrity
  371.  
  372.     IF    ROM
  373.  
  374.     LD    B,47    ;length of msg
  375.     LD    HL,COPYRT-110H
  376.     ADD    HL,DE
  377.     XOR    A
  378. LPP1    ADD    (HL)
  379.     INC    HL
  380.     DJNZ    LPP1
  381. LPP2    CP    0E5H    ;patch for each serial #
  382.     JR    NZ,LPP2
  383.  
  384.     ENDIF    ;ROM
  385.  
  386.  
  387. ;DETERMINE IF CONSOLE I/O CONFIGURATION WILL BE FOR THE
  388. ;ON-BOARD CRT AND KEYBOARD OR AN EXTERNAL SERIAL TERMINAL
  389. ;
  390. ;First enable keyboard interrupts
  391.     IN    A,(KBDDAT)    ;Clear any rubbish
  392.     LD    A,10000011B
  393.     OUT    (KBDCTL),A ;ENABLE INTERRUPTS FROM KBD PIO
  394.     EI
  395. ;
  396.     LD    C,SIOCPB
  397.     LD    A,2    ;Select read register 2
  398.     OUT    (C),A
  399.     IN    A,(C)    ;TEST SIO READ REGISTER 2 TO see
  400. ;    CP    00000110B ; IF THE SIO IS INSTALLED (Status affected)
  401.     CP    0    ;See if SIO is installed (no status affects)
  402.     JR    NZ,PARALL ;SKIP CONFIGURATION TEST IF NO SIO
  403.     LD    B,00010000B ;B=RESET SIO EXTERNAL STATUS COMMAND  
  404. DECIDE:    OUT    (C),B    ;TEST FOR ARRIVAL OF A SERIAL
  405.     IN    A,(C)    ; INPUT CHARACTER START BIT
  406.     BIT    4,A
  407.     JR    NZ,BAUD    ;EXIT LOOP IF START BIT DETECTED
  408.     CALL     KBDST    ;See if FIFO has char ready from
  409.     JR    Z,DECIDE ; parallel keyboard yet
  410. PARALL:    CALL    KBDIN ;DISCARD FIRST KEYBOARD CHARACTER
  411.     JR    SIGNON
  412. ;
  413. ;
  414. ; AUTOMATIC BAUD RATE SETTING ROUTINE FOR SIO
  415. ;
  416. BAUD:    XOR    A
  417. BAUD1:    OUT    (C),B
  418.     IN    D,(C)    ;READ SIO STATUS REGISTER
  419.     BIT    4,D    ;TEST THE SYNC/HUNT BIT
  420.     JR    Z,BAUD1    ;LOOP UNTIL IT CHANGES STATE
  421. BAUD2:    INC    A
  422.     OUT    (C),B    ;RESET REGISTER #0 FLAGS AGAIN
  423.     IN    D,(C)    ;AND LOOP TIMING THE SYNC/HUNT BIT
  424.     BIT    4,D
  425.     JR    NZ,BAUD2 ;REPEAT UNTIL BIT CHANGES AGAIN
  426.  
  427.     IF    IS5MHZ
  428.     RRA        ;divide by 2
  429.     ENDIF    ;IS5MHZ
  430.  
  431.     LD    HL,RATES-1
  432. BAUD3:    INC    HL    ;INDEX INTO BAUD RATE TABLE
  433.     RLA        ; USING COUNT DERRIVED IN A
  434.     JR    NC,BAUD3
  435.     LD    A,(HL)    ;GET BAUD RATE CONTROL BYTE FROM
  436.     OUT    (BAUDB),A ;TABLE AND OUTPUT TO COM-8116 TIMER
  437.     CALL    SIOIN    ;DISARD FIRST SERIAL INPUT CHARACTER
  438.  
  439.     IF    SIO.INTERRUPT
  440.  
  441.     LD    A,1
  442.     OUT    (SIOCPB),A ;RE-PROGRAM SIO B TO GENERATE
  443.     LD    A,00011000B ;INTERRUPTS ON RECIEVED DATA,
  444.     OUT    (SIOCPB),A ;PARITY DOES NOT AFFECT VECTOR
  445.     LD    HL,SIOOUT
  446.     LD    DE,KBDIN
  447.     LD    BC,KBDST
  448.  
  449.     ENDIF    ;SIO.INTERRUPT
  450.  
  451.     IF    SIO.POLLED
  452.  
  453.     LD    HL,SIOOUT
  454.     LD    DE,SIOIN    ;No  interrupts on input
  455.     LD    BC,SIOST
  456.  
  457.     ENDIF    ;SIO.POLLED
  458.  
  459.     CALL    SWITCH.STASH ;And modify vectors for VDU
  460. ;
  461. ;    PRINT SIGNON MESSAGE
  462. ;
  463. SIGNON:
  464.     IF    NOT ROM
  465.     CALL    PNEXT
  466.     DB    '(C) Copyright 1981 Trevor Marshall',EOT
  467.     XOR    A
  468.     LD    (UNIT),A    ;So that warmboot logs in A:
  469.     JP    WARMBOOT
  470.     ENDIF    ;NOT ROM
  471.  
  472.     IF    ROM
  473.     DEFB    9,9,9,'... WAITAID monitor 4.1 ...'
  474.     DEFB    CR,LF,LF,9,9
  475. COPYRT: DB '(C) Copyright 1981 Trevor Marshall, serial # 00 ',EOT
  476. ;Now delay for Drive ready signal to go true
  477.     LD    HL,2000H
  478. LP1X:    DEC    HL
  479.     EX    (SP),HL
  480.     EX    (SP),HL
  481.     LD    A,H
  482.     OR    A,L    ;Is HL zero?
  483.     JR    NZ,LP1X
  484.     LD    C,0    ;Drive A
  485.     CALL    SELECT
  486.     AND    10011000B
  487.     JR    NZ,ABORT.BOOT
  488.     JP    BOOT    ;Boot if ready
  489. ABORT.BOOT: CALL LOGOFF ;Log off DSK not ready
  490.     JP    PROMPT    ;Else GO ENTER MONITOR
  491.     ENDIF    ;ROM
  492. ;
  493. ;
  494. ; BAUD RATE CONSTANTS FOR COM 8116 BAUD RATE GENERATOR
  495. ;
  496. RATES:    DEFB    0101B        ;   300 BAUD
  497.     DEFB    0110B        ;   600 BAUD
  498.     DEFB    0111B        ;  1200 BAUD
  499.     DEFB    1010B        ;  2400 BAUD
  500.     DEFB    1100B        ;  4800 BAUD
  501.     DEFB    1110B        ;  9600 BAUD
  502.     DEFB    1111B        ; 19200 BAUD
  503.     DEFB    1111B        ; 19200 BAUD
  504. ;
  505. ;
  506. INTAB    EQU    $    ;INITIALIZATION DATA TABLES
  507. ;
  508. ;
  509. ;INITIALIZE THE Z-80 'I' REGISTER INTERRUPT VECTOR TABLE
  510. ;
  511.     DEFB    2
  512.     DEFW    SYSVEC+2
  513.     DEFW    KEYSRV ;PARALLEL KEYBOARD INTERRUPT VECTOR
  514. ;
  515.     DEFB    2
  516.     DEFW    CTCVEC+6
  517.     DEFW    TIMER ;ONE SECOND TIMER INTERRUPT VECTOR
  518.  
  519. ;    IF     SIO.INTERRUPT
  520.  
  521.     DEFB    4
  522.     DEFW    SIOVEC+4
  523.     DEFW    SIOINT    ;SIO RECIEVE INTERRUPT VECTOR
  524.     DEFW    SIOERR    ;SIO PARITY, OVERRUN & FRAMING ERROR
  525.  
  526. ;    ENDIF    ;SIO.INTERRUPT
  527.  
  528. ;
  529. ;    INITIALIZE DISK I/O DRIVER VARIABLES
  530. ;
  531.     DEFB    6
  532.     DEFW    UNIT
  533.     DEFB    255    ;FLAG ALL DRIVES AS DE-SELECTED
  534.     DEFB    255,255    ;CLEAR HEAD POSITION TABLE
  535.     DEFB    0,0    ;Both default single density
  536.     DEFB    30    ;SET MOTOR TURN-OFF TIMER
  537. ; RECLEN, TRACK & SECTOR not initialized
  538. ;
  539. ;    INITIALIZE THE CRT DISPLAY CURSOR
  540. ;
  541.     DEFB    2
  542.     DEFW    CHRSAV
  543.     DEFB    ' '
  544.     DEFB    '_'+80H    ;USE BLINKING UNDERSCORE
  545. ;
  546. ;    SET DEFAULT 'SOFTWARE' INTERRUPT VECTORS
  547. ;
  548.     DEFB    6
  549.     DEFW    TIKVEC
  550.     DEFW    DSKTMR ;POINT 'TIKVEC' TO DISK MOTOR TIMER
  551.     DEFW    STASH ;POINT 'PINVEC' TO FIFO INPUT ROUTINE
  552.     DEFW    STASH ;POINT 'SINVEC' TO FIFO INPUT ROUTINE
  553. ;
  554. ;
  555.     DEFB    -1    ;END OF VARIABLE INIT TABLE
  556. ;
  557. ;
  558. ;
  559. BAUDA    EQU    00H ;CHANEL A BAUD RATE GENETATOR
  560. SIO    EQU    04H ;DUAL SERIAL I/O
  561. GENPIO    EQU    08H ;GENERAL PURPOSE PARALLEL I/O
  562. BAUDB    EQU    0CH ;CHANEL B BAUD RATE GENERATOR
  563. WD1771    EQU    10H ;WESTERN DIGITAL DISK CONTROLLER
  564. SCROLL    EQU    14H ;CRT SCROLL MEMORY SCROLL REGISTER
  565. CTC    EQU    18H ;QUAD COUNTER/TIMER CIRCUIT
  566. SYSPIO    EQU    1CH ;SYSTEM PARALLEL I/O
  567. ;
  568. ;INITIALIZE SYSTEM PIO FOR USE AS BANK-SWITCH,
  569. ; DISK DRIVE SELECT AND PARALLEL KEYBOARD INPUT
  570. ;
  571. BITDAT    EQU    SYSPIO+0
  572. BITCTL    EQU    SYSPIO+1
  573. KBDDAT    EQU    SYSPIO+2
  574. KBDCTL    EQU    SYSPIO+3
  575.  
  576.     IF    ROM
  577.     DEFB    3,BITCTL
  578.     DEFB    11001111B ;PUT SYSTEM PIO IN BIT MODE
  579.     DEFB    00000000B ;All bits outputs
  580.     DEFB    01000000B ;DISABLE INTERRUPTS
  581. ;
  582.     DEFB    1,BITDAT
  583.     DEFB    00001000B ;DE-SELECT ROMS, ENABLE DRIVE 0
  584. ;            ; DD* line high
  585. ;            ; SIDE 2 line low (=side 1)
  586.     ENDIF    ;ROM
  587. ;
  588.     DEFB    2,KBDCTL
  589.     DEFB    01001111B ;PUT KEYBOARD PORT IN INPUT MODE
  590.     DEFB    [SYSVEC+2] AND 0FFH ;LOAD KEYBOARD INTERRUPT VECTOR
  591. ;
  592. ;Set up printer PIO
  593. PIOADAT: EQU    8
  594. PIOACTL: EQU    9
  595. PIOBDAT: EQU    10
  596. PIOBCTL: EQU    11
  597. ;
  598.     IF    PARALLEL AND NOT ROM
  599.     DB    3,PIOACTL
  600.     DB    3    ;Disable interrupts
  601.     DB    0CFH    ;Put in bit mode
  602.     DB    0    ;All outputs
  603. ;
  604.     DB    3,PIOBCTL
  605.     DB    3    ;Disable interrupts
  606.     DB    0CFH    ;Bit mode
  607.     DB    0FH    ;Bits 1-3 inputs
  608. ;
  609.     DB    1,PIOBDAT ;Set bit 7 for parallel printer
  610.     DB    80H     ;reset special bell (bit 6)
  611.     ENDIF    ;PARALLEL
  612. ;
  613. ;    INITIALIZE CHANELS 2 AND 3 OF THE CTC
  614. ;    TO GENERATE ONE SECOND INTERRUPTS FROM CTC3
  615. ;
  616. CTC0    EQU    CTC+0        ;CTC CHANEL 0 PORT#
  617. CTC1    EQU    CTC+1        ;CTC CHANEL 1
  618. CTC2    EQU    CTC+2        ;CTC CHANEL 2
  619. CTC3    EQU    CTC+3        ;CTC CHANEL 3
  620.  
  621.     DEFB    1,CTC0
  622.     DEFB    [CTCVEC] AND 0FFH ;BASE INTERRUPT VECTOR FOR CTC
  623. ;
  624.     IF    ROM
  625.     DEFB    2,CTC2
  626.     DEFB    00100111B ;PUT CTC2 IN TIMER MODE
  627.     DEFB    105    ;CTC2 PERIOD=105*256*400 nsecs
  628. ;
  629.     DEFB    2,CTC3
  630.     DEFB    11000111B ;PUT CTC3 IN COUNTER MODE
  631.     DEFB    93    ;CTC3 PERIOD=999936 MICROSECONDS
  632.     ENDIF    ;ROM
  633. ;
  634. ;
  635. ;INITIALIZE SIO CHANEL B FOR ASYNCHRONOUS SERIAL
  636. ; INTERFACE TO PRINTER OR TERMINAL
  637. ;
  638. SIODPA    EQU    SIO+0    ;SIO DATA PORT A
  639. SIODPB    EQU    SIO+1    ;SIO DATA PORT B
  640. SIOCPA    EQU    SIO+2    ;SIO CONTROL/STATUS PORT A
  641. SIOCPB    EQU    SIO+3    ;SIO CONTROL/STATUS PORT B
  642.  
  643.     IF    ROM
  644.     DEFB    1,BAUDB
  645.     DEFB    0101B ;SET COM 8116 FOR 300 BAUD DEFAULT
  646.  
  647.     DEFB    10,SIOCPB
  648.     DEFB    4      ;SELECT REGISTER #4
  649.     DEFB    01001100B ;16X CLOCK, 2 STOP BIT, NO PARITY
  650.     DEFB    1      ;SELECT REGISTER #1
  651.     DEFB    00000000B ;STATUS NO EFFECT ON VECTOR, NO INTERRUPTS
  652.     DEFB    3      ;SELECT REGISTER #3
  653.     DEFB    11000001B ;8 BITS/RX CHARACTER,NO AUTO ENABLES
  654.     DEFB    5      ;SELECT REGISTER #5
  655.     DEFB    11101010B ;8 BITS/TX CHARACTER, ASSERT DTR
  656.     DEFB    2      ;SELECT REGISTER #2
  657.     DEFB    [SIOVEC] AND 0FFH ;LOAD INTERRUPT VECTOR BASE
  658.  
  659.     ELSE
  660.     DB    4,SIOCPB
  661.     DB    1
  662.     DB    0    ;status no effect
  663.     DB    2
  664.     DB    [SIOVEC] AND 0FFH
  665.  
  666.     ENDIF    ;ROM
  667.  
  668.     DEFB    -1        ;END-OF-TABLE
  669. ;
  670. ;    INIT DONE
  671. ;
  672. ;
  673. ;************************************************
  674. ;*                        *
  675. ;* BASIC HEX MONITOR FOR Z-80 PROCESSORS    *
  676. ;*                3-Aug-80    *
  677. ;*                        *
  678. ;************************************************
  679. ;
  680.     IF    ROM    ;Only want the monitor in ROM
  681. ;
  682. ;
  683. ;
  684. PROMPT:    LD    SP,[MEM+0FFH]
  685.     CALL    PNEXT
  686.     DEFB    CR,LF
  687.     DEFB    '* '
  688.     DEFB    EOT
  689.     LD    HL,LINBUF
  690.     LD    C,32
  691.     CALL    GETLIN    ;INPUT A BUFERED CONSOLE LINE
  692.     JR    C,WHAT    ;PRINT 'WHAT ?' IF INPUT ERROR
  693.  
  694.     XOR    A
  695.     LD    (ESCFLG),A
  696.     CALL    CRLFS
  697.     LD    A,(LINBUF) ;GET FIRST CHARACTER IN LINE
  698.     CP    CR
  699.     JR    Z,PROMPT ;JUMP IF A NULL LINE
  700.     LD    HL,CMDTAB ;SEARCH FOR A MATCHING CHARACTER
  701.     LD    BC,CMDSIZ/3 ; IN COMMAND SEARCH TABLE
  702.     CALL    SEARCH
  703.     JR    NZ,WHAT    ;TRY AGAIN IF SEACRH FAILS
  704.     PUSH    BC
  705.     LD    IY,LINBUF+1
  706.     CALL    PARAMS    ;INPUT NUMERIC PARAMETERS FROM
  707.     POP    IX    ; LINE BUFFER AND TEST IF ERROR
  708.     JR    C,WHAT
  709.     LD    HL,(PARAM1)
  710.     LD    DE,(PARAM2)
  711.     LD    BC,(PARAM3)
  712.     CALL    CALLX    ;CALL SUBROUTINE @ IX
  713.     JR    NC,PROMPT ;GO BACK TO PROMPT IF NO ERRORS
  714.  
  715. WHAT:    CALL    PNEXT
  716.     DEFB    ' what ?'
  717.     DEFB    'G'-64    ;SAY 'what ?' AND BEEP THE BELL
  718.     DEFB    EOT
  719.     JR    PROMPT
  720. ;
  721. ;
  722. CALLX:    JP    (IX)    ;CALL SUBROUTINE @ IX
  723. ;
  724. ;
  725. ;
  726. CMDTAB:    DEFB    'R'
  727.     DB    'W'
  728.     DEFB    'O'
  729.     DEFB    'E'
  730.     DEFB    'G'
  731.     DEFB    'T'
  732.     DEFB    'F'
  733.     DEFB    'S'
  734.     DEFB    'M'
  735.     DEFB    'B'
  736.     DEFB    'D'
  737.     DEFB    'S'
  738.  
  739.     DEFW    SWITCH    ;SWITCH CONSOLE OUTPUT VECTOR
  740.     DEFW    MEMDMP    ;DUMP MEMORY IN HEX/ASCII
  741.     DEFW    BOOT    ;BOOT UP CP/M
  742.     DEFW    BLOCK    ;MEMORY BLOCK MOVE
  743.     DEFW    VIEW    ;MEMORY EXAMINE/CHANGE
  744.     DEFW    FILL    ;FILL MEMORY
  745.     DEFW    TEST    ;RAM DIAGNOSTIC
  746.     DEFW    GOTO    ;JUMP TO MEMORY LOCATION
  747.     DEFW    INCMD    ;READ FROM INPUT PORT
  748.     DEFW    OUTCMD    ;WRITE TO OUTPUT PORT
  749.     DW    WRITE.SECTOR
  750.     DEFW    READ.SECTOR ;DISPLAY DISK SECTOR DATA
  751.  
  752. CMDSIZ    EQU    $-CMDTAB
  753. ;
  754. ;
  755. ;************************************************
  756. ;*                        *
  757. ;* MONITOR COMMAND ACTION ROUTINES PACKAGE    *
  758. ;*                        *
  759. ;************************************************
  760. ;
  761. ;
  762. ;
  763. ;
  764. ;
  765. ; -- DISK BOOT LOADER COMMAND --
  766. ;
  767. BOOT:    LD    C,0    ;SELECT DRIVE 0 FOR BOOT LOAD
  768.     CALL    SELECT
  769.     JR    NZ,DSKERR
  770.     CALL    LOGIN    ;HOME HEAD TO TRACK 0 and login disk
  771.     JR    NZ,DSKERR ;ERROR IF NOT READY OR AT TR0
  772.     LD    BC,0080H ;POINT TO CP/M READ BUFFER
  773.     CALL    SETDMA
  774.     LD    C,1    ;SELECT SECTOR 1
  775.     CALL    SETSEC
  776.     CALL    READ    ;READ TRACK 0/ SECTOR 1
  777.     JR    NZ,DSKERR
  778.     JP    0080H    ;GO EXECUTE LOADER
  779. ;
  780. ;
  781. ; ---- Write Disk Sector-----
  782. WRITE.SECTOR: LD  C,A  ;Save param count
  783.     LD    A,0FFH
  784.     LD    (RWFLAG),A ;If flag is non zero = write
  785.     JR    RW11
  786. ;    -- DISK SECTOR READ COMMAND --
  787. ;
  788. READ.SECTOR: LD    C,A ;Save param count
  789.     XOR A
  790.     LD    (RWFLAG),A ; flag is zero if read
  791. RW11:    LD    A,C
  792.     CP    3    ;CHECK PARAMETER COUNT
  793.     SCF
  794.     RET    NZ
  795.     CALL    LOGOFF    ;Logoff current disk
  796.     LD    HL,PARAM1
  797.     LD    C,(HL)    ;USE FIRST ARG AS UNIT#
  798.     CALL    SELECT
  799.     JR    NZ,DSKERR
  800.     LD    HL,PARAM2
  801.     LD    C,(HL)    ;USE SECOND ARG AS TRACK#
  802.     CALL    SEEK
  803.     JR    NZ,DSKERR
  804.     LD    HL,PARAM3
  805.     LD    C,(HL)    ;USE THIRD ARG AS SECTOR#
  806.     CALL    SETSEC
  807.     LD    BC,0080H ;** Default DSK buffer for BOOT
  808.     CALL    SETDMA
  809.     LD    A,(RWFLAG)
  810.     OR    A
  811.     JR    Z,RD1
  812.     CALL    WRITE
  813.     JR    NZ,DSKERR ;Will need to catch this during LOGON
  814.     RET
  815. RD1:    CALL    READ
  816.     JR    NZ,DSKERR
  817. ;    LD    HL,0080H
  818. ;    LD    DE,8
  819. ;    JP    DUMP    ;DUMP DISK READ BUFFER AND RETURN
  820.     RET
  821. ;
  822. ;
  823. DSKERR:    LD    C,A    ;SAVE 1771 STATUS
  824.     CALL    PNEXT
  825.     DEFB    'disk error ',EOT
  826.     LD    A,C    ;get status
  827.     CALL    PUT2HS
  828.     RET
  829. ;
  830. ;
  831. ;    -- MEMORY DUMP COMMAND --
  832. ;
  833. MEMDMP:    DEC    A    ;CHECK PARAMETER COUNT
  834.     JR    Z,MDMP2
  835.     DEC    A
  836.     JR    Z,MDMP3
  837. MDMP1:    LD    HL,(LAST)
  838. MDMP2:    LD    DE,8    ;Default # of lines dumped
  839.     JR    MDMP3B
  840.  
  841. MDMP3:    EX    DE,HL
  842.     SBC    HL,DE    ;DERRIVE BYTECOUNT FOR DUMP RANGE
  843.     LD    B,4
  844. MDMP3A:    SRL    H    ;DIVIDE BYTECOUNT BY 16
  845.     RR    L
  846.     DJNZ    MDMP3A
  847.     INC    HL
  848.     EX    DE,HL
  849. MDMP3B:    CALL    DUMP    ;DUMP DE*16 BYTES STRTING AT HL
  850.     LD    (LAST),HL
  851.     RET    
  852. ;
  853. ;
  854. DUMP:    PUSH    HL    ;SAVE STARTING ADDRESS
  855.     CALL    PUT4HS    ;PRINT STARTING ADDRESS IN HEX
  856.     CALL    SPACE
  857.     LD    B,16
  858. DUMP2:    LD    A,(HL)    ;GET A DATA BYTE @ HL
  859.     INC    HL
  860.     CALL    PUT2HS    ;PRINT THE DATA IN HEX
  861.     DJNZ    DUMP2    ;REPEAT 16 TIMES
  862.     POP    HL    ;RESTORE STARTING ADDRESS
  863.     LD    B,16
  864. DUMP3:    LD    A,(HL)    ;GET BACK DATA BYTE @ HL
  865.     INC    HL
  866.     RES    7,A
  867.     CP    20H
  868.     JR    C,DUMP4
  869.     CP    7FH
  870.     JR    C,DUMP5
  871. DUMP4:    LD    A,'.'    ;PRINT A DOT IF DATA < 20 OR > 7F
  872. DUMP5:    CALL    OUTPUT    ;PRINT ASCII CHARACTER IN A
  873.     DJNZ    DUMP3
  874.     CALL    CRLFS
  875.     RET    NZ    ;EXIT IF ESCAPE REQUEST IS INDICATED
  876.     DEC    DE
  877.     LD    A,D
  878.     OR    E
  879.     JR    NZ,DUMP
  880.     RET
  881. ;
  882. ;
  883. ;
  884. ;
  885. ;    -- MEMORY EXAMINE COMMAND --
  886. ;
  887. VIEW:    CALL    MDATA
  888.     CALL    ECHO
  889.     CP    CR
  890.     JR    Z,VIEW4
  891.     CP    '-'
  892.     JR    Z,VIEW5
  893. VIEW2:    CALL    ASCHEX
  894.     CCF    
  895.     RET    NC
  896.     RLCA    
  897.     RLCA    
  898.     RLCA    
  899.     RLCA    
  900.     LD    C,A
  901.     CALL    ECHO
  902.     CALL    ASCHEX
  903.     CCF    
  904.     RET    NC
  905.     OR    C
  906. VIEW3:    LD    (HL),A
  907.     CALL    CHECK
  908. VIEW4:    INC    HL
  909.     INC    HL
  910. VIEW5:    DEC    HL
  911.     JR    VIEW
  912. ;
  913. ;
  914. ;
  915. ;    -- JUMP TO MEMORY LOCATION COMMAND --
  916. ;
  917. ; We should fill the registers from RAM
  918. GOTO:    DEC    A    ;CHECK PARAMETER COUNT
  919.     SCF
  920.     RET    NZ
  921.     PUSH    HL
  922.     POP    IX
  923. ;Set up the jump at 30H for breakpoints (F7H,RST6)
  924.     LD    A,0C3H
  925.     LD    HL,30H
  926.     LD    (HL),A
  927.     INC    HL
  928.     LD    A,[BKPT AND 0FFH]
  929.     LD    (HL),A
  930.     INC    HL
  931.     LD    A,[BKPT SHR 8]
  932.     LD    (HL),A
  933. ; OK, now go to routine
  934.     JP    (IX)
  935. ;    OR    A
  936. ;    RET    ;RETURN IF WE GET BACK AGAIN
  937. ;
  938. BKPT:    PUSH    HL
  939.     PUSH    DE
  940.     PUSH    BC
  941.     PUSH    AF
  942.     CALL    PNEXT
  943.     DB    '**Breakpoint**, regs are: ',EOT
  944.     POP    AF
  945.     CALL    PUT2HS    ;Put acc
  946.     POP    HL
  947.     CALL    PUT4HS    ;BC
  948.     POP    HL
  949.     CALL    PUT4HS    ;DE
  950.     POP    HL
  951.     CALL    PUT4HS    ;HL
  952.     CALL    PNEXT
  953.     DB    ',PC=',EOT
  954.     POP    HL
  955.     DEC    HL    ;To allow for PC incr past RST30 
  956.     CALL    PUT4HS    ;PC
  957.     CALL    CRLFS
  958.     JP    PROMPT
  959. ;
  960. ;
  961. ;    -- MEMORY READ/WRITE DIAGNOSTIC COMMAND --
  962. ;
  963. TEST:    CP    2    ;CHECK PARAMETER COUNT
  964.     SCF
  965.     RET    NZ
  966.     INC    DE
  967.     LD    E,D    ;GET ENDING PAGE ADDRESS INTO E
  968.     LD    D,H    ;GET STARTING PAGE ADDRESS INTO D
  969.     LD    B,0    ;INITIALIZE PASS COUNTER
  970. TEST1:    LD    H,D    ;POINT HL TO START OF BLOCK
  971.     LD    L,0
  972. TEST2:    LD    A,L
  973.     XOR    H    ;GENERATE TEST BYTE
  974.     XOR    B
  975.     LD    (HL),A    ;STORE BYTE IN RAM
  976.     INC    HL
  977.     LD    A,H
  978.     CP    E    ;CHECK FOR END OF TEST BLOCK
  979.     JR    NZ,TEST2
  980. ;            NOW READ BACK EACH BYTE & COMPARE
  981.     LD    H,D
  982.     LD    L,0    ;POINT HL BACK TO START
  983. TEST3:    LD    A,L
  984.     XOR    H    ;RE-GENERATE TEST BYTE DATA
  985.     XOR    B
  986.     CALL    CHECK    ;VERIFY MEMORY DATA STILL GOOD
  987.     RET    NZ    ;EXIT IF ESCAPE REQUEST IS INDICATED
  988.     INC    HL    ; ELSE GO ON TO NEXT BYTE
  989.     LD    A,H
  990.     CP    E    ;CHECK FOR END OF BLOCK
  991.     JR    NZ,TEST3
  992.     INC    B    ;BUMP PASS COUNT
  993.     LD    A,'+'
  994.     CALL    OUTPUT    ;PRINT '+' AND ALLOW FOR EXIT
  995.     JR    Z,TEST1    ;DO ANOTHER PASS IF NO ESCAPE
  996.     RET
  997. ;
  998. ;
  999. ;
  1000. CHECK:    CP    (HL)
  1001.     RET    Z    ;RETURN IF (HL)=A
  1002.     PUSH    AF
  1003.     CALL    MDATA    ;PRINT WHAT WAS ACTUALLY READ
  1004.     CALL    PNEXT
  1005.     DEFB    'should='
  1006.     DEFB    EOT
  1007.     POP    AF
  1008.     JP    PUT2HS    ;PRINT WHAT SHOULD HAVE BEEN READ
  1009. ;
  1010. ;
  1011. MDATA:    CALL    CRLFS
  1012.     CALL    PUT4HS
  1013.     LD    A,(HL)
  1014.     JP    PUT2HS
  1015. ;
  1016. ;
  1017. ;
  1018. ;    -- FILL MEMORY WITH CONSTANT COMMAND --
  1019. ;
  1020. FILL:    CP    3    ;CHECK IF PARAMETER COUNT=3
  1021.     SCF    
  1022.     RET    NZ
  1023. FILL1:    LD    (HL),C
  1024.     PUSH    HL
  1025.     OR    A
  1026.     SBC    HL,DE    ;COMPARE HL TO END ADDRESS IN DE
  1027.     POP    HL
  1028.     INC    HL    ;ADVANCE POINTER AFTER COMPARISON
  1029.     JR    C,FILL1
  1030.     RET
  1031. ;
  1032. ;
  1033. ;
  1034. ;
  1035. ;    -- MEMORY BLOCK MOVE COMMAND --
  1036. ;
  1037. BLOCK:    CP    3    ;CHECK IF PARAMETER COUNT=3
  1038.     SCF    
  1039.     RET    NZ
  1040.     CALL    BLOCAD
  1041.     LD    A,C
  1042.     OR    B
  1043.     RET    Z    ;EXIT NOW IF BC=0
  1044.     LDIR
  1045.     RET
  1046. ;
  1047. ;
  1048. ;
  1049. BLOCAD:    EX    DE,HL
  1050.     OR    A    ;CLEAR CARRY
  1051.     SBC    HL,DE    ;GET DIFFRENCE BETWEEN
  1052.     EX    DE,HL    ;HL & DE FOR BYTECOUNT
  1053.     PUSH    DE
  1054.     PUSH    BC
  1055.     POP    DE    ;GET OLD BC INTO DE
  1056.     POP    BC
  1057.     INC    BC    ;GET COUNT+1 INTO BC
  1058.     RET    
  1059. ;
  1060. ;
  1061. ;
  1062. ;
  1063. ;    -- READ FROM INPUT PORT COMMAND --
  1064. ;
  1065. INCMD:    DEC    A    ;CHECK IF PARAMETER COUNT=1
  1066.     SCF
  1067.     RET    NZ
  1068.     LD    C,L    ;POINT C TO INPUT PORT
  1069. IN1:    CALL    CRLFS
  1070.     LD    A,C
  1071.     CALL    PUT2HS
  1072.     IN    A,(C)
  1073.     CALL    PUT2HS
  1074.     CALL    ECHO
  1075.     CP    CR
  1076.     JR    Z,IN2
  1077.     CP    '-'
  1078.     JR    Z,IN3
  1079.     OR    A
  1080.     RET
  1081.  
  1082. IN2:    INC    C
  1083.     INC    C
  1084. IN3:    DEC    C
  1085.     JR    IN1
  1086. ;
  1087. ;
  1088. ;
  1089. ;    -- WRITE TO OUTPUT PORT COMMAND --
  1090. ; Syntax: O <Data> <Port>
  1091. OUTCMD:    CP    2    ;CHECK IF PARAMETER COUNT=2
  1092.     SCF
  1093.     RET    NZ
  1094.     LD    C,E    ;POINT C TO OUTPUT PORT
  1095.     OUT    (C),L    ;OUTPUT DATA PASSED IN L
  1096.     OR    A
  1097.     RET
  1098. ;
  1099. ;
  1100. ;    -- SWITCH CONSOLE OUTPUT DEVICE COMMAND --
  1101. ;
  1102. SWITCH:    LD    HL,COFLAG
  1103.     INC    (HL)    ;TOGGLE CONSOLE OUTPUT TYPE FLAG
  1104.     BIT    0,(HL)
  1105.  
  1106.     IF    SIO.POLLED
  1107.     LD    DE,SIOIN    ;No interrupts
  1108.     LD    BC,SIOST
  1109.     LD    HL,SIOOUT
  1110.     ELSE
  1111.     LD    DE,KBDIN    ;Interrupts
  1112.     LD    BC,KBDST
  1113.     LD    HL,SIOOUT
  1114.     ENDIF    ;SIO.POLLED
  1115.  
  1116.     JR    Z,SWIT2    ;JUMP IF ZERO TO ONE TRANSITION
  1117.     LD    HL,CRTOUT
  1118.     LD    DE,KBDIN
  1119.     LD    BC,KBDST
  1120.  
  1121.     ENDIF    ;ROM (over all the monitor package)
  1122.  
  1123. SWITCH.STASH: ;Store the Serial/Parallel vectors
  1124. SWIT2:    LD    (CONOUT+1),HL ;STORE NEW CONSOLE OUTPUT ADDRESS
  1125.     LD    (CONIN+1),DE
  1126.     LD    (CONST+1),BC
  1127.     RET
  1128. ;
  1129. ;
  1130. ;************************************************
  1131. ;*                        *
  1132. ;* CONSOLE I/O PACKAGE AND UTILITY ROUTINES    *
  1133. ;*                        *
  1134. ;************************************************
  1135. ;
  1136.     IF    ROM
  1137. ;
  1138. ;
  1139. GETLIN:    LD    B,C    ;SAVE MAX LINE LENGTH PARAMETER IN B
  1140. GLIN1:    CALL    ECHO    ;GET A CHARACTER FROM THE CONSOLE
  1141.     CP    CR    ;CHECK FOR CARRIAGE RETURN
  1142.     JR    Z,GLIN2
  1143.     CP    'H'-64    ;CHECK FOR CTL-H BACKSPACE
  1144.     JR    Z,GLIN4
  1145. ; Check for delete here will not work, catch it at CHIN
  1146. ;    CP    7FH    ;Check fo delete
  1147. ;    JR    Z,GLIN4
  1148.     CP    ' '
  1149.     RET    C    ;OTHER CONTROL CHARACTERS ARE ILLEGAL
  1150.     LD    (HL),A
  1151.     INC    HL    ;STORE CHARACTER IN BUFFER
  1152.     DEC    C
  1153.     JR    NZ,GLIN1 ;GET ANOTHER IF THERE'S MORE ROOM
  1154.     SCF    
  1155.     RET        ;RETURN WITH CARRY=1 IF TOO
  1156.             ;MANY CHARACTERS ARE ENTERED
  1157. GLIN2:    LD    (HL),A    ;PUT CARRIAGE RETURN ON END OF LINE
  1158.     RET        ;RETURN WITH CARRY BIT=0
  1159.  
  1160. GLIN4:    DEC    HL    ;DELETE LAST CHARACTER FROM BUFFER
  1161.     CALL    PNEXT
  1162.     DEFB    ' ','H'-64 ;PRINT A SPACE TO OVERWRITE THE
  1163.     DEFB    EOT    ; LAST CHARACTER, THEN DO A BACKSPACE
  1164.     INC    C
  1165.     LD    A,B    ;MAKE SURE YOU'RE NOT TRYING TO
  1166.     SUB    C    ;BACKSPACE PAST THE START OF THE LINE
  1167.     JR    NC,GLIN1
  1168.     RET    
  1169. ;
  1170. ;
  1171. ;
  1172. PARAMS:    LD    BC,0
  1173.     LD    A,(IY+0)
  1174. LOOKAGAIN: CP    CR    ;CHECK IF LINE TERMINATES
  1175.     JR    Z,ZEROLENGTH ;Immediately with <CR>
  1176.     CP    ' '     ;Or begins with a space
  1177.     JR    Z,DROPIT
  1178.     CP    'M'     ;Or an M
  1179.     JR    Z,DROPIT
  1180.     JR    PARA2
  1181. DROPIT:    INC    IY
  1182.     LD    A,(IY)
  1183.     JR    LOOKAGAIN
  1184. ;
  1185. ZEROLENGTH: XOR    A
  1186.     RET        ;RETURN WITH PARAM COUNT=0 IF SO
  1187. PARA1:    INC    C
  1188.     INC    C
  1189.     BIT    3,C
  1190.     SCF
  1191.     RET    NZ    ;ERROR IF > 4 NUMBERS ENTERED
  1192. PARA2:    PUSH    BC    ;SAVE PARAMETER COUNT
  1193.     CALL    GETHEX    ;READ A NUMBER FROM LINE BUFFER
  1194.     POP    BC
  1195. PARA4:    RET    C    ;ERROR IF RESULT OVER 16 BITS
  1196.     LD    IX,PARAM1 ;POINT TO PARAMETER STORAGE AREA
  1197.     ADD    IX,BC    ;ADD PARAMETER COUNT IN BC
  1198.     LD    (IX+0),L
  1199.     LD    (IX+1),H ;STORE DATA RETURNED FROM 'GETHEX'
  1200.     CP    ' '
  1201.     JR    Z,PARA1    ;GET ANOTHER ITEM IF SPACE
  1202.     CP    ','
  1203.     JR    Z,PARA1    ;GET ANOTHER ITEM IF COMMA
  1204.     CP    CR
  1205.     SCF        ;ELSE CHECK FOR CARRIAGE RETURN
  1206.     RET    NZ    ; AND EXIT WITH CY=1 IF NOT
  1207. PAREND:    LD    A,C
  1208.     SRL    A    ;A=COUNT OF NUMBERS ENTERED
  1209.     INC    A
  1210.     RET
  1211. ;
  1212. ;    GETHEX CONVERTS ASCII TO BINARY AND DOES
  1213. ;    HIGH LIMIT CHECKS TO LESS THAN 17 BITS.
  1214. ;    CARRY SET ON ILLEGAL CONVERSION RESULT
  1215. ;    TERMINATING CHARACTER RETURNS IN A.
  1216. ;    HL RETURNS WITH 16 BIT BINARY INTEGER
  1217. ;
  1218. GETHEX:    LD    HL,0
  1219.     JR    GNUM3
  1220.     
  1221. GNUM1:    LD    B,4
  1222. GNUM2:    ADD    HL,HL    ;MULTIPLY RESULT BY 16
  1223.     RET    C    ;RETURN IF IT OVERFLOWS 16 BITS
  1224.     DJNZ    GNUM2
  1225.     LD    E,A    ;APPEND NEW LOW ORDER DIGIT
  1226.     LD    D,0    ;AND GET RESULT BACK INTO DE
  1227.     ADD    HL,DE
  1228.     RET    C    ;RETURN IF OVERFLOW
  1229. GNUM3:    LD    A,(IY+0) ;GET A CHARACTER FROM LINE INPUT
  1230.     INC    IY    ; BUFFER @ IY AND BUMP IY
  1231.     LD    C,A
  1232.     CALL    ASCHEX    ;CONVERT ASCII TO NUMERIC
  1233.     JR    NC,GNUM1
  1234.     LD    A,C
  1235.     OR    A
  1236.     RET
  1237. ;
  1238. ;
  1239. ASCHEX:    SUB    '0'
  1240.     RET    C
  1241.     CP    10
  1242.     CCF
  1243.     RET    NC
  1244.     SUB    7
  1245.     CP    10
  1246.     RET    C
  1247.     CP    16
  1248.     CCF
  1249.     RET
  1250. ;
  1251.  
  1252.     ENDIF    ;ROM
  1253.  
  1254. ;
  1255. ;
  1256. SEARCH:    CPIR        ;SEARCH TABLE @HL FOR MATCH WITH A
  1257.     RET    NZ    ;EXIT NOW IF SEARCH FAILS
  1258.     ADD    HL,BC
  1259.     ADD    HL,BC    ;ADD RESIDUE FROM CPIR BYTECOUNT
  1260.     ADD    HL,BC    ; TO HL 3 TIMES TO GET POINTER
  1261.     LD    C,(HL)    ; TO ADDRESS PART OF TABLE ENTRY
  1262.     INC    HL
  1263.     LD    B,(HL)
  1264.     RET        ;EXIT WITH Z=1 TO INDICATE MATCH
  1265. ;
  1266. ;
  1267. ;
  1268. PUT4HS:    LD    A,H
  1269.     CALL    PUT2HX
  1270.     LD    A,L
  1271. PUT2HS:    CALL    PUT2HX
  1272.     JR    SPACE
  1273. ;
  1274. ;
  1275. PUT2HEX:
  1276. PUT2HX:    PUSH    AF
  1277.     RRA    
  1278.     RRA    
  1279.     RRA    
  1280.     RRA    
  1281.     CALL    PUTNIB
  1282.     POP    AF
  1283. PUTNIB:    AND    00001111B
  1284.     ADD    A,90H
  1285.     DAA
  1286.     ADC    A,40H
  1287.     DAA
  1288.     JR    OUTPUT
  1289. ;
  1290. ;
  1291. ; PMSG PRINTS THE STRING OF ASCII CHARACTERS
  1292. ;  POINTED TO BY THE RELATIVE ADDRESS IN DE
  1293. ;  UNTIL AN EOT IS ENCOUNTERED IN THE STRING.
  1294. ;
  1295. EOT    EQU    04H
  1296. CR    EQU    0DH
  1297. LF    EQU    0AH
  1298. ;
  1299.     
  1300. PNEXT:    EX    (SP),HL
  1301.     CALL    PMSG
  1302.     EX    (SP),HL
  1303.     RET
  1304. ;
  1305. PMSG:    LD    A,(HL)
  1306.     INC    HL
  1307.     CP    EOT
  1308.     RET    Z
  1309.     CALL    OUTPUT
  1310.     JR    PMSG
  1311. ;
  1312. ;
  1313. ; CRLFS OUTPUTS A RETURN-LINEFEED-SPACE
  1314. ;  TO THE CONSOLE DEVICE
  1315. ;
  1316. CRLFS:    CALL    PNEXT
  1317.     DEFB    CR,LF,EOT
  1318. SPACE:    LD    A,' '
  1319.     JR    OUTPUT
  1320. ;
  1321.     IF    ROM
  1322. ;
  1323. ;
  1324. ; ECHO INPUTS ONE CHARACTER FROM THE CONSOLE
  1325. ; DEVICE, PRINTS IT ON THE CONSOLE OUTPUT AND
  1326. ; THEN RETURNS IT IN REGISTER A WITH BIT 7 RESET
  1327. ;
  1328. ; OUTPUT PRINTS THE CHARACTER IN REGISTER A ON
  1329. ; THE CONSOLE OUTPUT DEVICE AND THEN DOES A CHECK
  1330. ; FOR CONSOLE INPUT TO FREEZE OR ABORT OUTPUT.
  1331. ;
  1332.  
  1333. ECHO:    CALL    CONIN     ;INPUT A CHARACTER AND ECHO IT
  1334.     CP    7FH    ;delete?
  1335.     JR    NE,ECHO2
  1336.     LD    A,8    ;yes, load a backspace
  1337. ECHO2:    PUSH    AF
  1338.     CALL    CONOUT    
  1339.     POP    AF
  1340.     CP    'Z'+1    ;make LC UC
  1341.     RET    C
  1342.     SUB    20H    ;CONVERT UPPER CASE TO LOWER CASE
  1343.     RET
  1344. ;
  1345.     ENDIF    ;ROM
  1346. ;
  1347. ;
  1348. OUTPUT:    CALL    CONOUT
  1349.     CALL    CONST    ;SEE IF CONSOLE INPUT IS PENDING
  1350.     JR    Z,OUTP2
  1351.     CALL    CONIN
  1352.     CP    CR    ;SEE IF CARRIAGE RETURN WAS TYPED
  1353.     JR    Z,OUTP1
  1354.     CP    'S'-40H ;<CTL-S>?
  1355.     JR    NZ,OUTP3 ;If not put the char back on the queue
  1356.     CALL    CONIN    ;WAIT FOR ANOTHER INPUT CHARACTER
  1357.     JR    OUTP2    ; THEN RETURN TO CALLING ROUTINE
  1358.  
  1359. OUTP1:    LD    (ESCFLG),A ;SET ESCAPE FLAG TO NON-ZERO VALUE
  1360. OUTP2:    LD    A,(ESCFLG)
  1361.     OR    A    ;RETURN CURRENT STATUS OF ESCAPE
  1362.     RET        ; FLAG TO CALLING ROUTINE
  1363. ;
  1364. OUTP3:    PUSH    HL
  1365.     CALL    REPLACE
  1366.     POP    HL
  1367.     JR    OUTP2    ;and return
  1368. ;
  1369. ;
  1370. ;********************************************************
  1371. ;*                            *
  1372. ;*    INTERRUPT SERVICE ROUTINES FOR KEYBOARD        *
  1373. ;*    INPUT AND REAL-TIME CLOCK FUNCTIONS        *
  1374. ;*                3-Aug-80        *
  1375. ;*                            *
  1376. ;********************************************************
  1377. ;
  1378. ;
  1379. ;
  1380. ;
  1381. KBDST:    LD    A,(FIFCNT)    ;GET INPUT FIFO BYTECOUNT
  1382.     OR    A        ;TEST IF EQUAL ZERO
  1383.     RET    Z        ;EXIT WITH A=0 IF QUEUE IS EMPTY
  1384.     LD    A,255
  1385.     RET            ;ELSE SET A=255 TO INDICATE DATA READY
  1386. ;
  1387. ;
  1388. ;
  1389. KBDIN:    CALL    KBDST
  1390.     JR    Z,KBDIN    ;LOOP UNTIL KEYBOARD INPUT READY
  1391.     PUSH    HL
  1392.     CALL    REMOVE        ;GET CHARACTER FROM INPUT QUEUE
  1393.     POP    HL
  1394.     BIT    7,A
  1395. ;If B7 set it must be HONEYWELL KYBD char code
  1396.     RET    Z
  1397. ; Else catch the cursor codes for Honeywell keyboard
  1398. ; 81=UP, 83=right, 84=left, 82=down, 88= home
  1399. ; E7=CLRSCREEN is caught in STASH immediately it is pressed
  1400.     PUSH    HL
  1401.     PUSH    BC
  1402.     LD    HL,TBL1    ;Point at keycode table
  1403.     LD    BC,TBL1.LENGTH
  1404.     CPIR    ;Until match or no match
  1405.     JR    NZ,RET1    ;Abort if no match
  1406.     LD    BC,TBL1.LENGTH ;Point into next table
  1407.     ADD    HL,BC
  1408.     LD    A,(HL)
  1409. RET1:    POP    BC
  1410.     POP    HL
  1411.     RET
  1412. ;
  1413. TBL1:    DB    81H
  1414.     DB    83H
  1415.     DB    84H
  1416.     DB    82H
  1417.     DB    0FFH    ;a dummy entry for debugging
  1418. TBL1.LENGTH: EQU $-TBL1
  1419.     DB    0 ;1 byte spare as HL is incremented past match
  1420. TBL2:    DB    05H    ;Up line
  1421.     DB    04H    ;Right char
  1422.     DB    13H    ;Left char
  1423.     DB    18H    ;Down line
  1424.     DB    0    ;our dummy entry again
  1425. ;HOME is not processed, as not used by WORDSTAR
  1426. ;
  1427. ;
  1428. ;
  1429. ; We don't need software shift lock
  1430. STASH:;    LD    HL,LOCK        ;POINT TO SHIFT LOCK VARIABLES
  1431. ;    CP    (HL)        ;TEST IF A=SHIFT LOCK CHARACTER
  1432. ;    INC    HL        ; THEN POINT TO LOCK FLAG
  1433. ;    JR    NZ,STASH2    ;JUMP IF NOT THE SHIFT CHARACTER
  1434. ;    INC    (HL)        ; ELSE COMPLIMENT THE SHIFT LOCK
  1435. ;    RET            ; AND EXIT NOW
  1436. ;
  1437. STASH2:;    BIT    0,(HL)        ;TEST THE SHIFT LOCK FLAG
  1438. ;    JR    Z,STASH3    ;JUMP IF SHIFT LOCK NOT SET
  1439. ;    CP    40H        ;ELSE CHECK FOR SHIFABLE CHARACTER
  1440. ;    JR    C,STASH3    ; AND JUMP IF NOT EQUAL OR GREATER
  1441. ;    CP    7FH        ; THAN '@' AND LESS THAN RUBOUT
  1442. ;    JR    NC,STASH3
  1443. ;    XOR    00100000B    ;ELSE TOGGLE BIT 5 OF THE CHARACTER
  1444. STASH3:    LD    C,A
  1445. ;
  1446.     CP    0E7H    ;Honeywell Keyboard's CLEAR SCREEN key
  1447.     JR    NZ,NXT35
  1448.     CALL    CLRSCN
  1449.     IN    A,(BITDAT)
  1450.     RES    7,A
  1451.     OUT    (BITDAT),A
  1452.     RET
  1453. ;
  1454. NXT35:    LD    HL,FIFCNT    ;BUMP INPUT FIFO CHARACTER COUNT
  1455.     LD    A,(HL)
  1456.     INC    A
  1457.     CP    16
  1458.     RET    NC        ;EXIT NOW IF FIFO IS FULL
  1459.     LD    (HL),A        ; ELSE INCREMENT FIFO COUNT
  1460.     LD    HL,FIFIN    ;POINT HL TO FIFO INPUT OFFSET
  1461.     CALL    INDEX
  1462.     LD    (HL),C        ;STORE CHARACTER IN FIFO @ HL
  1463.     RET
  1464. ;
  1465. ;
  1466. ;
  1467. ;
  1468. REMOVE:    LD    HL,FIFCNT
  1469.     DEC    (HL)
  1470.     LD    HL,FIFOUT    ;POINT HL TO FIFO OUTPUT OFFSET
  1471. INDEX:    LD    A,(HL)
  1472.     INC    A
  1473.     AND    00001111B    ;INCREMENT FIFO POINTER
  1474.     LD    (HL),A        ; MODULO 16 AND REPLACE
  1475.     LD    HL,FIFO
  1476.     ADD    A,L        ;INDEX INTO FIFO BY OFFSET IN A
  1477.     LD    L,A
  1478.     LD    A,(HL)
  1479.     RET
  1480. ;
  1481. REPLACE: LD    HL,FIFCNT
  1482.     INC    (HL)
  1483.     LD    HL,FIFOUT
  1484. INDEX2:    LD    A,(HL)
  1485.     DEC    A
  1486.     AND    00001111B
  1487.     LD    (HL),A
  1488.     RET
  1489. ;
  1490. ;
  1491. ;    SOFTWARE DISK MOTOR TURN-OFF TIMER ROUTINE
  1492. ;
  1493. DSKTMR:    LD    HL,MOTOR    ;DECREMENT DISK TURN-OFF TIMER
  1494.     DEC    (HL)
  1495.     RET    NZ        ;EXIT IF NOT TIMED OUT YET
  1496.     IN    A,(BITDAT)
  1497.     OR    00000100B    ;DISABLE ALL DRIVE SELECTS AND
  1498.     OUT    (BITDAT),A    ; TURN OFF THE SPINDLE MOTORS
  1499.     RET
  1500. ;
  1501. ;
  1502. ;    -- INTERRUPT SERVICE ROUTINE FOR PARALLEL KEYBOARD --
  1503. ;
  1504. KEYSRV:    LD    (SPSAVE),SP    ;SAVE USER STACK POINTER AND
  1505.     LD    SP,TMPSTK+16    ; SWITCH TO LOCAL STACK
  1506.     PUSH    HL
  1507.     PUSH    DE
  1508.     PUSH    BC
  1509.     PUSH    AF        ;SAVE MACHINE STATE
  1510.     IN    A,(KBDDAT)    ;READ KEYBOARD INPUT PORT
  1511.     CPL
  1512.     LD    HL,(PINVEC)    ;GET KBD INTERRUPT ROUTINE VECTOR
  1513.     JR    DSPTCH    ; AND JUMP TO DISPATCH POINT
  1514. ;
  1515. ;
  1516. ;
  1517. ;    -- INTERRUPT SERVICE ROUTINE FOR ONE SECOND TIMER --
  1518. ;
  1519. TIMER:    LD    (SPSAVE),SP    ;SAVE USER STACK POINTER AND
  1520.     LD    SP,TMPSTK+16    ; SWITCH TO LOCAL STACK
  1521.     PUSH    HL
  1522.     PUSH    DE
  1523.     PUSH    BC
  1524.     PUSH    AF
  1525.     LD    HL,(TIKVEC)    ;GET CLOCK INTERRUPT ROUTINE VECTOR
  1526.     JR    DSPTCH    ; AND JUMP TO DISPATCH POINT
  1527. ;
  1528. ;
  1529. ;
  1530. ;    -- SERIAL INPUT INTERRUPT SERVICE ROUTINE FOR SIO --
  1531. ;
  1532.     IF    SIO.INTERRUPT
  1533.  
  1534. SIOINT:    LD    (SPSAVE),SP    ;SAVE USER STACK POINTER AND
  1535.     LD    SP,TMPSTK+16    ; SWITCH TO LOCAL STACK
  1536.     PUSH    HL
  1537.     PUSH    DE
  1538.     PUSH    BC
  1539.     PUSH    AF        ;SAVE MACHINE STATE
  1540.     IN    A,(SIODPB)    ;READ SIO DATA INPUT PORT
  1541.     AND    01111111B
  1542.     LD    HL,(SINVEC)    ;GET SERIAL INPUT ROUTINE VECTOR
  1543.  
  1544.     ENDIF    ;SIO.INTERRUPT
  1545.  
  1546. DSPTCH:    CALL    CALLHL        ;CALL SUBROUTINE ADDRESSED BY H
  1547.     POP    AF
  1548.     POP    BC
  1549.     POP    DE
  1550.     POP    HL
  1551.     LD    SP,(SPSAVE)
  1552.     EI            ;RE-ENABLE INTERRUPTS AND RETURN
  1553.     RETI
  1554. ;
  1555. ;
  1556. ;    -- RX ERROR INTERRUPT SERVICE ROUTINE FOR SIO --
  1557. ;
  1558. ;    ARRIVE HERE IF RECIEVE INTERRUPT FROM FRAMING, OVERRUN
  1559. ;    AND PARITY ERRORS. (PARITY CAN BE DISABLED)
  1560. ;
  1561. SIOERR:
  1562.     IF    SIO.INTERRUPT
  1563.  
  1564.     LD    (SPSAVE),SP    ;SAVE USER STACK POINTER AND
  1565.     LD    SP,TMPSTK+16    ; SWITCH TO LOCAL STACK
  1566.     PUSH    AF
  1567.     CALL    SIOIN2        ;CLEAR BAD CHARACTER FROM SIO
  1568.     LD    A,'G'-64
  1569.     CALL    SIOXMT        ;OUTPUT A CTL-G AS A WARNING
  1570.     POP    AF
  1571.     LD    SP,(SPSAVE)
  1572.  
  1573.     ENDIF    ;SIO.INTERRUPT
  1574.  
  1575.     IF    NOT SIO.INTERRUPT
  1576. SIOINT:
  1577.     ENDIF    ;NOT SIO.INTERRUPT
  1578.  
  1579.     EI
  1580.     RETI
  1581. ;
  1582. ;
  1583. CALLHL:    JP    (HL)
  1584. ;
  1585. ;
  1586. ;
  1587. ;    POLLED MODE I/O ROUTINES FOR SIO CHANEL B
  1588. ;
  1589. SIOST:    IN    A,(SIOCPB)    ;GET SIO STATUS REGISTER
  1590.     AND    00000001B
  1591.     RET    Z        ;ACC=0 IF NO DATA AVAILABLE
  1592.     LD    A,255
  1593.     RET
  1594. ;
  1595. ;
  1596. SIOIN:    CALL    SIOST        ;TEST CONSOLE STATUS
  1597.     JR    Z,SIOIN    ;LOOP UNTIL DATA IS RECIEVED
  1598. SIOIN2:    LD    A,00110000B    ;RESET STATUS BITS IN SIO FOR
  1599.     OUT    (SIOCPB),A    ; PARITY/OVERRUN/FRAMING ERRORS,
  1600.     IN    A,(SIODPB)    ; THEN GET THE INPUT CHARACTER 
  1601.     AND    7FH
  1602.     RET
  1603. ;
  1604. ;
  1605. ; We dont need null padding
  1606. SIOOUT:    ;CP    ' '        ;TEST FOR CONTROL CHARACTERS
  1607. ;    JR    NC,SIOXMT    ;JUMP IF PRINTABLE CHARACTER
  1608. ;    CALL    SIOXMT        ; ELSE SEND CONTROL CHARACTER
  1609. ;    LD    A,(NULLS)    ; AND THEN SEND NULLS AS PADDING
  1610. ;    INC    A        ;GET NULL PAD COUNT AND FIX SO
  1611. ;    JR    PAD1        ; THAT COUNT=0 SENDS NO NULLS
  1612.  
  1613. ;PAD:    PUSH    AF
  1614. ;    XOR    A
  1615. ;    CALL    SIOXMT        ;OUTPUT A NULL TO THE SIO
  1616. ;    POP    AF
  1617. ;PAD1:    DEC    A
  1618. ;    JR    NZ,PAD    ;LOOP SENDING NULLS TO SIO
  1619. ;    RET
  1620. ;
  1621. ;
  1622. SIOXMT:    PUSH    AF
  1623. SIOX1:    IN    A,(SIOCPB)
  1624.     AND    00000100B    ;TEST TBE STATUS BIT
  1625.     JR    Z,SIOX1
  1626.     POP    AF
  1627.     OUT    (SIODPB),A    ;OUTPUT DATA TO SIO
  1628.     RET
  1629. ;
  1630. ;
  1631. ;************************************************
  1632. ;*                        *
  1633. ;*    MEMORY-MAPPED CRT OUTPUT DRIVER        *
  1634. ;*                        *
  1635. ;*    Russell Smith    18-August-1980        *
  1636. ;*                        *
  1637. ;************************************************
  1638. ;
  1639. ;
  1640. CRTMEM    EQU    3000H    ;Start of 3K CRT memory space
  1641. CRTBAS    EQU    CRTMEM SHR 8 ;STARTING PAGE# OF 3K CRT SPACE
  1642. CRTTOP    EQU    [CRTMEM+3072] SHR 8 ;ENDING PAGE# OF CRT SPACE
  1643. ;
  1644. ;
  1645. CRTOUT:
  1646.     PUSH    AF
  1647.     PUSH    HL
  1648.     PUSH    DE
  1649.     PUSH    BC
  1650.     RES    7,A
  1651.     LD    C,A
  1652.     DI        ;KEEP THE WOLVES AWAY FOR A WHILE
  1653.     LD    (SPSAVE),SP
  1654.     LD    SP,TMPSTK+16 ;POINT SP TO TOP OF LOCAL STACK
  1655.     IN    A,(BITDAT)
  1656.     SET    7,A        ;SELECT ROM/CRT MEMORY BANK
  1657.     OUT    (BITDAT),A
  1658. ;
  1659. ;FIRST REMOVE THE OLD CURSOR CHARACTER FROM THE SCREEN
  1660. ;
  1661.     LD    HL,CHRSAV ;GET CHARACTER NOW OVERLAYED BY CURSOR
  1662.     LD    B,(HL)
  1663.     LD    HL,(CURSOR) ;LOAD HL WITH CURSOR POINTER
  1664.     LD    A,H
  1665.     AND    00001111B ;A LITTLE INSURANCE THAT HL CAN'T
  1666.     OR    CRTBAS     ; EVER POINT OUTSIDE THE CRT MEMORY
  1667.     LD    H,A
  1668.     LD    (HL),B    ;REMOVE CURSOR BY RESTORING CHARACTER
  1669. ;
  1670. ;    PROCESS CHARACTER PASSED IN C
  1671. ;
  1672.     CALL    OUTCH
  1673. ;
  1674. ;NOW STORE A NEW CURSOR CHARACTER AT THE CURSOR LOCATION
  1675. ;
  1676.     LD    A,(HL)    ;GET CHARACTER AT NEW CURSOR LOCATION
  1677.     LD    (CHRSAV),A ;SAVE FOR NEXT TIME 'CRTOUT' IS CALLED
  1678.     CP    ' '    ;TEST IF CHARACTER IS A SPACE
  1679.     SET    7,A    ;THEN TURN ON BIT 7 TO ENABLE BLINK
  1680.     JR    NZ,CRT2    ;JUMP IF CHARACTER IS NON-BLANK
  1681.     LD    A,(CSRCHR) ;ELSE GET CHARACTER USED FOR CURSOR
  1682. CRT2:    LD    (HL),A    ;STORE CHARACTER IN A AS CURSOR MARK
  1683.     LD    (CURSOR),HL ;SAVE HL AS CURSOR POINTER
  1684.  
  1685.     LD    SP,(SPSAVE)
  1686.     IN    A,(BITDAT)
  1687.     RES    7,A    ;SWITCH BACK THE LOWER 16K OF RAM
  1688.     OUT    (BITDAT),A
  1689.     EI        ;INTERRUPTS ARE SAFE AGAIN
  1690.     POP    BC
  1691.     POP    DE
  1692.     POP    HL
  1693.     POP    AF
  1694.     RET
  1695. ;
  1696. ;
  1697. ;
  1698. OUTCH:    LD    DE,LEADIN
  1699.     LD    A,(DE)    ;GET LEAD-IN SEQUENCE STATE
  1700.     OR    A
  1701.     JP    NZ,MULTI ;JUMP IF IN A LEAD-IN SEQUENCE
  1702.     LD    A,C    ; ELSE PROCESS CHARACTER IN C
  1703.     CP    ' '
  1704.     JR    C,CONTRL ;JUMP IF A CONTROL CHARACTER
  1705. DISPLA:    LD    (HL),C    ; ELSE STORE DISPLAYABLE CHARACTER
  1706.     INC    HL    ; AND ADVANCE POINTER TO NEXT COLUMN
  1707.     LD    A,L
  1708.     AND    01111111B ;EXTRACT COLUMN# FROM HL
  1709.     CP    80
  1710.     RET    C    ;EXIT IF NOT PAST COLUMN 79
  1711.     CALL    RETURN    ; ELSE DO AUTOMATIC CARRIAGE RETURN
  1712.     CALL    LFEED    ; AND LINEFEED
  1713.     RET
  1714. ;
  1715. ;
  1716. ;
  1717. CONTRL:    PUSH    HL
  1718.     LD    HL,CTLTAB ;SEARCH FOR CONTROL CHARACTER
  1719.     LD    BC,CTLSIZ/3 ;HANDLING SUBROUTINE IN TABLE
  1720.     CALL    SEARCH
  1721.     POP    HL
  1722.     RET    NZ    ;EXIT IF NOT IMPLEMENTED
  1723.     PUSH    BC
  1724.     RET    ;DO SNEAKY JUMP TO PRESERVE REGISTERS
  1725.  
  1726. CTLTAB:    DEFB    '_'-64
  1727.     DEFB    '^'-64
  1728.     DEFB    '['-64
  1729.     DEFB    'Z'-64
  1730.     DEFB    'X'-64
  1731.     DEFB    'Q'-64
  1732.     DEFB    'M'-64
  1733.     DEFB    'L'-64
  1734.     DEFB    'K'-64
  1735.     DEFB    'J'-64
  1736.     DEFB    'I'-64
  1737.     DEFB    'H'-64
  1738.     DEFB    'G'-64
  1739.  
  1740.     DEFW    BELL    ;CTL-G IS THE BELL
  1741.     DEFW    BAKSPC    ;CTL-H IS CURSOR LEFT
  1742.     DEFW    TAB    ;CTL-I IS TAB
  1743.     DEFW    LFEED    ;CTL-J IS CURSOR DOWN
  1744.     DEFW    UPCSR    ;CTL-K IS CURSOR UP
  1745.     DEFW    FORSPC    ;CTL-L IS CURSOR RIGHT
  1746.     DEFW    RETURN    ;CTL-M IS CARRIAGE RETURN
  1747.     DEFW    CLREOS    ;CTL-Q IS CLEAR TO END-OF-SCREEN
  1748.     DEFW    CLREOL    ;CTL-X IS CLEAR TO END-OF-LINE
  1749.     DEFW    CLRSCN    ;CTL-Z IS CLEAR SCREEN
  1750.     DEFW    ESCAPE    ;CTL-[ IS ESCAPE
  1751.     DEFW    HOMEUP    ;CTL-^ IS HOME UP
  1752.     DEFW    STUFF    ;CTL-_ IS DISPLAY CONTROL CHARS
  1753.  
  1754. CTLSIZ    EQU    $-CTLTAB
  1755. ;
  1756. ;
  1757. ESCAPE:    LD    A,1
  1758.     LD    (DE),A    ;SET LEAD-IN SEQUENCE STATE
  1759.     RET         ; FOR XY CURSOR POSITIONING MODE
  1760. ;
  1761. ;
  1762. STUFF:    LD    A,4
  1763.     LD    (DE),A    ;SET LEAD-IN SEQUENCE STATE
  1764.     RET        ; FOR CONTROL CHAR OUTPUT MODE
  1765. ;
  1766. ;
  1767. BAKSPC    LD    A,L    ;CHECK FOR LEFT MARGIN
  1768.     AND    01111111B
  1769.     RET    Z    ;ABORT IF IN LEFTMOST COLUMN
  1770.     DEC    HL    ;BACK UP CURSOR POINTER
  1771.     RET
  1772. ;
  1773. ;
  1774. FORSPC:    LD    A,L    ;CHECK FOR RIGHTMOST COLUNM
  1775.     AND    01111111B
  1776.     CP    79
  1777.     RET    NC    ;DO NOTHING IF ALREADY THERE
  1778.     INC    HL
  1779.     RET        ;ELSE ADVANCE THE CURSOR POINTER
  1780. ;
  1781. ;
  1782. TAB:    LD    DE,8    ;TABS ARE EVERY 8 COLUMNS
  1783.     LD    A,L    ;GET COLUMN COMPONENT OF
  1784.     AND    01111000B ; PREVIOUS TAB POSITION
  1785.     ADD    A,E
  1786.     CP    80    ;EXIT IF NEXT TAB COLUMN WOULD
  1787.     RET    NC    ; BE PAST THE RIGHT MARGIN
  1788.     LD    A,L
  1789.     AND    11111000B ;ELSE INCREMENT THE CURSOR
  1790.     LD    L,A      ; POINTER FOR REAL
  1791.     ADD    HL,DE
  1792.     RET
  1793. ;
  1794. BELL:
  1795.     IF    NOT CACHE
  1796.  
  1797.     IN    A,(BITDAT)
  1798.     SET    4,A      ;TOGGLE BIT 5 OF SYSTEM PIO TO
  1799.     OUT    (BITDAT),A ;TRIGGER BELL HARDWARE TO SOUND
  1800. ;Now delay for 120msec
  1801.     PUSH    BC
  1802.     LD    B,120    ;msec
  1803. LPX2:    LD    C,8AH
  1804. LPX3:    NOP
  1805.     NOP
  1806.     NOP
  1807.     DEC    C
  1808.     JR    NZ,LPX3
  1809.     DJNZ    LPX2
  1810.     POP    BC    ;Done delay
  1811.     RES    4,A
  1812.     OUT    (BITDAT),A
  1813.     RET
  1814.     ENDIF    ;NOT CACHE
  1815.  
  1816.     IF    CACHE
  1817.  
  1818.     IN    A,PIOBDAT    ;We use GPPIO bit 7
  1819.     RES    7,A
  1820.     OUT    PIOBDAT,A
  1821. ;Now delay for 120msec
  1822.     PUSH    BC
  1823.     LD    B,120
  1824. LPZ2:    LD    C,8AH
  1825. LPZ3:    NOP
  1826.     NOP
  1827.     NOP
  1828.     DEC    C
  1829.     JR    NZ,LPZ3
  1830.     DJNZ    LPZ2
  1831.     POP    BC
  1832.     SET    7,A
  1833.     OUT    PIOBDAT,A
  1834.     RET
  1835.     ENDIF    ;CACHE
  1836. ;
  1837. ;
  1838. RETURN:    LD    A,L
  1839.     AND    10000000B
  1840.     LD    L,A    ;MOVE CURSOR POINTER BACK
  1841.     RET        ; TO START OF LINE
  1842. ;
  1843. ;
  1844. ; Now clear the screen
  1845. CLRSCN:    IN    A,(BITDAT)
  1846.     SET    7,A
  1847.     OUT    (BITDAT),A    ;Select CRT bank
  1848.     LD    HL,CRTMEM
  1849.     PUSH    HL
  1850.     LD    DE,CRTMEM+1
  1851.     LD    BC,24*128
  1852.     LD    (HL),' '
  1853.     LDIR        ;FILL CRT MEMORY WITH SPACES
  1854.     POP    HL    ;POINT TO HOME CURSOR POSITION
  1855.     LD    A,23
  1856.     LD    (BASE),A ;MAKE BASE LINE# BE 23 AND
  1857.     OUT    (SCROLL),A ; STORE IN SCROLL REGISTER
  1858.     RET
  1859. ;
  1860. ;
  1861. CLREOL:    PUSH    HL    ;SAVE CURSOR POINTER
  1862.     LD    A,L
  1863.     AND    01111111B ;GET COLUMN# COMPONENT OF
  1864.     LD    C,A    ; CURSOR POINTER INTO C
  1865.     LD    A,80    ;CALCULATE HOW MANY CHARACTERS
  1866.     SUB    C    ; REMAIN ON CURRENT LINE
  1867.     LD    B,A
  1868.     CALL    CLR    ;CLEAR REST OF LINE @ HL
  1869.     POP    HL
  1870.     RET
  1871. ;
  1872. ;
  1873. CLREOS:    CALL    CLREOL    ;CLEAR REMAINDER OF CURRENT ROW
  1874.     PUSH    HL
  1875.     LD    A,(BASE)
  1876.     LD    C,A    ;COPY BASE SCREEN ROW# TO C
  1877. CLRS1:    LD    A,L
  1878.     RLA
  1879.     LD    A,H
  1880.     RLA        ;GET ROW# COMPONENT OF HL INTO A
  1881.     AND    00011111B
  1882.     CP    C  ;SEE IF HL IS AT BOTTOM ROW OF SCREEN
  1883.     JR    Z,CLRS2    ; AND LEAVE CLEAR LOOP IF SO
  1884.     CALL    DNCSR    ;ELSE POINT HL TO NEXT ROW DOWN
  1885.     CALL    CLRLIN    ; AND FILL THAT LINE WITH SPACES
  1886.     JR    CLRS1
  1887.  
  1888. CLRS2:    POP    HL    ;RESTORE ORIGINAL CURSOR POINTER
  1889.     RET
  1890. ;
  1891. ;
  1892. UPCSR:    LD    DE,-128    ;SUBTRACT 1 FROM ROW# COMPONENT
  1893.     ADD    HL,DE    ; OF CURSOR POINTER IN HL
  1894.     LD    A,H
  1895.     CP    CRTBAS    ;CHECK FOR UNDERFLOW OF POINTER
  1896.     RET    NC
  1897.     LD    H,CRTTOP-1 ;WRAP CURSOR AROUND MODULO 3K
  1898.     RET
  1899. ;
  1900. ;
  1901. DNCSR:    LD    DE,128    ;ADD 1 TO ROW# COMPONENT
  1902.     ADD    HL,DE    ;OF CURSOR POINTER IN HL
  1903.     LD    A,H
  1904.     CP    CRTTOP    ;CHECK FOR OVERFLOW OF POINTER
  1905.     RET    C
  1906.     LD    H,CRTBAS ;RESET POINTER MODULO 128*24
  1907.     RET
  1908. ;
  1909. ;
  1910. ;
  1911. LFEED:    LD    A,L
  1912.     RLA
  1913.     LD    A,H
  1914.     RLA        ;EXTRACT ROW# COMPONENT OF HL
  1915.     AND    00011111B
  1916.     LD    C,A    ;COPY ROW# INTO C FOR SCROLL TEST
  1917.     CALL    DNCSR    ;MOVE CURSOR TO NEXT ROW DOWN
  1918.     LD    A,(BASE) ;TEST IF CURSOR WAS ON BOTTOM ROW
  1919.     CP    C    ; OF SCREEN BEFORE MOVING DOWN
  1920.     RET    NZ    ;EXIT IF NOT AT BOTTOM
  1921.  
  1922.     PUSH    HL    ;ELSE PREP TO SCROLL SCREEN UP
  1923.     CALL    CLRLIN    ;FILL NEW BOTTOM LINE WITH SPACES
  1924.     ADD    HL,HL
  1925.     LD    A,H    ;GET ROW# COMPONENT OF HL INTO A
  1926.     AND    00011111B
  1927.     LD    (BASE),A ;STORE NEW BASE LINE#
  1928.     OUT    (SCROLL),A ;NOW SCROLL UP NEW BLANK BOTTOM LINE
  1929.     POP    HL
  1930.     RET
  1931. ;
  1932. ;
  1933. CLRLIN:    LD    A,L
  1934.     AND    10000000B ;POINT HL TO FIRST COLUMN OF ROW
  1935.     LD    L,A
  1936.     LD    B,80
  1937. CLR:    LD    (HL),' ' ;STORE ASCII SPACES AT ADDRESS IN HL
  1938.     INC    HL     ; AND INCREMENT HL
  1939.     DJNZ    CLR     ;REPEAT NUMBER OF TIMES GIVEN BY B
  1940.     RET
  1941. ;
  1942. ;
  1943. HOMEUP:    LD    C,' ' ;FAKE-OUT CURSOR ADDRESSING ROUTINE
  1944.     JR    SETROW    ; TO DO HOMEUP ALMOST FOR FREE
  1945. ;
  1946. ;
  1947. MULTI:    EX    DE,HL ;UNCONDITIONALLY RESET THE LEAD-IN
  1948.     LD    (HL),0 ; STATE TO ZERO BEFORE GOING ON
  1949.     EX    DE,HL
  1950.     CP    1
  1951.     JR    NZ,M2TST
  1952. SETXY:    LD    A,C    ;GET SECOND CHAR OF SEQUENCE
  1953.     CP    '='
  1954.     RET    NZ    ;ABORT SEQUENCE IF NOT '='
  1955.     LD    A,2
  1956.     LD    (DE),A    ;MAKE LEADIN=2 NEXT TIME
  1957.     RET
  1958.  
  1959. M2TST:    CP    2
  1960.     JR    NZ,M3TST
  1961.     LD    A,3
  1962.     LD    (DE),A    ;MAKE LEADIN=3 NEXT TIME
  1963. SETROW:    LD    A,(BASE) ;ARRIVE HERE ON THIRD CHARACTER
  1964.     ADD    A,C     ; OF ESC,'=',ROW,COL SEQUENCE
  1965.     SUB    ' '-1
  1966. SETR2:    SUB    24
  1967.     JR    NC,SETR2 ;MAKE SURE ROW# IS BETWEEN 0 AND 23
  1968.     ADD    A,24
  1969.     OR    CRTMEM SHR 7 ;MERGE IN MSB'S OF CRT MEMORY
  1970.     LD    H,A
  1971.     LD    L,0
  1972.     SRL    H
  1973.     RR    L
  1974.     RET
  1975.  
  1976. M3TST:    CP    3
  1977.     JR    NZ,M4TST
  1978. SETCOL:    LD    A,C        ;ARRIVE HERE ON FOURTH CHARACTER
  1979.     SUB    ' '        ; OF ESC,'=',ROW,COL SEQUENCE
  1980. SETC2:    SUB    80
  1981.     JR    NC,SETC2    ;MAKE SURE COL# IS BETWEEN 0 AND 79
  1982.     ADD    A,80
  1983.     OR    L        ;MERGE IN COL# WITH L
  1984.     LD    L,A
  1985.     RET
  1986.  
  1987. M4TST:    CALL    DISPLA        ;DISPLAY THE CONTROL CHARACTER
  1988.     RET            ; PASSED IN C
  1989. ;
  1990. ;
  1991. ;
  1992. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1993. ;    FILTER FOR CDOS SYSTEM CALLS
  1994. ;    LAST CHANGE    12:Mar:81
  1995. ;
  1996. ;    Written by Steve Hope, Trevor Marshall,
  1997. ;        Wait-Aid, Western Australia
  1998. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1999. ;
  2000. FILTER:
  2001.     PUSH    AF
  2002.     LD    A,C
  2003.     CP    80H        ;CP/M 0-80H
  2004.     JR    GE,CDOS        ;CHK IF CDOS COMPATIBLE
  2005.     CP    2        ;WRITE CONSOL NEEDS EXTRA CARE,A must be kept
  2006.     JR    Z,SYSC2
  2007.     CP    11    ;Console status must return all
  2008.     JR    Z,SYSC11
  2009.     CP    15    ;Open file must zero (DE)+32 (current record)
  2010.     CALL    Z,SYSC15
  2011.     POP    AF        ;FIX STACK
  2012.     LD    (PARAM1),HL    ;save temporarily
  2013.     LD    (PARAM2),DE
  2014.     LD    (PARAM3),BC
  2015.     CALL    BDOS+0BH    ;Usually E011, Go execute BDOS
  2016.     LD    BC,(PARAM3)
  2017.     LD    DE,(PARAM2)
  2018.     PUSH    AF
  2019.     LD    A,C        ;Check functions which return values in HL
  2020.     CP    27    ;Max 1.4 FN
  2021.     JR    GE,RET67 ;All higher return HL
  2022.     CP    24    ;login code
  2023.     JR    EQ,RET67
  2024.     CP    12    ;Get version
  2025.     JR    EQ,RET67
  2026.     LD    HL,(PARAM1)
  2027. RET67:
  2028.     POP    AF
  2029.     RET
  2030. ;
  2031. SYSC2:
  2032.     LD    (SPSAV),SP    ;the CP/M DIR command always bombs
  2033.     LD    SP,STACK    ;due to stack overflow unless
  2034.     LD    A,E        ;we give it some help
  2035.     CALL    CONOUT    ;Destroys nothing
  2036.     LD    SP,(SPSAV)
  2037.     POP    AF
  2038.     RET
  2039. ;
  2040. SYSC11: POP    AF
  2041.     CALL    CPMST
  2042.     OR    A
  2043.     RET    Z    ;Don't alter HL unless we have to
  2044.     LD    L,A    ; required for CP/M compatibility
  2045.     RET
  2046. ;
  2047. SYSC15: PUSH    HL    ;This is required
  2048.     LD    HL,32    ; for CDOS
  2049.     ADD    HL,DE
  2050.     LD    (HL),0
  2051.     POP    HL
  2052.     RET    ;thence to BDOS
  2053. ;
  2054. CDOS:    
  2055.     CP    80H        ;READ NO ECHO
  2056.     JR    Z,RNEC
  2057.     CP    82H        ;Set CTL-C abort (it doesn't)
  2058.     JR    Z,SYSC82
  2059.     CP    86H        ;FORMAT NAME TO FCB
  2060.     JR    Z,FFCB
  2061. ;    CP    8EH        ;CRT FUNCTION (XY POS)
  2062. ;    JP    Z,CRT
  2063.     CP    89H        ;MULTIPLY INTEGERS
  2064.     JP    Z,MULT
  2065.     CP    8AH        ;DIVIDE INTEGERS
  2066.     JP    Z,DIVIDE
  2067.     CP    8BH
  2068.     JP    Z,HOME        ;Home selected disk
  2069.     CP    8DH        ;Get version
  2070.     JP    Z,GETVERSION
  2071.     CP    90H        ;Read date
  2072.     JR    Z,READ.DATE
  2073.     CP    92H        ;Read time of day
  2074.     JR    Z,READ.DATE    ;Return zero, same as 90H
  2075.     CP    96H        ;Turn motors off
  2076.     JR    Z,MOTORS.OFF
  2077.     POP    AF        ;FIX STACK
  2078.     JP    CALLERR    ;ELSE ERROR FOR NOW
  2079. ;
  2080. RNEC:                ;READ NO ECHO
  2081.     POP    AF        ;FIX STACK
  2082.     JP    CPMIN    ;And return with char in acc.
  2083. ;
  2084. READ.DATE: POP    AF
  2085.     XOR    A    ; A=0
  2086.     LD    C,A
  2087.     LD    B,A    ;BC=0
  2088.     RET        ;***Done ***
  2089. ;
  2090. MOTORS.OFF: IN    A,(BITDAT)
  2091.     OR    A,01000100B ;Motors off, drive deselected
  2092.     OUT    (BITDAT),A
  2093. SYSC82:    POP    AF
  2094.     RET
  2095.  
  2096. ;;;
  2097. FFCB:    
  2098.     POP    AF        ;FIX STACK
  2099.     PUSH    DE        ;SAVE DE
  2100.     LD    B,(HL)        ;GET FIRST CHAR
  2101.     INC    HL
  2102.     LD    A,(HL)
  2103.     CP    ':'        ;CHK IF DRIVE
  2104.     JR    NZ,NOCOL
  2105.     INC    HL        ;PAST COL
  2106.     LD    A,7
  2107.     AND    B        ;DRV #
  2108.     JR    FBYTE
  2109. NOCOL:    DEC    HL
  2110.     XOR    A        ;DEFAULT DRV
  2111. FBYTE:    
  2112.     LD    (DE),A
  2113.     INC    DE
  2114.     LD    B,8
  2115. ;
  2116. NAME1:
  2117.     LD    A,(HL)
  2118.     CP    '*'
  2119.     JR    EQ,FILLWILD
  2120.     CP    21H
  2121.     JR    C,FILLL1
  2122.     INC    HL
  2123.     CP    '.'
  2124.     JR    Z,FILLL1
  2125.     LD    (DE),A
  2126.     INC    DE
  2127.     DJNZ,NAME1
  2128.     JR    EX1
  2129. FILLWILD:
  2130.     LD    A,'?'
  2131.     LD    (DE),A
  2132.     INC    DE
  2133.     DJNZ    FILLWILD
  2134.     JR    EX1
  2135. FILLL1:    
  2136.     LD    A,' '
  2137.     LD    (DE),A
  2138.     INC    DE
  2139.     DJNZ,FILLL1
  2140. EX1:
  2141. ;;;;;;
  2142.     LD    A,'.'
  2143.     CP    (HL)
  2144.     JR    NZ,EXT
  2145.     INC    HL
  2146. EXT:    LD    B,3
  2147. NAME2:    
  2148.     LD    A,(HL)
  2149.     CP    '*'
  2150.     JR    EQ,WILDEXT
  2151.     CP    21H
  2152.     JR    C,FILLL2
  2153.     INC    HL
  2154.     CP    '.'
  2155.     JR    Z,FILLL2
  2156.     LD    (DE),A
  2157.     INC    DE
  2158.     DJNZ,NAME2
  2159.     JR    EX2
  2160. WILDEXT: LD    A,'?'
  2161.     LD    (DE),A
  2162.     INC    DE
  2163.     DJNZ    WILDEXT
  2164.     JR    EX2
  2165. FILLL2:    
  2166.     LD    A,' '
  2167.     LD    (DE),A
  2168.     INC    DE
  2169.     DJNZ,FILLL2
  2170. EX2: ;Done, restore ready for exit
  2171.     XOR    A
  2172.     LD    (DE),A
  2173.     POP    DE
  2174.     RET    
  2175.  
  2176.  
  2177. ;CRT:    
  2178. ;    POP    AF        ;FIX STACK
  2179. ;    XOR    A
  2180. ;    CP    E        ;CANT HANDLE ALL
  2181. ;    JR    NZ,CRT3
  2182. ;    LD    A,1AH    ;Clearscreen char
  2183. ;    JP    CRTOUT    ;Neglect all other special fns
  2184. ;CRT3:    PUSH    DE        ;SAVE DE
  2185. ;    CALL    PNEXT
  2186. ;    DB    1BH,'=',EOT
  2187. ;    POP    DE        ;RECOVER DE
  2188. ;    PUSH    DE        ;SAVE AGAIN
  2189. ;    LD    A,1FH
  2190. ;    ADD    E        ;ROW
  2191. ;    CALL    CONOUT
  2192. ;    POP    DE
  2193. ;    PUSH    DE
  2194. ;    LD    A,1FH
  2195. ;    ADD    D        ;COL
  2196. ;    CALL    CONOUT
  2197. ;    POP    DE
  2198. ;    RET    
  2199. ;;;;;;;;;;;;;;;;;;;;;;;;;;
  2200.  
  2201. MULT:                ;DE=HL*DE
  2202.     POP    AF        ;FIX STACK
  2203.     PUSH    BC        ;SAVE REGS
  2204.     PUSH    HL
  2205.     LD    L,16
  2206.     LD    BC,0
  2207. MLOOP:
  2208.     EX    (SP),HL
  2209.     LD    A,1
  2210.     AND    A,E
  2211.     JR    Z,M1
  2212.     PUSH    HL
  2213.     ADD    HL,BC
  2214.     EX    (SP),HL
  2215.     POP    BC
  2216. M1:
  2217.     RR    B
  2218.     RR    C
  2219.     RR    D
  2220.     RR    E
  2221.     EX    (SP),HL
  2222.     DEC    L
  2223.     JR    NZ,MLOOP
  2224.     POP    HL
  2225.     POP    BC
  2226.     RET
  2227.  
  2228.  
  2229. DIVIDE:                ;HL=HL/DE , DE=REMAINDER
  2230.     POP    AF        ;FIX STACK
  2231.     LD    A,D
  2232.     OR    A,E
  2233.     RET    Z        ;DIVIDE BY 0
  2234.     LD    A,D
  2235.     CPL
  2236.     LD    D,A
  2237.     LD    A,E
  2238.     CPL
  2239.     LD    E,A
  2240.     INC    DE        ;2'S COMP
  2241.     PUSH    BC
  2242.     LD    B,H
  2243.     LD    C,L
  2244.     LD    HL,0
  2245.     LD    A,17
  2246. DLOOP:
  2247.     PUSH    HL
  2248.     ADD    HL,DE
  2249.     JR    NC,D1
  2250.     EX    (SP),HL
  2251. D1:
  2252.     POP    HL
  2253.     RL    C
  2254.     RL    B
  2255.     RL    L
  2256.     RL    H
  2257.     DEC    A
  2258.     JR    NZ,DLOOP
  2259.     OR    A,A
  2260.     RR    H
  2261.     RR    L
  2262.     EX    DE,HL
  2263.     LD    H,B
  2264.     LD    L,C
  2265.     POP    BC
  2266.     RET
  2267.  
  2268. ;;;;;;;;
  2269.  
  2270. CALLERR:
  2271.     CALL    PNEXT
  2272.     DEFB    CR,LF,'Illegal system call ',EOT
  2273.     LD    A,C
  2274.     CALL    PUT2HEX
  2275.     CALL    PNEXT
  2276.     DB    ',PC=',EOT
  2277.     POP    HL        ;GET CALL ADDR
  2278.     PUSH    HL        ;REt addr back on stack
  2279.     DEC    HL        ;start
  2280.     DEC    HL
  2281.     DEC    HL
  2282. ;NOW PRINT ADDR OF ILLEGAL CALL
  2283.     CALL    PUT4HS    ;Print calling addres
  2284.     XOR    A    ;Set up return variable values=0
  2285.     LD    BC,0
  2286.     LD    DE,0
  2287.     LD    HL,0
  2288.     RET        ;Hope program will not bomb
  2289. ;
  2290. GETVERSION: POP    AF
  2291.     LD    BC,0107H ;Version 1.07
  2292.     RET
  2293. ;
  2294. ;
  2295. ;
  2296. ;************************************************
  2297. ;*                        *
  2298. ;* DISK INPUT/OUTPUT DRIVER SUBROUTINE PACKAGE    *
  2299. ;* FOR WESTERN DIGITAL 1771 DISK CONTROLLER    *
  2300. ;*                        *
  2301. ;* bullet-proof error recovery added 12-APR-80    *
  2302. ;*                        *
  2303. ;************************************************
  2304. ;
  2305. ;
  2306. ;EQUATES FOR DISK CONTROLLER PORTS AND COMMAND CODES
  2307. ;
  2308. STSREG    EQU    WD1771+0 ;STATUS REGISTER
  2309. CMDREG    EQU    WD1771+0 ;COMMAND REGISTER
  2310. TRKREG    EQU    WD1771+1 ;TRACK REGISTER
  2311. SECREG    EQU    WD1771+2 ;SECTOR REGISTER
  2312. DATREG    EQU    WD1771+3 ;DATA REGISTER
  2313. ;
  2314. RDCMD    EQU    10001000B ;READ COMMAND
  2315. WRTCMD    EQU    10101000B ;WRITE COMMAND
  2316. SKCMD    EQU    00011100B ;SEEK COMMAND
  2317. FINCMD    EQU    11010000B ;FORCE INTR COMMAND
  2318. RSTCMD    EQU    00001100B ;RESTORE COMMAND
  2319. HLOAD    EQU    00000100B ;RD/WRT HEAD LOAD ENABLE
  2320. ;
  2321. RET    EQU    0C9H    ;SUBROUTINE RETURN INSTR OPCODE
  2322. NMIVEC    EQU    0066H    ;THE NON-MASKABLE INTERRUPT IS
  2323.         ;USED FOR DATA SYNCRONIZATION BETWEEN
  2324.         ;THE Z-80 AND 1771 DISK CONTROLLER
  2325. ;
  2326. ;
  2327. ;
  2328. SETSEC:    LD    HL,SECTOR
  2329.     LD    (HL),C
  2330.     XOR    A ;To prevent errors being notified
  2331.     RET
  2332. ;
  2333. SETDMA: LD    (IOPTR),BC
  2334.     XOR    A
  2335.     RET
  2336. ;
  2337. ;
  2338. SECTRAN: EX    DE,HL    ;ADD TRANSLATION TABLE ADDRESS
  2339.     ADD    HL,BC    ; PASSED IN DE TO SECTOR# IN BC
  2340.     LD    L,(HL)
  2341.     LD    H,0    ;LOOKUP PHYSICAL SECTOR NUMBER
  2342.     XOR    A
  2343.     RET        ; AND RETURN IT IN HL
  2344. ;
  2345. ;
  2346. SELECT:    LD    HL,0    ;In case of error exit    
  2347.     LD    A,C    ;GET UNIT# PASSED IN C AND
  2348.     CP    2    ; CHECK FOR MAXIMUM VALID#
  2349.     RET    NC    ;ERROR IF NUMBER > 1
  2350. ;
  2351.     LD    (SAVE.DRIVE),A ;Stash Unit# for DOSELECT later
  2352. ; check that it is logged
  2353.     LD    HL,TRKTAB ;Calculate trk ptr of requested drive
  2354.     LD    A,L
  2355.     ADD    C
  2356.     LD    L,A    ;Now pointing at the modified byte
  2357.     LD    A,(HL)    ;Has this drive been logged on?
  2358.     CP    0FFH
  2359.     LD    A,C    ;Get new dsk# to A ready for RET21
  2360.     JR    NE,RET21 ;Only a number of FF indicates not logged
  2361.              ;so if anything else make no hardware changes yet
  2362.              ;If the drive is not logged we had better do so, as
  2363.              ; BDOS expects DPB info on its size
  2364.     CALL    DOSELECT
  2365.     RET
  2366. ;
  2367. ;
  2368. DOSELECT: 
  2369.     LD    A,(SAVE.DRIVE)
  2370.     LD    C,A
  2371.     LD    HL,UNIT    ;POINT HL TO DRIVE SELECT DATA
  2372.     LD    A,(HL)    ;LOAD A WITH CURRENT UNIT#
  2373.     LD    (HL),C    ; AND STORE NEW UNIT# FROM C
  2374. ;Check if drive is already current
  2375.     LD    E,A    ;Save current #
  2376.     SUB    A,C
  2377.     JR    Z,RET20 ;If so, exit
  2378. ;
  2379.      LD    D,C    ;Save new drive
  2380.     IN    A,(BITDAT)
  2381.     AND    11011000B ;MERGE IN NEW DRIVE UNIT# & side 0
  2382.     OR    C    ; IN PLACE OF THE CURRENT ONE
  2383.     OUT    (BITDAT),A ; TO SELECT THE NEW DISK DRIVE
  2384. ;Delay turnon until an operation is actually requested
  2385. ;    CALL    TURNON    ;After selecting drive
  2386. ;    BIT    7,A     ;TEST DRIVE NOT READY BIT
  2387. ;    JR    Z,SEL2    ; AND CONTINUE IF ITS READY
  2388. ;    LD    HL,0    ;for BDOS
  2389. ;    LD    A,10000000B ;else RETURN DRIVE-NOT-READY STATUS
  2390. ;    OR    A
  2391. ;    RET
  2392. SEL2:
  2393. ;We will store the old track number and RECLEN for later
  2394.     LD    C,D    ;retrieve new drive
  2395.     LD    A,E    ;retrieve original UNIT byte
  2396.     CP    255    ;TEST IF NO DRIVE HAS BEEN SELECTED
  2397. ; Else store last drive's parameters
  2398.     JR    Z,SEL3    ;YET AND SKIP NEXT SEGMENT IF SO
  2399.     INC    HL    ;POINT TO HEAD POSITION TABLE
  2400.     ADD    A,L    ; AND ADD IN OLD UNIT# AS INDEX
  2401.     LD    L,A
  2402.     LD    A,(TRACK) ;Get current track position
  2403.     LD    (HL),A    ; AND STORE IN TABLE @ HL
  2404.     LD    A,TRKTAB.LENGTH ;RECLENTAB next
  2405.     ADD    A,L
  2406.     LD    L,A
  2407.     LD    A,(RECLEN)
  2408.     LD    (HL),A    ;Store it in reclen table
  2409. SEL3:    LD    HL,RECLENTAB
  2410.     LD    A,L
  2411.     ADD    A,C    ;INDEX INTO TABLE TO GET
  2412.     LD    L,A    ; RECLEN OF NEW DRIVE
  2413.     LD    A,(HL)
  2414.     LD    (RECLEN),A
  2415.     LD    A,-TRKTAB.LENGTH ;Now get select data
  2416.     ADD    A,L
  2417.     LD    L,A
  2418.     LD    A,(HL)
  2419.     CP    255    ;TEST IF NEW DRIVE HAS EVER BEEN
  2420.     JR    NE,NXT111 ; SELECTED AND
  2421.     CALL    LOGIN    ;Do a LOGIN if not
  2422.     LD    HL,0    ;for an error exit
  2423.     RET    NZ
  2424. ;If LOGIN fails leave drive logged off,HL=0
  2425. NXT111:    LD    (TRACK),A ;Success,store the current head position
  2426. ;Now wait for a while to allow time for head load solenoid
  2427.     IF    IS5MHZ
  2428.     LD    B,8    ;Loop four times
  2429.     ELSE
  2430.     LD    B,4
  2431.     ENDIF    ;IS5MHZ
  2432.  
  2433. LP124:    IN    A,CTC3    ;Get current CTC3 value
  2434.     LD    C,A    ;Save it
  2435. LP123:    IN    A,CTC3
  2436.     CP    C    ;Loop until it has changed
  2437.     JR    NZ,LP123 ;The first may be a short cycle
  2438.     DJNZ    LP124    ;the rest will be a full 5.5 msec at 5MHz
  2439. ;
  2440. RET20:    LD    A,(UNIT) ;get current unit
  2441. RET21:    LD    H,0
  2442.     LD    L,A    ;Calculate DPHB addr
  2443.     ADD    HL,HL
  2444.     ADD    HL,HL
  2445.     ADD    HL,HL
  2446.     ADD    HL,HL    ;MULTIPLY UNIT# BY 16
  2447.     LD    DE,DPBASE
  2448.     ADD    HL,DE    ;ADD START ADDRESS OF DHP BLOCK
  2449.     XOR    A    ;No errors, HL points to DPBASE
  2450.     RET
  2451. ;
  2452. ;
  2453. ;
  2454. ; We log the disks in under HOME
  2455. ; Home aways in S/D
  2456. ;
  2457. HOME:
  2458.     CALL    DOSELECT
  2459.     RET    NZ
  2460. ;
  2461.     IN    A,(BITDAT)
  2462.     SET    3,A    ;select S/D
  2463.     RES    5,A    ;select side 0
  2464.     OUT    (BITDAT),A
  2465. ;
  2466.     CALL    TURNON    ;CLEAR DISK CONTROLLER
  2467.     AND    10000001B ;Mask statuses
  2468.     RET    NZ
  2469. RESTOR:    LD    A,RSTCMD ;LOAD B WITH A RESTORE COMMAND
  2470.     CALL    CMDOUT
  2471.     AND    10011000B ;Mask off TRK 0 status
  2472.     LD    (TRACK),A ;SET TRACK# IN MEM TO ZERO (A is 0)
  2473.     RET    ;If any errors trk# is wrong
  2474. ;
  2475. ;LOGIN checks the disk density
  2476. ;
  2477. LOGIN:    CALL    HOME
  2478.     RET    NZ
  2479.  
  2480. ;Now log on the disk to see if it is double or single density
  2481.     INC    A    ;read sector 1
  2482.     LD    (SECTOR),A
  2483. ;
  2484.     LD    HL,(IOPTR)
  2485.     LD    (OLDPTR),HL
  2486.     LD    HL,LOGBUF ;default dsk buffer
  2487.     LD    (IOPTR),HL
  2488. ;
  2489.     LD    A,80H    ;Bit 7 set to indicate LOGread
  2490.     LD    (RECLEN),A ;Default S/D
  2491.     CALL    READ
  2492. ;
  2493.     LD    HL,(OLDPTR) ;Restore previos DMA addr
  2494.     LD    (IOPTR),HL
  2495.     RET    NZ    ;to DSKERR
  2496. ;
  2497.     LD    HL,LOGBUF ;look for 'DS' on the label
  2498.     LD    A,'D'
  2499.     CP    (HL)
  2500.     JR    NE,SINGLED
  2501.     INC    HL
  2502.     LD    A,'S'
  2503.     CP    (HL)
  2504.     JR    NE,SINGLED
  2505. ; If we are here then it is at least double sided
  2506.     INC    HL
  2507.     LD    A,'D'
  2508.     CP    (HL)
  2509.     JR    NE,DOUBLES
  2510.     INC    HL
  2511.     CP    (HL)
  2512.     JR    NE,DOUBLES
  2513. ;Here it must be double sided double density
  2514.     LD    A,11B    ;128 bytes/sector +D/D + D/S
  2515.     JR    SD2
  2516. DOUBLES: LD    A,10B    ;128 bytes/sector +D/S
  2517.     JR    SD2
  2518. ; Load the sector length/2 for read/writes
  2519. SINGLED: LD    A,00B ;128 bytes/sector
  2520. SD2:    LD    (RECLEN),A
  2521. ;Now we must change the Disk Parameter Blocks
  2522.     LD    HL,DPB0    ;The D/D disk parameter block
  2523.     LD    BC,XLT0 ;The D/D interleave table
  2524.     BIT    0,A    ;Test D/D flag
  2525.     JR    NZ,SETPATCH ;If D/D then use those values
  2526.     LD    HL,DPB1    ;Else load D/S values
  2527.     LD    BC,XLT1
  2528.     BIT    1,A    ;Test D/S flag
  2529.     JR    NZ,SETPATCH
  2530.     LD    HL,DPB2    ;Else load S/D DPBlk
  2531. SETPATCH: ;Now have to calculate the patch address to use
  2532.     LD    A,(UNIT)
  2533.     OR    A    ;Is it A:? (DPE0)
  2534.     JR    NZ,NEXTPATCH ;No, patch DPE1
  2535.     LD    (PATCH1),BC
  2536.     LD    (PATCH2),HL
  2537.     JR    DONEPATCH
  2538. NEXTPATCH: LD    (PATCH3),BC
  2539.     LD    (PATCH4),HL    
  2540. DONEPATCH:
  2541.     XOR    A
  2542.     RET
  2543. ;
  2544. ;
  2545. ;
  2546. SEEK:
  2547.     PUSH    BC    ;Save trk #
  2548.     CALL    DOSELECT
  2549.     POP    BC
  2550.     RET    NZ
  2551.  
  2552.     CALL    TURNON    ;CLEAR DISK CONTROLLER
  2553.     BIT    7,A
  2554.     RET    NZ    ;EXIT IF DRIVE NOT READY
  2555.     LD    A,(TRACK) ;Get current track#
  2556.     OUT    TRKREG,A ;to the 1771
  2557.     LD    HL,RECLEN ;Dont do next if D/D
  2558.     BIT    1,(HL)    ;is it D/D ?
  2559.     SCF        ;clr Carry
  2560.     CCF        ;ready to select side 0
  2561.     JR    Z,SK1    ;skip track/side calculation if S/D
  2562.     RR    C    ;now carry is side#, track is in C
  2563. ;PA5 is side select
  2564. SK1:    IN    A,(BITDAT)    ;get side select mask
  2565.     RES    5,A    ;default side 0 again
  2566.     LD    B,0    ;use B as carry mask
  2567.     RR    B    ;carry into b7 of B
  2568.     RR    B
  2569.     RR    B    ;now in b5 of B
  2570.      OR    A,B    ;OR BITDAT with B, the side select mask
  2571.     LD    B,A    ;save BITDAT (A) to B
  2572. ;Are we reading a single or double density track?
  2573.     SET    3,B    ;set up BITDAT mask for S/D
  2574.     BIT    5,B    ;test side bit for side 1
  2575.     JR    NZ,SK2    ;so that trk 0, side 0 is always S/D
  2576.     LD    A,C
  2577.     OR    A    ;On side 0, is the trk # also = 0 ?
  2578.     JR    Z,NSKP    ;yes, always make trk 0, side 0, S/D
  2579. SK2:    BIT    0,(HL)    ;(RECLEN) (Z=S/D)
  2580. ;    SET    3,B    ;DD* bit is reset ready for single density
  2581.     JR    Z,NSKP    ; exit calculation if single density disk
  2582.     RES    3,B    ;here it must be DD
  2583. NSKP:    LD    A,B    ;(get BITDAT mask back to A ready for)
  2584.     OUT    (BITDAT),A
  2585.  
  2586.     LD    A,(TRACK) ;GET old TRACK#
  2587.     SUB    C    ;Is new trk the same as the last?
  2588.     RET    Z    ;Yes,return with 0 in A
  2589.  
  2590.     LD    A,C    ;get new trk#
  2591.     LD    (TRACK),A ; STORE TRACK# FOR SEEK
  2592.     OUT    (DATREG),A ;OUTPUT TRACK # TO 1771
  2593.     LD    A,SKCMD    ;LOAD A WITH A SEEK COMMAND AND
  2594.     CALL    CMDOUT
  2595.     AND    10011000B ;MASK TO READY,SEEK AND CRC ERROR
  2596.     PUSH    AF
  2597. ;
  2598. ;Now a short delay to allow head to settle
  2599.     IF    IS5MHZ
  2600.     LD    B,6    ;Loop 6 times at 5MHz
  2601.     ELSE
  2602.     LD    B,3
  2603.     ENDIF    ;IS5MHZ
  2604.  
  2605. LP24:    IN    A,CTC3    ;Get current CTC3 value
  2606.     LD    C,A    ;Save it
  2607. LP23:    IN    A,CTC3
  2608.     CP    C    ;Loop until it has changed
  2609.     JR    NZ,LP23 ;The first loop may be a short cycle
  2610.     DJNZ    LP24    ;the rest will be a full 5.5 msec at 5MHz
  2611. ;
  2612.     POP    AF
  2613.     RET        ;RETURN FINAL SEEK STATUS IN A
  2614. ;
  2615. ;
  2616. ;We wont check if drive ready here, error handler will fix any exceptions
  2617. ;Famous last words, system lost speed if following call to TURNON was omitted==
  2618. WRITE:    PUSH    HL    ;HL is required for SELECT errors
  2619.     CALL    TURNON
  2620. ; If disk is write protected prompt now
  2621.     BIT    6,A
  2622.     JP    Z,NXT571 ;Z = OK
  2623.     CALL    PNEXT    ;Print to console
  2624.     DB    CR,LF,7,'Disk is write protected',EOT
  2625.     CALL    CPMIN    ;Get any key to acknowledge message
  2626.     CALL    TURNON    ;Operator may be asleep
  2627. NXT571:    AND    11000001B
  2628.     POP    HL
  2629.     RET    NZ    ;EXIT IF DRIVE NOT READY or still protected
  2630.     LD    B,WRTCMD
  2631.     JR    RDWRT
  2632.  
  2633. READ:
  2634.     PUSH    HL
  2635.     CALL    TURNON
  2636.     AND    10000001B
  2637.     POP    HL
  2638.     RET    NZ    ;EXIT IF DRIVE NOT READY
  2639.     LD    B,RDCMD
  2640. RDWRT:    LD    HL,CMDTYP
  2641.     LD    (HL),B    ;SAVE READ/WRITE COMMAND BYTE
  2642.     INC    HL
  2643.     LD    (HL),4    ;SET DISK OPERATION RE-TRY COUNT
  2644. RW1:    CALL    SETUPNMI
  2645. ;Are we reading a single or double density track?
  2646.     LD    B,80H    ;set up B for S/D
  2647. SK4:            ;B=NUMBER OF BYTES/SECTOR
  2648.     LD    C,DATREG ;C=1771 DATA REGISTER PORT#
  2649.     LD    A,(SECTOR) ;GET SECTOR NUMBER
  2650.     OUT    (SECREG),A ;OUTPUT SECTOR# TO 1771
  2651.     CALL    FORCE     ;ISSUE A FORCE INTERRUPT COMMAND
  2652.     BIT    5,A     ; TO TEST CURRENT HEAD LOAD STATUS
  2653.     LD    A,(CMDTYP) ;GET READ OR WRITE COMMAND BYTE
  2654.     JR    NZ,RW2    ;JUMP IF HEAD IS ALREADY LOADED
  2655.     OR    HLOAD    ; ELSE MERGE IN HLD BIT
  2656. RW2:
  2657.     LD    HL,RECLEN
  2658.     BIT    7,(HL)
  2659.  
  2660.     LD    HL,(IOPTR) ;Set up DMA pointer
  2661.     OUT    CMDREG,A ;START the 1771 reading/writing
  2662.  
  2663.     JP    NZ,LOGLOOP    ;Reclen test above
  2664.  
  2665.     BIT    5,A    ;TEST IF COMMAND IS A READ OR WRITE
  2666.     JR    NZ,WLOOP ; AND JUMP TO THE CORRECT LOOP
  2667.  
  2668. RLOOP:    HALT
  2669.     INI        
  2670.     JP    NZ,RLOOP
  2671. RW6:    CALL    IRQ2
  2672.     AND    10011100B ;MASK OFF TO READY, NOT FOUND, CRC
  2673.     JR    RW3    ; AND LOST DATA STATUS BITS
  2674. ;
  2675. LOGLOOP: LD    B,7AH    ;Bytes to discard
  2676. LPZY2:    HALT
  2677.     IN    A,(C)
  2678.     DJNZ    LPZY2 ;Speed not important as only S/D
  2679.     LD    B,6
  2680. LPZY3:    HALT    ;Now collect the data bytes
  2681.     INI
  2682.     JP    NZ,LPZY3
  2683.     JR    RW6
  2684. ;
  2685. WLOOP:    HALT
  2686.     OUTI
  2687.     JP    NZ,WLOOP
  2688.     CALL    IRQ2
  2689.     AND    11111100B ;MASK OFF AS ABOVE PLUS WRITE FAULT
  2690. RW3:    RET    Z    ;RETURN IF NO DISK I/O ERRORS
  2691.     LD    HL,RETRY
  2692.     DEC    (HL)    ;DECREMENT RE-TRY COUNT AND
  2693.     JR    NZ,RW1    ;Execute command again if not=0
  2694.     OR    A
  2695.     RET        ;ELSE RETURN 1771 ERROR STATUS
  2696.  
  2697. ;
  2698. ;
  2699. ;Forcing a D1 interrupt here hangs (197X app p3) 
  2700. CMDOUT: OUT    CMDREG,A ;Output the command
  2701.     CALL    SETUPNMI
  2702. IRQ2:    HALT
  2703.     CALL    RESTORENMI
  2704.     IN    A,STSREG
  2705.     RET
  2706. ;
  2707. FORCE:    LD    A,FINCMD
  2708.     OUT    CMDREG,A
  2709. LP7:    IN    A,STSREG
  2710.     BIT    0,A    ;Still busy?
  2711.     JR    NZ,LP7
  2712.     RET
  2713. ;
  2714. SETUPNMI: DI
  2715.     LD    HL,NMIVEC
  2716.     LD    D,(HL)
  2717.     LD    A,0C9H
  2718.     LD    (HL),A
  2719.     RET
  2720. ;
  2721. RESTORENMI: LD    HL,NMIVEC
  2722.     LD    (HL),D
  2723.     EI
  2724.     RET
  2725. ;
  2726. TURNON:    
  2727.     LD    A,30
  2728.     LD    (MOTOR),A ;RE-LOAD THE MOTOR TURN-OFF TIMER
  2729. ;Just testing the motors status here is no good if 
  2730. ;  a new drive has just been selected
  2731. ; Test to see if new drive is ready here
  2732.     CALL    FORCE
  2733. ;    AND    11011001B    ;do in main routines
  2734.     BIT    7,A    ;Ready?
  2735.     RET    Z    ; AND EXIT IF STILL TURNED ON
  2736.     IN    A,(BITDAT)
  2737.     AND    11111011B ;ELSE RE-ENABLE THE DRIVE SELECTS
  2738.     OUT    (BITDAT),A ; AND ACTIVATE THE MOTOR RELAY
  2739.     PUSH    BC
  2740.     LD    B,0 ;SET READY LOOP MAX TIMEOUT
  2741. ;
  2742. TURN2:    CALL    WAIT    ;WAIT 1/93 SECOND AND TEST READY
  2743.     RLA    ;Test the ready status bit
  2744.     JR    NC,TURN3 ;EXIT LOOP IF DRIVE READY
  2745.     DJNZ    TURN2    ; ELSE TRY AGAIN UP TO 256 TIMES
  2746. TURN3:    LD    B,4
  2747. TURN4:    CALL    WAIT    ;GIVE ABOUT 1/20 SECOND MORE DELAY
  2748.     DJNZ    TURN4    ;to ensure no CRC errors
  2749. ;    CALL    FORCE    ;Done in WAIT
  2750. ;    AND    11011001B ;do in main routines
  2751.     POP    BC
  2752.     RET
  2753. ;
  2754. ;
  2755. WAIT:    IN    A,(CTC3) ;GET CURRENT CTC3 COUNT VALUE
  2756.     LD    C,A
  2757. WAIT2:    IN    A,(CTC3)
  2758.     CP    C    ;TEST IF CTC3 HAS CHANGED BY 1 COUNT
  2759.     JR    Z,WAIT2    ; AND LOOP UNTIL IT CHANGES
  2760.     JR    FORCE    ; THEN GO TEST DRIVE READY STATUS
  2761. ;
  2762. ;
  2763. ;****************************************
  2764. ;*                    *
  2765. ;* DISK I/O BUFFER, PARAMETER TABLES    *
  2766. ;*                    *
  2767. ;****************************************
  2768. ;
  2769. DPBASE    EQU    $    ;BASE OF DISK PARAMETER BLOCKS
  2770. ;Use two Single Sided Single Density Blocks
  2771. ;Which can be patched as required
  2772. DPE0:
  2773. PATCH1:    DW    XLT1,0000H    ;TRANSLATE TABLE
  2774.     DW    0000H,0000H    ;SCRATCH AREA
  2775.     DW    DIRBUF
  2776. PATCH2:    DW    DPB2    ;DIR BUFF,PARM BLOCK
  2777.     DW    CSV0,ALV0    ;CHECK, ALLOC VECTORS (Use largest ones always)
  2778. DPE1:
  2779. PATCH3:    DW    XLT1,0000H    ;TRANSLATE TABLE
  2780.     DW    0000H,0000H    ;SCRATCH AREA
  2781.     DW    DIRBUF
  2782. PATCH4:    DW    DPB2    ;DIR BUFF,PARM BLOCK
  2783.     DW    CSV1,ALV1    ;CHECK, ALLOC VECTORS
  2784. ;
  2785. ; DOUBLE DENSITY DOUBLE SIDED
  2786. ;    DISKDEF    0,1,34H,4,4096,(77-2)*2*52/32,192,192,2
  2787. DPB0    EQU    $        ;DISK PARM BLOCK
  2788.     DW    52        ;SEC PER TRACK
  2789.     DB    5        ;BLOCK SHIFT
  2790.     DB    31        ;BLOCK MASK
  2791.     DB    0        ;EXTNT MASK
  2792.     DW    242        ;DISK SIZE-1
  2793.     DW    191        ;DIRECTORY MAX
  2794.     DB    192        ;ALLOC0
  2795.     DB    0        ;ALLOC1
  2796.     DW    48        ;CHECK SIZE
  2797.     DW    2        ;OFFSET
  2798. ;
  2799. ;SINGLE DENSITY DOUBLE SIDED
  2800. ;    DISKDEF 1,1,1AH,6,2048,(77-2)*2*1AH/16,128,128,2
  2801. DPB1    EQU    $        ;DISK PARM BLOCK
  2802.     DW    26        ;SEC PER TRACK
  2803.     DB    4        ;BLOCK SHIFT
  2804.     DB    15        ;BLOCK MASK
  2805.     DB    0        ;EXTNT MASK
  2806.     DW    242        ;DISK SIZE-1
  2807.     DW    127        ;DIRECTORY MAX
  2808.      DB    192        ;ALLOC0
  2809.     DB    0        ;ALLOC1
  2810.     DW    32        ;CHECK SIZE
  2811.     DW    2        ;OFFSET
  2812. ;
  2813. ;SINGLE DENSITY SINGLE SIDED
  2814. ;    DISKDEF 1,1,1AH,6,1024,(77-2)*1AH/8,64,64,2
  2815. DPB2    EQU    $        ;DISK PARM BLOCK
  2816.     DW    26        ;SEC PER TRACK
  2817.     DB    3        ;BLOCK SHIFT
  2818.     DB    7        ;BLOCK MASK
  2819.     DB    0        ;EXTNT MASK
  2820.     DW    242        ;DISK SIZE-1
  2821.     DW    63        ;DIRECTORY MAX
  2822.     DB    192        ;ALLOC0
  2823.     DB    0        ;ALLOC1
  2824.     DW    16        ;CHECK SIZE
  2825.     DW    2        ;OFFSET
  2826. ;
  2827. XLT0:        ;TRANSLATE TABLE (Double Density)
  2828.     DB    1,5,9,13,17,21,25,29,33,37,41,45,49,2,6,10,14,18,22,26,30,34
  2829.     DB    38,42,46,50,3,7,11,15,19,23,27,31,35,39,43,47,51,4,8,12,16,20
  2830.     DB    24,28,32,36,40,44,48,52        
  2831. ;
  2832. XLT1:        ;TRANSLATE TABLE (IBM)
  2833.     DB 1,7,13,19,25,5,11,17,23,3,9,15,21,2,8,14,20,26,6,12,18,24,4,10,16,22
  2834. ;
  2835. DIRBUF:    DS    128    ;DIRECTORY ACCESS BUFFER
  2836. ;
  2837. ALLOCATION.VECTORS: ;Must be zeroed on Warm Boot
  2838. ALV0:    DS    31    ;Double Sided, Double Density
  2839. CSV0:    DS    48
  2840. ;
  2841. ALV1:    DS    31
  2842. CSV1:    DS    48
  2843. VECTORS.LENTH: EQU $-ALLOCATION.VECTORS
  2844. ;
  2845. ;
  2846. ;These are smaller, and not required
  2847. ;ALV:    DS    31    ;Double Sided Single Density 
  2848. ;CSV:    DS    16
  2849. ;ALV:    DS    31    ;Single Sided Single Density same as DSSD
  2850. ;CSV:    DS    16
  2851. ;
  2852. ;
  2853. LOGBUF:    DS    6    ;For logging in disks
  2854. ;
  2855. SAVE.DRIVE: DS    1
  2856. ;
  2857. END.ROM: EQU    $    !Ignore error
  2858. ;
  2859. ;
  2860. ;********************************************************
  2861. ;*                            *
  2862. ;*    STORAGE ALLOCATION FOR 256 BYTE FIXED RAM    *
  2863. ;*                            *
  2864. ;********************************************************
  2865. ;
  2866.     ORG    0FF00H    ;Top page of RAM
  2867. :
  2868. MEM:    EQU    $
  2869. ;
  2870.  
  2871. VECTAB    EQU    $    ;INTERRUPT VECTOR TABLE STARTS HERE
  2872. SIOVEC:    DEFS    16    ;SPACE FOR 8 VECTORS FOR SIO
  2873. CTCVEC:    DEFS    8    ;SPACE FOR 4 VECTORS FOR CTC
  2874. SYSVEC:    DEFS    4    ;SPACE FOR 2 VECTORS FOR SYSTEM PIO
  2875. GENVEC:    DEFS    4    ;SPACE FOR 2 VECTORS FOR GENERAL PIO
  2876. ;
  2877. ;
  2878. ;
  2879. ;    DISK I/O DRIVER VARIABLES
  2880. ; Be careful not to straddle a Page Boundary with these
  2881. UNIT:    DEFS    1    ;CURRENTLY SELECTED DISK#
  2882. TRKTAB:    DEFS    2    ;2 DRIVE HEAD POSITION TABLE
  2883. TRKTAB.LENGTH: EQU $-TRKTAB
  2884. RECLENTAB: DS    2    ;2 Drive record length table
  2885. MOTOR:    DEFS    1    ;DRIVE MOTOR TURN-OFF TIMER
  2886. RECLEN:    DEFS    1    ;Current disk 'Record Length'
  2887. TRACK:    DEFS    1
  2888. SECTOR:    DEFS    1
  2889. CMDTYP:    DEFS    1    ;COMMAND BYTE FOR READS/WRITES
  2890. RETRY:    DEFS    1    ;DISK OPERATION RE-TRY COUNT
  2891. IOPTR:    DEFS    2    ;DISK I/O BUFFER POINTER
  2892. OLDPTR:    DS    2    ;A scratch location used by RESTORE
  2893. RWFLAG:    DS    1    ;Discriminates reads/writes
  2894. ;
  2895. ;
  2896. ;
  2897. ;    KEYBOARD DATA INPUT FIFO VARIABLES
  2898.  
  2899. FIFO:    DEFS    16    ;CONSOLE INPUT FIFO
  2900. FIFCNT:    DEFS    1    ;FIFO DATA COUNTER
  2901. FIFIN:    DEFS    1    ;FIFI INPUT POINTER
  2902. FIFOUT:    DEFS    1    ;FIFO OUTPUT POINTER
  2903. ;
  2904. ;
  2905. ;    STACK POINTER SAVE AND LOCAL STACK FOR INTERRUPT ROUTINES
  2906. TMPSTK:    EQU    $    ;Internal stack for all routines
  2907.     DEFS    16    ;LOCAL STACK FOR INTERRUPTS
  2908. SPSAVE:    DS    2    ;Save stack pointer
  2909. ;
  2910. ;
  2911. ;    'SOFTWARE' VECTORS FOR INTERRUPT SERVICE ROUTINES
  2912.  
  2913. TIKVEC:    DEFS    2    ;ONE SECOND INTERRUPT ROUTINE VECTOR
  2914. PINVEC:    DEFS    2    ;PARALLEL CONSOLE INPUT VECTOR
  2915. SINVEC:    DEFS    2    ;SERIAL CONSOLE INPUT VECTOR
  2916. ;
  2917. ;
  2918. ;    CLOCK-TIMER INTERRUPT VARIABLES
  2919.  
  2920. TIKCNT:    DEFS    2    ;BINARY CLOCK TICK COUNTER
  2921. DAY:    DEFS    1    ;CALENDAR DAY
  2922. MONTH:    DEFS    1    ;      MONTH
  2923. YEAR:    DEFS    1    ;      YEAR
  2924. HRS:    DEFS    1    ;CLOCK HOURS REGISTER
  2925. MINS:    DEFS    1    ;      MINUTES RETISTER
  2926. SECS:    DEFS    1    ;      SECONDS REGISTER
  2927. ;
  2928. ;    CRT OUTPUT DRIVER VARIABLES
  2929.  
  2930. CURSOR:    DEFS    2    ;CURSOR POINTER
  2931. CHRSAV:    DEFS    1    ;CHARACTER OVERLAYED BY CURSOR
  2932. CSRCHR:    DEFS    1    ;CHARACTER USED FOR A CURSOR
  2933. BASE:    DEFS    1    ;CURRENT CONTENTS OF SCROLL REGISTER
  2934. LEADIN:    DEFS    1    ;STATE OF LEAD-IN SEQUENCE HANDLER
  2935. ;
  2936. ;
  2937. ;    NULL PAD COUNT FOR SERIAL OUTPUT DELAY
  2938.  
  2939. ;NULLS:    DEFS    1    ;# OF NULLS SENT AFTER CONTROL CHARS.
  2940. ;
  2941. ;
  2942. ;    CONSOLE MONITOR PROGRAM VARIABLES
  2943.  
  2944. PARAM1:    DEFS    2    ;STORAGE FOR NUMBERS READ
  2945. PARAM2:    DEFS    2    ; FROM LINE INPUT BUFFER
  2946. PARAM3:    DEFS    2    ; BY 'PARAMS' SUBROUTINE
  2947. PARAM4:    DEFS    2
  2948. ESCFLG:    DEFS    1    ;CONSOLE ESCAPE FLAG
  2949. COFLAG:    DEFS    1    ;CONSOLE OUTPUT TOGGLE
  2950. LAST:    DEFS    2    ;LAST ADDRESS USED BY 'MEMDMP'
  2951. HLSAV:    DS    2    ;Storage of values at entry
  2952. DESAV:    DS    2
  2953. BCSAV:    DS    2
  2954. SPSAV:    DS    2
  2955. ROUTINE.ADDRESS: DS 2    ;Where to restart on errors
  2956. OFFSET:    DS    1    ;the offset (function #)
  2957. LINBUF:    DEFS    64    ;CONSOLE LINE INPUT BUFFER
  2958. ;
  2959. STACK:    EQU    0FFFFH    ;Top of memory
  2960. ;STACKLENGTH: EQU STACK-[LINBUF+64] !Ignore error
  2961. ;
  2962.     END
  2963.