home *** CD-ROM | disk | FTP | other *** search
Text File | 1985-02-10 | 62.1 KB | 2,964 lines |
- ;*************************************************
- ;* *
- ;* BIGBOARD MONITOR ROM, NON-RELOCATABLE VERSION *
- ;* 61 K version *
- ;* Original outline: Russell Smith, 2-Aug-80 *
- ;* Rewritten by Trevor Marshall, Feb-Mar 81 *
- ;* for self-contained WAIT-AID BIOS *
- ;* *
- ;*************************************************
- ;
- ;
- TRUE EQU -1
- FALSE EQU 0
- ;
- IS5MHZ EQU TRUE
- ROM: EQU FALSE
- SIO.POLLED EQU TRUE
- SIO.INTERRUPT EQU NOT SIO.POLLED
- PARALLEL EQU TRUE
- SERIAL EQU FALSE
- CACHE EQU TRUE
- ;
- ROMLOC: EQU 0F000H ;START OF 2K ROM
- ;
- ORG ROMLOC-10H ; at 0 on reset,100 if disk
- ;
- DI
-
- IF NOT ROM
- LD HL,110H ;Where the code will be loaded
- ENDIF ;NOT ROM
-
- IF ROM
- LD HL,10H ;Where code is in ROM
- ENDIF ;ROM
-
- LD DE,ROMLOC ;Where we want it put
- LD BC,0FF0H ;remaining Length of this ROM
- ;and the next
- LDIR
- JP INIT ;Initialize all parameters
- NOP ;To use up 16 bytes
- ;
- ;************************************************
- ;* *
- ;* COLD START INITIALIZATION ROUTINE FOR *
- ;* CONFIGURING THE SYSTEM AFTER A POWER-ON *
- ;* OR PUSHBUTTON RESET. *
- ;* 18-Oct-80 *
- ;* *
- ;************************************************
- ;
- ;
- ; CP/M Equates
- CPMBASE EQU 0D800H ;CP/M base address
- CCP EQU CPMBASE ;CONSOLE COMMAND PROCESSOR
- BDOS EQU 806H+CPMBASE ;OPERATING SYSTEM ENTRY POINT
- CBIOS EQU 1600H+CPMBASE ;BASE OF CUSTOM BIOS
-
- ;
- ; -- MONITOR ENTRY POINT TABLE --
- ;
- ; We need to catch all the external calls to the BIOS
- ; so that we can restore registers upon error
- ; and handle stack imbalance from error control
- ; BIOS FUNCTION CALLING TABLE
- COLD: JP COLDBOOT ;COLD
- JP WARMBOOT ;WARM
- JP CPMST ;CONST
- JP CPMIN ;CONIN
- JP CPMOUT ;CONOUT
- JP LIST ;LIST
- JP CPMOUT ;PUNCH
- JP KBDIN ;READER
- CALL BIOSGO ;HOME
- CALL BIOSGO ;SELDSK
- CALL BIOSGO ;SETTRK
- JP SETSEC ;SETSEC
- JP SETDMA ;SETDMA
- CALL BIOSGO ;READ
- CALL BIOSGO ;WRITE
- JP LSTST ;LSTST
- JP SECTRAN ;SECTRAN
- ; A few extra easily accessible subroutines
- JP INIT
-
- IF ROM
- JP PROMPT
- ENDIF ;ROM
-
- ;Now we need a jump table for the routines
- BIOSTBL: JP COLDBOOT
- JP WARMBOOT
- JP CPMST
- JP CPMIN
- JP CPMOUT
- JP LIST
- JP CPMOUT ;Punch
- JP KBDIN ;Reader
- JP HOME
- JP SELECT
- JP SEEK
- JP SETSEC
- JP SETDMA
- JP READ
- JP WRITE
- ;
- BIOSGO: LD (HLSAV),HL ;Save all registers
- LD (DESAV),DE
- LD (BCSAV),BC
- POP HL ;Get calling address in HL
- LD A,L ;Arithmetic with L only is OK
- SUB A,3 ;Point at start of CALL
- LD L,A ;with HL
- LD (OFFSET),A ;Save function number
- LD (SPSAV),SP ; Save Stack Pointer at entry
- LD DE,BIOSTBL-COLD ;Add the table length to first table
- ADD HL,DE ;To point to corresponding entry
- LD (ROUTINE.ADDRESS),HL ;Save it for error rentry
- LD DE,ERROR.HANDLER ;Fake a return to Error Handler
- PUSH DE
- LD DE,(DESAV) ;REstore DE
- ; Trying JP(IX) BLEW DEBUG
- JP (HL) ;Go to BIOS routine
-
-
- ERROR.HANDLER: PUSH HL ;Save return status, acc.
- ;Is error status zero?
- PUSH AF
- OR A
- JR Z,RET9 ;Return if no error indicated
- CALL PNEXT ;Output an error message
- DB 0DH,0AH,7,'***** Disk I/O error, trk/sec ',EOT
- LD A,(TRACK)
- CALL PUT2HX
- LD A,'/'
- CALL CONOUT
- LD A,(SECTOR)
- CALL PUT2HX
- CALL PNEXT
- DB ', FDC status ',EOT
- POP AF
- PUSH AF ;Get status
- CALL PUT2HS ;Put it in HEX
- CALL CONIN
- AND 5FH ;LC -> UC
- CP 'R'
- JR Z,TRYAGAIN
- CP 'I'
- JR Z,IGNORE
- ;Else drop through to RET9 and return error status
- CALL PNEXT
- DB 'continue',EOT
- RET9:
- ;If functions return values in HL, trap the HL restore
- POP AF
- POP HL ;get HL
- PUSH AF ;acc destroyed below
- LD A,(OFFSET)
- CP 1BH ;SELDSK
- JR EQ,RET10
- LD HL,(HLSAV)
- RET10: LD DE,(DESAV)
- LD BC,(BCSAV)
- POP AF ;retrieve accumulator
- ; LD SP,(SPSAV)
- RET
-
- TRYAGAIN: CALL PNEXT
- DB 'retry',EOT
- LD A,(TRACK) ;save TRK #
- LD HL,PARAM1 ;in scratch
- LD (HL),A
- INC HL
- LD A,(SECTOR)
- LD (HL),A
- CALL HOME ;Recalibrate the drive
- ;Disregard any errors here, easier to handle them upon return
- LD HL,PARAM1
- LD C,(HL)
- CALL SEEK
- LD A,(PARAM1+1) ;Restore original sector
- LD (SECTOR),A ;Effectively CALL SETSEC
- LD BC,(BCSAV) ;Restore relevant calling data
- LD HL,(ROUTINE.ADDRESS)
- LD SP,(SPSAV) ;where we began
- LD DE,ERROR.HANDLER
- PUSH DE ;Fake a return to the handler
- JP (HL)
- ;
- IGNORE: CALL PNEXT
- DB 'ignore',EOT
- ;
- POP AF
- XOR A ;make error status = 0 and return
- PUSH AF
- JR RET9
- ;
- ; Indirect call to subroutines, modifying code
- CPMOUT: LD A,C
- CONOUT: JP CRTOUT ;Modified by SWITCH routines
- CPMIN:
- CONIN: JP KBDIN
- CPMST:
- CONST: JP KBDST
- ;
- LSTST:
- IF NOT ROM
-
- IN A,PIOBDAT ;Is printer busy?
- CPL
- AND 2 ;if LO, busy
- RET Z ;if so ret Zero
-
- ENDIF ;NOT ROM
-
- LD A,0FFH
- RET
- ;
- LIST:
- IF NOT ROM
-
- PUSH AF
- LP1Z: CALL LSTST
- JR Z,LP1Z
- POP AF
- OUT PIOADAT,A
- IN A,PIOBDAT ;Strobe port B bit 7
- RES 7,A
- OUT PIOBDAT,A
- SET 7,A
- OUT PIOBDAT,A
-
- ENDIF ;NOT ROM
-
- RET
- ;
- ;The CCP jumps to coldboot if there is an boot error
- COLDBOOT: XOR A
- LD (0003H),A ;RESET IOBYTE TO ZEROS
- ;CCP uses location 4 as a store for user & drive
- LD (4),A ;Select User 0 & A: on COLDboot
- JR GOCPM
- ;
- ;
- WARMBOOT: LD SP,STACK
- ; We will select in the CCP ROM by writing
- ; a 1 to port 1C bit 7
- IN A,(BITDAT)
- SET 7,A
- OUT (BITDAT),A
- ; the PROM is in socket 3, 1000H up
- LD BC,800H ;move prom contents
- LD DE,CCP
- LD HL,1000H
- LDIR
- ;
- IN A,(BITDAT) ;Deselect PROM
- RES 7,A
- OUT (BITDAT),A
- ;
- ;We must zero the bottom bytes of BDOS
- ;So that the serial numbers match
- LD B,6
- XOR A
- LD HL,BDOS-6 ;or CPMBASE + 800H
- LPP3: LD (HL),A
- INC HL
- DJNZ LPP3
- ;
- ;Zero all the allocation vector tables
- GOCPM: LD BC,VECTORS.LENGTH-1
- LD DE,ALLOCATION.VECTORS+1
- LD HL,ALLOCATION.VECTORS
- LD (HL),A
- LDIR
- ; Zero our BIOS logged disks
- CALL LOGOFF
- ;
- LD A,0C3H ;STORE JUMP VECTORS IN RAM
- LD (00H),A
- LD HL,CBIOS+3 ;JUMP TO CBIOS WARM BOOT AT 00H
- LD (01H),HL
- LD (05H),A
- LD HL,BDOS ;JUMP TO BDOS GOES AT 05H
- LD (06H),HL
-
- IF ROM
- LD (38H),A
- LD HL,BKPT ;JUMP TO Breakpoint GOES AT 38H
- LD (39H),HL
- ENDIF ;ROM
-
- LD HL,FILTER ;Jump to filter replaces that in BDOS
- LD (BDOS+1),HL
-
- LD BC,0080H
- CALL SETDMA ;MAKE DISK BUFFER=0080H
-
- ;The CCP takes in C | User# | Drive# |
-
- LD A,(4) ;Get current user/drive value
- LD C,A ;into C for CCP
- ;
- JP CCP
- ;
- ;
- LOGOFF: ;Log off both disks
- LD HL,UNIT ;Point to TRKTAB-1
- LD A,-1 ;'CLEAR' it
- LD (HL),A
- INC HL
- LD (HL),A
- INC HL
- LD (HL),A ;=== 2 Disk system
- RET
- ;
- ;********************************************************
- ;* Entry point at initialization *
- ;********************************************************
- ;
- ;DO A SHORT POST-RESET TIME DELAY. ALSO INITIALIZES THE
- ;STACK POINTER AND ZEROES THE MONITOR SCRATCH RAM.
- INIT: DI
- LD HL,MEM ;POINT TO START OF MONITOR RAM
- INIT1: LD (HL),0 ;FILL 256 BYTE SPACE WITH ZEROS
- LD SP,HL ;DO SOMETHING USEFUL & ADD DELAY
- INC L ;On exit SP points to top of RAM
- JR NZ,INIT1 ;LOOP TAKES ABOUT 4 msecs
- ;
- ; INITIALIZE THE Z-80 FOR INTERRUPT MODE #2
- LD A,H
- LD I,A ;LOAD I REG WITH MSB OF VECTOR TABLE
- IM 2 ; AND SELECT INTERRUPT MODE 2
- ;
- CALL CLRSCN ;FILL THE CRT MEMORY WITH BLANKS
- IN A,(BITDAT) ;Deselect CRT Bank
- RES 7,A
- OUT (BITDAT),A
- ;
- ; STORE ANY NON-ZERO VALUES FOR VARIABLES IN MEMORY
- ;
- LD HL,INTAB ;POINT TO DEFAULT VARIABLE TABLE
- INIT2: LD B,0
- LD C,(HL) ;BC=DATA BLOCK BYTECOUNT
- INC HL
- LD E,(HL) ;DE=DESTINATION FOR DATA
- INC HL
- LD D,(HL)
- INC HL
- LDIR ;COPY DATA @ HL TO VARIABLES @ DE
- BIT 7,(HL)
- JR Z,INIT2 ;LOOP AGAIN IF NOT AT END OF TABLE
- ;
- ; INITIALIZE THE PROGRAMMABLE I/O DEVICES
- LD DE,110H ;For copyright routine
- ;
- INC HL ;POINT TO I/O INIT DATA TABLE
- INIT3: LD B,(HL) ;B=INIT LOOP BYTECOUNT
- INC HL
- LD C,(HL) ;C=DEVICE CONTROL PORT#
- INC HL
- OTIR ;SEND DATA @ HL TO PORT @ C
- BIT 7,(HL) ;TEST FOR TABLE END MARKER
- JR Z,INIT3 ;LOOP AGAIN IF NOT AT END
- ;
- ; LD BC,80H
- ; CALL SETDMA
- ;
- ;Now check the copyright integrity
-
- IF ROM
-
- LD B,47 ;length of msg
- LD HL,COPYRT-110H
- ADD HL,DE
- XOR A
- LPP1 ADD (HL)
- INC HL
- DJNZ LPP1
- LPP2 CP 0E5H ;patch for each serial #
- JR NZ,LPP2
-
- ENDIF ;ROM
-
-
- ;DETERMINE IF CONSOLE I/O CONFIGURATION WILL BE FOR THE
- ;ON-BOARD CRT AND KEYBOARD OR AN EXTERNAL SERIAL TERMINAL
- ;
- ;First enable keyboard interrupts
- IN A,(KBDDAT) ;Clear any rubbish
- LD A,10000011B
- OUT (KBDCTL),A ;ENABLE INTERRUPTS FROM KBD PIO
- EI
- ;
- LD C,SIOCPB
- LD A,2 ;Select read register 2
- OUT (C),A
- IN A,(C) ;TEST SIO READ REGISTER 2 TO see
- ; CP 00000110B ; IF THE SIO IS INSTALLED (Status affected)
- CP 0 ;See if SIO is installed (no status affects)
- JR NZ,PARALL ;SKIP CONFIGURATION TEST IF NO SIO
- LD B,00010000B ;B=RESET SIO EXTERNAL STATUS COMMAND
- DECIDE: OUT (C),B ;TEST FOR ARRIVAL OF A SERIAL
- IN A,(C) ; INPUT CHARACTER START BIT
- BIT 4,A
- JR NZ,BAUD ;EXIT LOOP IF START BIT DETECTED
- CALL KBDST ;See if FIFO has char ready from
- JR Z,DECIDE ; parallel keyboard yet
- PARALL: CALL KBDIN ;DISCARD FIRST KEYBOARD CHARACTER
- JR SIGNON
- ;
- ;
- ; AUTOMATIC BAUD RATE SETTING ROUTINE FOR SIO
- ;
- BAUD: XOR A
- BAUD1: OUT (C),B
- IN D,(C) ;READ SIO STATUS REGISTER
- BIT 4,D ;TEST THE SYNC/HUNT BIT
- JR Z,BAUD1 ;LOOP UNTIL IT CHANGES STATE
- BAUD2: INC A
- OUT (C),B ;RESET REGISTER #0 FLAGS AGAIN
- IN D,(C) ;AND LOOP TIMING THE SYNC/HUNT BIT
- BIT 4,D
- JR NZ,BAUD2 ;REPEAT UNTIL BIT CHANGES AGAIN
-
- IF IS5MHZ
- RRA ;divide by 2
- ENDIF ;IS5MHZ
-
- LD HL,RATES-1
- BAUD3: INC HL ;INDEX INTO BAUD RATE TABLE
- RLA ; USING COUNT DERRIVED IN A
- JR NC,BAUD3
- LD A,(HL) ;GET BAUD RATE CONTROL BYTE FROM
- OUT (BAUDB),A ;TABLE AND OUTPUT TO COM-8116 TIMER
- CALL SIOIN ;DISARD FIRST SERIAL INPUT CHARACTER
-
- IF SIO.INTERRUPT
-
- LD A,1
- OUT (SIOCPB),A ;RE-PROGRAM SIO B TO GENERATE
- LD A,00011000B ;INTERRUPTS ON RECIEVED DATA,
- OUT (SIOCPB),A ;PARITY DOES NOT AFFECT VECTOR
- LD HL,SIOOUT
- LD DE,KBDIN
- LD BC,KBDST
-
- ENDIF ;SIO.INTERRUPT
-
- IF SIO.POLLED
-
- LD HL,SIOOUT
- LD DE,SIOIN ;No interrupts on input
- LD BC,SIOST
-
- ENDIF ;SIO.POLLED
-
- CALL SWITCH.STASH ;And modify vectors for VDU
- ;
- ; PRINT SIGNON MESSAGE
- ;
- SIGNON:
- IF NOT ROM
- CALL PNEXT
- DB '(C) Copyright 1981 Trevor Marshall',EOT
- XOR A
- LD (UNIT),A ;So that warmboot logs in A:
- JP WARMBOOT
- ENDIF ;NOT ROM
-
- IF ROM
- DEFB 9,9,9,'... WAITAID monitor 4.1 ...'
- DEFB CR,LF,LF,9,9
- COPYRT: DB '(C) Copyright 1981 Trevor Marshall, serial # 00 ',EOT
- ;Now delay for Drive ready signal to go true
- LD HL,2000H
- LP1X: DEC HL
- EX (SP),HL
- EX (SP),HL
- LD A,H
- OR A,L ;Is HL zero?
- JR NZ,LP1X
- LD C,0 ;Drive A
- CALL SELECT
- AND 10011000B
- JR NZ,ABORT.BOOT
- JP BOOT ;Boot if ready
- ABORT.BOOT: CALL LOGOFF ;Log off DSK not ready
- JP PROMPT ;Else GO ENTER MONITOR
- ENDIF ;ROM
- ;
- ;
- ; BAUD RATE CONSTANTS FOR COM 8116 BAUD RATE GENERATOR
- ;
- RATES: DEFB 0101B ; 300 BAUD
- DEFB 0110B ; 600 BAUD
- DEFB 0111B ; 1200 BAUD
- DEFB 1010B ; 2400 BAUD
- DEFB 1100B ; 4800 BAUD
- DEFB 1110B ; 9600 BAUD
- DEFB 1111B ; 19200 BAUD
- DEFB 1111B ; 19200 BAUD
- ;
- ;
- INTAB EQU $ ;INITIALIZATION DATA TABLES
- ;
- ;
- ;INITIALIZE THE Z-80 'I' REGISTER INTERRUPT VECTOR TABLE
- ;
- DEFB 2
- DEFW SYSVEC+2
- DEFW KEYSRV ;PARALLEL KEYBOARD INTERRUPT VECTOR
- ;
- DEFB 2
- DEFW CTCVEC+6
- DEFW TIMER ;ONE SECOND TIMER INTERRUPT VECTOR
-
- ; IF SIO.INTERRUPT
-
- DEFB 4
- DEFW SIOVEC+4
- DEFW SIOINT ;SIO RECIEVE INTERRUPT VECTOR
- DEFW SIOERR ;SIO PARITY, OVERRUN & FRAMING ERROR
-
- ; ENDIF ;SIO.INTERRUPT
-
- ;
- ; INITIALIZE DISK I/O DRIVER VARIABLES
- ;
- DEFB 6
- DEFW UNIT
- DEFB 255 ;FLAG ALL DRIVES AS DE-SELECTED
- DEFB 255,255 ;CLEAR HEAD POSITION TABLE
- DEFB 0,0 ;Both default single density
- DEFB 30 ;SET MOTOR TURN-OFF TIMER
- ; RECLEN, TRACK & SECTOR not initialized
- ;
- ; INITIALIZE THE CRT DISPLAY CURSOR
- ;
- DEFB 2
- DEFW CHRSAV
- DEFB ' '
- DEFB '_'+80H ;USE BLINKING UNDERSCORE
- ;
- ; SET DEFAULT 'SOFTWARE' INTERRUPT VECTORS
- ;
- DEFB 6
- DEFW TIKVEC
- DEFW DSKTMR ;POINT 'TIKVEC' TO DISK MOTOR TIMER
- DEFW STASH ;POINT 'PINVEC' TO FIFO INPUT ROUTINE
- DEFW STASH ;POINT 'SINVEC' TO FIFO INPUT ROUTINE
- ;
- ;
- DEFB -1 ;END OF VARIABLE INIT TABLE
- ;
- ;
- ;
- BAUDA EQU 00H ;CHANEL A BAUD RATE GENETATOR
- SIO EQU 04H ;DUAL SERIAL I/O
- GENPIO EQU 08H ;GENERAL PURPOSE PARALLEL I/O
- BAUDB EQU 0CH ;CHANEL B BAUD RATE GENERATOR
- WD1771 EQU 10H ;WESTERN DIGITAL DISK CONTROLLER
- SCROLL EQU 14H ;CRT SCROLL MEMORY SCROLL REGISTER
- CTC EQU 18H ;QUAD COUNTER/TIMER CIRCUIT
- SYSPIO EQU 1CH ;SYSTEM PARALLEL I/O
- ;
- ;INITIALIZE SYSTEM PIO FOR USE AS BANK-SWITCH,
- ; DISK DRIVE SELECT AND PARALLEL KEYBOARD INPUT
- ;
- BITDAT EQU SYSPIO+0
- BITCTL EQU SYSPIO+1
- KBDDAT EQU SYSPIO+2
- KBDCTL EQU SYSPIO+3
-
- IF ROM
- DEFB 3,BITCTL
- DEFB 11001111B ;PUT SYSTEM PIO IN BIT MODE
- DEFB 00000000B ;All bits outputs
- DEFB 01000000B ;DISABLE INTERRUPTS
- ;
- DEFB 1,BITDAT
- DEFB 00001000B ;DE-SELECT ROMS, ENABLE DRIVE 0
- ; ; DD* line high
- ; ; SIDE 2 line low (=side 1)
- ENDIF ;ROM
- ;
- DEFB 2,KBDCTL
- DEFB 01001111B ;PUT KEYBOARD PORT IN INPUT MODE
- DEFB [SYSVEC+2] AND 0FFH ;LOAD KEYBOARD INTERRUPT VECTOR
- ;
- ;Set up printer PIO
- PIOADAT: EQU 8
- PIOACTL: EQU 9
- PIOBDAT: EQU 10
- PIOBCTL: EQU 11
- ;
- IF PARALLEL AND NOT ROM
- DB 3,PIOACTL
- DB 3 ;Disable interrupts
- DB 0CFH ;Put in bit mode
- DB 0 ;All outputs
- ;
- DB 3,PIOBCTL
- DB 3 ;Disable interrupts
- DB 0CFH ;Bit mode
- DB 0FH ;Bits 1-3 inputs
- ;
- DB 1,PIOBDAT ;Set bit 7 for parallel printer
- DB 80H ;reset special bell (bit 6)
- ENDIF ;PARALLEL
- ;
- ; INITIALIZE CHANELS 2 AND 3 OF THE CTC
- ; TO GENERATE ONE SECOND INTERRUPTS FROM CTC3
- ;
- CTC0 EQU CTC+0 ;CTC CHANEL 0 PORT#
- CTC1 EQU CTC+1 ;CTC CHANEL 1
- CTC2 EQU CTC+2 ;CTC CHANEL 2
- CTC3 EQU CTC+3 ;CTC CHANEL 3
-
- DEFB 1,CTC0
- DEFB [CTCVEC] AND 0FFH ;BASE INTERRUPT VECTOR FOR CTC
- ;
- IF ROM
- DEFB 2,CTC2
- DEFB 00100111B ;PUT CTC2 IN TIMER MODE
- DEFB 105 ;CTC2 PERIOD=105*256*400 nsecs
- ;
- DEFB 2,CTC3
- DEFB 11000111B ;PUT CTC3 IN COUNTER MODE
- DEFB 93 ;CTC3 PERIOD=999936 MICROSECONDS
- ENDIF ;ROM
- ;
- ;
- ;INITIALIZE SIO CHANEL B FOR ASYNCHRONOUS SERIAL
- ; INTERFACE TO PRINTER OR TERMINAL
- ;
- SIODPA EQU SIO+0 ;SIO DATA PORT A
- SIODPB EQU SIO+1 ;SIO DATA PORT B
- SIOCPA EQU SIO+2 ;SIO CONTROL/STATUS PORT A
- SIOCPB EQU SIO+3 ;SIO CONTROL/STATUS PORT B
-
- IF ROM
- DEFB 1,BAUDB
- DEFB 0101B ;SET COM 8116 FOR 300 BAUD DEFAULT
-
- DEFB 10,SIOCPB
- DEFB 4 ;SELECT REGISTER #4
- DEFB 01001100B ;16X CLOCK, 2 STOP BIT, NO PARITY
- DEFB 1 ;SELECT REGISTER #1
- DEFB 00000000B ;STATUS NO EFFECT ON VECTOR, NO INTERRUPTS
- DEFB 3 ;SELECT REGISTER #3
- DEFB 11000001B ;8 BITS/RX CHARACTER,NO AUTO ENABLES
- DEFB 5 ;SELECT REGISTER #5
- DEFB 11101010B ;8 BITS/TX CHARACTER, ASSERT DTR
- DEFB 2 ;SELECT REGISTER #2
- DEFB [SIOVEC] AND 0FFH ;LOAD INTERRUPT VECTOR BASE
-
- ELSE
- DB 4,SIOCPB
- DB 1
- DB 0 ;status no effect
- DB 2
- DB [SIOVEC] AND 0FFH
-
- ENDIF ;ROM
-
- DEFB -1 ;END-OF-TABLE
- ;
- ; INIT DONE
- ;
- ;
- ;************************************************
- ;* *
- ;* BASIC HEX MONITOR FOR Z-80 PROCESSORS *
- ;* 3-Aug-80 *
- ;* *
- ;************************************************
- ;
- IF ROM ;Only want the monitor in ROM
- ;
- ;
- ;
- PROMPT: LD SP,[MEM+0FFH]
- CALL PNEXT
- DEFB CR,LF
- DEFB '* '
- DEFB EOT
- LD HL,LINBUF
- LD C,32
- CALL GETLIN ;INPUT A BUFERED CONSOLE LINE
- JR C,WHAT ;PRINT 'WHAT ?' IF INPUT ERROR
-
- XOR A
- LD (ESCFLG),A
- CALL CRLFS
- LD A,(LINBUF) ;GET FIRST CHARACTER IN LINE
- CP CR
- JR Z,PROMPT ;JUMP IF A NULL LINE
- LD HL,CMDTAB ;SEARCH FOR A MATCHING CHARACTER
- LD BC,CMDSIZ/3 ; IN COMMAND SEARCH TABLE
- CALL SEARCH
- JR NZ,WHAT ;TRY AGAIN IF SEACRH FAILS
- PUSH BC
- LD IY,LINBUF+1
- CALL PARAMS ;INPUT NUMERIC PARAMETERS FROM
- POP IX ; LINE BUFFER AND TEST IF ERROR
- JR C,WHAT
- LD HL,(PARAM1)
- LD DE,(PARAM2)
- LD BC,(PARAM3)
- CALL CALLX ;CALL SUBROUTINE @ IX
- JR NC,PROMPT ;GO BACK TO PROMPT IF NO ERRORS
-
- WHAT: CALL PNEXT
- DEFB ' what ?'
- DEFB 'G'-64 ;SAY 'what ?' AND BEEP THE BELL
- DEFB EOT
- JR PROMPT
- ;
- ;
- CALLX: JP (IX) ;CALL SUBROUTINE @ IX
- ;
- ;
- ;
- CMDTAB: DEFB 'R'
- DB 'W'
- DEFB 'O'
- DEFB 'E'
- DEFB 'G'
- DEFB 'T'
- DEFB 'F'
- DEFB 'S'
- DEFB 'M'
- DEFB 'B'
- DEFB 'D'
- DEFB 'S'
-
- DEFW SWITCH ;SWITCH CONSOLE OUTPUT VECTOR
- DEFW MEMDMP ;DUMP MEMORY IN HEX/ASCII
- DEFW BOOT ;BOOT UP CP/M
- DEFW BLOCK ;MEMORY BLOCK MOVE
- DEFW VIEW ;MEMORY EXAMINE/CHANGE
- DEFW FILL ;FILL MEMORY
- DEFW TEST ;RAM DIAGNOSTIC
- DEFW GOTO ;JUMP TO MEMORY LOCATION
- DEFW INCMD ;READ FROM INPUT PORT
- DEFW OUTCMD ;WRITE TO OUTPUT PORT
- DW WRITE.SECTOR
- DEFW READ.SECTOR ;DISPLAY DISK SECTOR DATA
-
- CMDSIZ EQU $-CMDTAB
- ;
- ;
- ;************************************************
- ;* *
- ;* MONITOR COMMAND ACTION ROUTINES PACKAGE *
- ;* *
- ;************************************************
- ;
- ;
- ;
- ;
- ;
- ; -- DISK BOOT LOADER COMMAND --
- ;
- BOOT: LD C,0 ;SELECT DRIVE 0 FOR BOOT LOAD
- CALL SELECT
- JR NZ,DSKERR
- CALL LOGIN ;HOME HEAD TO TRACK 0 and login disk
- JR NZ,DSKERR ;ERROR IF NOT READY OR AT TR0
- LD BC,0080H ;POINT TO CP/M READ BUFFER
- CALL SETDMA
- LD C,1 ;SELECT SECTOR 1
- CALL SETSEC
- CALL READ ;READ TRACK 0/ SECTOR 1
- JR NZ,DSKERR
- JP 0080H ;GO EXECUTE LOADER
- ;
- ;
- ; ---- Write Disk Sector-----
- WRITE.SECTOR: LD C,A ;Save param count
- LD A,0FFH
- LD (RWFLAG),A ;If flag is non zero = write
- JR RW11
- ; -- DISK SECTOR READ COMMAND --
- ;
- READ.SECTOR: LD C,A ;Save param count
- XOR A
- LD (RWFLAG),A ; flag is zero if read
- RW11: LD A,C
- CP 3 ;CHECK PARAMETER COUNT
- SCF
- RET NZ
- CALL LOGOFF ;Logoff current disk
- LD HL,PARAM1
- LD C,(HL) ;USE FIRST ARG AS UNIT#
- CALL SELECT
- JR NZ,DSKERR
- LD HL,PARAM2
- LD C,(HL) ;USE SECOND ARG AS TRACK#
- CALL SEEK
- JR NZ,DSKERR
- LD HL,PARAM3
- LD C,(HL) ;USE THIRD ARG AS SECTOR#
- CALL SETSEC
- LD BC,0080H ;** Default DSK buffer for BOOT
- CALL SETDMA
- LD A,(RWFLAG)
- OR A
- JR Z,RD1
- CALL WRITE
- JR NZ,DSKERR ;Will need to catch this during LOGON
- RET
- RD1: CALL READ
- JR NZ,DSKERR
- ; LD HL,0080H
- ; LD DE,8
- ; JP DUMP ;DUMP DISK READ BUFFER AND RETURN
- RET
- ;
- ;
- DSKERR: LD C,A ;SAVE 1771 STATUS
- CALL PNEXT
- DEFB 'disk error ',EOT
- LD A,C ;get status
- CALL PUT2HS
- RET
- ;
- ;
- ; -- MEMORY DUMP COMMAND --
- ;
- MEMDMP: DEC A ;CHECK PARAMETER COUNT
- JR Z,MDMP2
- DEC A
- JR Z,MDMP3
- MDMP1: LD HL,(LAST)
- MDMP2: LD DE,8 ;Default # of lines dumped
- JR MDMP3B
-
- MDMP3: EX DE,HL
- SBC HL,DE ;DERRIVE BYTECOUNT FOR DUMP RANGE
- LD B,4
- MDMP3A: SRL H ;DIVIDE BYTECOUNT BY 16
- RR L
- DJNZ MDMP3A
- INC HL
- EX DE,HL
- MDMP3B: CALL DUMP ;DUMP DE*16 BYTES STRTING AT HL
- LD (LAST),HL
- RET
- ;
- ;
- DUMP: PUSH HL ;SAVE STARTING ADDRESS
- CALL PUT4HS ;PRINT STARTING ADDRESS IN HEX
- CALL SPACE
- LD B,16
- DUMP2: LD A,(HL) ;GET A DATA BYTE @ HL
- INC HL
- CALL PUT2HS ;PRINT THE DATA IN HEX
- DJNZ DUMP2 ;REPEAT 16 TIMES
- POP HL ;RESTORE STARTING ADDRESS
- LD B,16
- DUMP3: LD A,(HL) ;GET BACK DATA BYTE @ HL
- INC HL
- RES 7,A
- CP 20H
- JR C,DUMP4
- CP 7FH
- JR C,DUMP5
- DUMP4: LD A,'.' ;PRINT A DOT IF DATA < 20 OR > 7F
- DUMP5: CALL OUTPUT ;PRINT ASCII CHARACTER IN A
- DJNZ DUMP3
- CALL CRLFS
- RET NZ ;EXIT IF ESCAPE REQUEST IS INDICATED
- DEC DE
- LD A,D
- OR E
- JR NZ,DUMP
- RET
- ;
- ;
- ;
- ;
- ; -- MEMORY EXAMINE COMMAND --
- ;
- VIEW: CALL MDATA
- CALL ECHO
- CP CR
- JR Z,VIEW4
- CP '-'
- JR Z,VIEW5
- VIEW2: CALL ASCHEX
- CCF
- RET NC
- RLCA
- RLCA
- RLCA
- RLCA
- LD C,A
- CALL ECHO
- CALL ASCHEX
- CCF
- RET NC
- OR C
- VIEW3: LD (HL),A
- CALL CHECK
- VIEW4: INC HL
- INC HL
- VIEW5: DEC HL
- JR VIEW
- ;
- ;
- ;
- ; -- JUMP TO MEMORY LOCATION COMMAND --
- ;
- ; We should fill the registers from RAM
- GOTO: DEC A ;CHECK PARAMETER COUNT
- SCF
- RET NZ
- PUSH HL
- POP IX
- ;Set up the jump at 30H for breakpoints (F7H,RST6)
- LD A,0C3H
- LD HL,30H
- LD (HL),A
- INC HL
- LD A,[BKPT AND 0FFH]
- LD (HL),A
- INC HL
- LD A,[BKPT SHR 8]
- LD (HL),A
- ; OK, now go to routine
- JP (IX)
- ; OR A
- ; RET ;RETURN IF WE GET BACK AGAIN
- ;
- BKPT: PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF
- CALL PNEXT
- DB '**Breakpoint**, regs are: ',EOT
- POP AF
- CALL PUT2HS ;Put acc
- POP HL
- CALL PUT4HS ;BC
- POP HL
- CALL PUT4HS ;DE
- POP HL
- CALL PUT4HS ;HL
- CALL PNEXT
- DB ',PC=',EOT
- POP HL
- DEC HL ;To allow for PC incr past RST30
- CALL PUT4HS ;PC
- CALL CRLFS
- JP PROMPT
- ;
- ;
- ; -- MEMORY READ/WRITE DIAGNOSTIC COMMAND --
- ;
- TEST: CP 2 ;CHECK PARAMETER COUNT
- SCF
- RET NZ
- INC DE
- LD E,D ;GET ENDING PAGE ADDRESS INTO E
- LD D,H ;GET STARTING PAGE ADDRESS INTO D
- LD B,0 ;INITIALIZE PASS COUNTER
- TEST1: LD H,D ;POINT HL TO START OF BLOCK
- LD L,0
- TEST2: LD A,L
- XOR H ;GENERATE TEST BYTE
- XOR B
- LD (HL),A ;STORE BYTE IN RAM
- INC HL
- LD A,H
- CP E ;CHECK FOR END OF TEST BLOCK
- JR NZ,TEST2
- ; NOW READ BACK EACH BYTE & COMPARE
- LD H,D
- LD L,0 ;POINT HL BACK TO START
- TEST3: LD A,L
- XOR H ;RE-GENERATE TEST BYTE DATA
- XOR B
- CALL CHECK ;VERIFY MEMORY DATA STILL GOOD
- RET NZ ;EXIT IF ESCAPE REQUEST IS INDICATED
- INC HL ; ELSE GO ON TO NEXT BYTE
- LD A,H
- CP E ;CHECK FOR END OF BLOCK
- JR NZ,TEST3
- INC B ;BUMP PASS COUNT
- LD A,'+'
- CALL OUTPUT ;PRINT '+' AND ALLOW FOR EXIT
- JR Z,TEST1 ;DO ANOTHER PASS IF NO ESCAPE
- RET
- ;
- ;
- ;
- CHECK: CP (HL)
- RET Z ;RETURN IF (HL)=A
- PUSH AF
- CALL MDATA ;PRINT WHAT WAS ACTUALLY READ
- CALL PNEXT
- DEFB 'should='
- DEFB EOT
- POP AF
- JP PUT2HS ;PRINT WHAT SHOULD HAVE BEEN READ
- ;
- ;
- MDATA: CALL CRLFS
- CALL PUT4HS
- LD A,(HL)
- JP PUT2HS
- ;
- ;
- ;
- ; -- FILL MEMORY WITH CONSTANT COMMAND --
- ;
- FILL: CP 3 ;CHECK IF PARAMETER COUNT=3
- SCF
- RET NZ
- FILL1: LD (HL),C
- PUSH HL
- OR A
- SBC HL,DE ;COMPARE HL TO END ADDRESS IN DE
- POP HL
- INC HL ;ADVANCE POINTER AFTER COMPARISON
- JR C,FILL1
- RET
- ;
- ;
- ;
- ;
- ; -- MEMORY BLOCK MOVE COMMAND --
- ;
- BLOCK: CP 3 ;CHECK IF PARAMETER COUNT=3
- SCF
- RET NZ
- CALL BLOCAD
- LD A,C
- OR B
- RET Z ;EXIT NOW IF BC=0
- LDIR
- RET
- ;
- ;
- ;
- BLOCAD: EX DE,HL
- OR A ;CLEAR CARRY
- SBC HL,DE ;GET DIFFRENCE BETWEEN
- EX DE,HL ;HL & DE FOR BYTECOUNT
- PUSH DE
- PUSH BC
- POP DE ;GET OLD BC INTO DE
- POP BC
- INC BC ;GET COUNT+1 INTO BC
- RET
- ;
- ;
- ;
- ;
- ; -- READ FROM INPUT PORT COMMAND --
- ;
- INCMD: DEC A ;CHECK IF PARAMETER COUNT=1
- SCF
- RET NZ
- LD C,L ;POINT C TO INPUT PORT
- IN1: CALL CRLFS
- LD A,C
- CALL PUT2HS
- IN A,(C)
- CALL PUT2HS
- CALL ECHO
- CP CR
- JR Z,IN2
- CP '-'
- JR Z,IN3
- OR A
- RET
-
- IN2: INC C
- INC C
- IN3: DEC C
- JR IN1
- ;
- ;
- ;
- ; -- WRITE TO OUTPUT PORT COMMAND --
- ; Syntax: O <Data> <Port>
- OUTCMD: CP 2 ;CHECK IF PARAMETER COUNT=2
- SCF
- RET NZ
- LD C,E ;POINT C TO OUTPUT PORT
- OUT (C),L ;OUTPUT DATA PASSED IN L
- OR A
- RET
- ;
- ;
- ; -- SWITCH CONSOLE OUTPUT DEVICE COMMAND --
- ;
- SWITCH: LD HL,COFLAG
- INC (HL) ;TOGGLE CONSOLE OUTPUT TYPE FLAG
- BIT 0,(HL)
-
- IF SIO.POLLED
- LD DE,SIOIN ;No interrupts
- LD BC,SIOST
- LD HL,SIOOUT
- ELSE
- LD DE,KBDIN ;Interrupts
- LD BC,KBDST
- LD HL,SIOOUT
- ENDIF ;SIO.POLLED
-
- JR Z,SWIT2 ;JUMP IF ZERO TO ONE TRANSITION
- LD HL,CRTOUT
- LD DE,KBDIN
- LD BC,KBDST
-
- ENDIF ;ROM (over all the monitor package)
-
- SWITCH.STASH: ;Store the Serial/Parallel vectors
- SWIT2: LD (CONOUT+1),HL ;STORE NEW CONSOLE OUTPUT ADDRESS
- LD (CONIN+1),DE
- LD (CONST+1),BC
- RET
- ;
- ;
- ;************************************************
- ;* *
- ;* CONSOLE I/O PACKAGE AND UTILITY ROUTINES *
- ;* *
- ;************************************************
- ;
- IF ROM
- ;
- ;
- GETLIN: LD B,C ;SAVE MAX LINE LENGTH PARAMETER IN B
- GLIN1: CALL ECHO ;GET A CHARACTER FROM THE CONSOLE
- CP CR ;CHECK FOR CARRIAGE RETURN
- JR Z,GLIN2
- CP 'H'-64 ;CHECK FOR CTL-H BACKSPACE
- JR Z,GLIN4
- ; Check for delete here will not work, catch it at CHIN
- ; CP 7FH ;Check fo delete
- ; JR Z,GLIN4
- CP ' '
- RET C ;OTHER CONTROL CHARACTERS ARE ILLEGAL
- LD (HL),A
- INC HL ;STORE CHARACTER IN BUFFER
- DEC C
- JR NZ,GLIN1 ;GET ANOTHER IF THERE'S MORE ROOM
- SCF
- RET ;RETURN WITH CARRY=1 IF TOO
- ;MANY CHARACTERS ARE ENTERED
- GLIN2: LD (HL),A ;PUT CARRIAGE RETURN ON END OF LINE
- RET ;RETURN WITH CARRY BIT=0
-
- GLIN4: DEC HL ;DELETE LAST CHARACTER FROM BUFFER
- CALL PNEXT
- DEFB ' ','H'-64 ;PRINT A SPACE TO OVERWRITE THE
- DEFB EOT ; LAST CHARACTER, THEN DO A BACKSPACE
- INC C
- LD A,B ;MAKE SURE YOU'RE NOT TRYING TO
- SUB C ;BACKSPACE PAST THE START OF THE LINE
- JR NC,GLIN1
- RET
- ;
- ;
- ;
- PARAMS: LD BC,0
- LD A,(IY+0)
- LOOKAGAIN: CP CR ;CHECK IF LINE TERMINATES
- JR Z,ZEROLENGTH ;Immediately with <CR>
- CP ' ' ;Or begins with a space
- JR Z,DROPIT
- CP 'M' ;Or an M
- JR Z,DROPIT
- JR PARA2
- DROPIT: INC IY
- LD A,(IY)
- JR LOOKAGAIN
- ;
- ZEROLENGTH: XOR A
- RET ;RETURN WITH PARAM COUNT=0 IF SO
- ;
- PARA1: INC C
- INC C
- BIT 3,C
- SCF
- RET NZ ;ERROR IF > 4 NUMBERS ENTERED
- PARA2: PUSH BC ;SAVE PARAMETER COUNT
- CALL GETHEX ;READ A NUMBER FROM LINE BUFFER
- POP BC
- PARA4: RET C ;ERROR IF RESULT OVER 16 BITS
- LD IX,PARAM1 ;POINT TO PARAMETER STORAGE AREA
- ADD IX,BC ;ADD PARAMETER COUNT IN BC
- LD (IX+0),L
- LD (IX+1),H ;STORE DATA RETURNED FROM 'GETHEX'
- CP ' '
- JR Z,PARA1 ;GET ANOTHER ITEM IF SPACE
- CP ','
- JR Z,PARA1 ;GET ANOTHER ITEM IF COMMA
- CP CR
- SCF ;ELSE CHECK FOR CARRIAGE RETURN
- RET NZ ; AND EXIT WITH CY=1 IF NOT
- PAREND: LD A,C
- SRL A ;A=COUNT OF NUMBERS ENTERED
- INC A
- RET
- ;
- ; GETHEX CONVERTS ASCII TO BINARY AND DOES
- ; HIGH LIMIT CHECKS TO LESS THAN 17 BITS.
- ; CARRY SET ON ILLEGAL CONVERSION RESULT
- ; TERMINATING CHARACTER RETURNS IN A.
- ; HL RETURNS WITH 16 BIT BINARY INTEGER
- ;
- GETHEX: LD HL,0
- JR GNUM3
-
- GNUM1: LD B,4
- GNUM2: ADD HL,HL ;MULTIPLY RESULT BY 16
- RET C ;RETURN IF IT OVERFLOWS 16 BITS
- DJNZ GNUM2
- LD E,A ;APPEND NEW LOW ORDER DIGIT
- LD D,0 ;AND GET RESULT BACK INTO DE
- ADD HL,DE
- RET C ;RETURN IF OVERFLOW
- GNUM3: LD A,(IY+0) ;GET A CHARACTER FROM LINE INPUT
- INC IY ; BUFFER @ IY AND BUMP IY
- LD C,A
- CALL ASCHEX ;CONVERT ASCII TO NUMERIC
- JR NC,GNUM1
- LD A,C
- OR A
- RET
- ;
- ;
- ASCHEX: SUB '0'
- RET C
- CP 10
- CCF
- RET NC
- SUB 7
- CP 10
- RET C
- CP 16
- CCF
- RET
- ;
-
- ENDIF ;ROM
-
- ;
- ;
- SEARCH: CPIR ;SEARCH TABLE @HL FOR MATCH WITH A
- RET NZ ;EXIT NOW IF SEARCH FAILS
- ADD HL,BC
- ADD HL,BC ;ADD RESIDUE FROM CPIR BYTECOUNT
- ADD HL,BC ; TO HL 3 TIMES TO GET POINTER
- LD C,(HL) ; TO ADDRESS PART OF TABLE ENTRY
- INC HL
- LD B,(HL)
- RET ;EXIT WITH Z=1 TO INDICATE MATCH
- ;
- ;
- ;
- PUT4HS: LD A,H
- CALL PUT2HX
- LD A,L
- PUT2HS: CALL PUT2HX
- JR SPACE
- ;
- ;
- PUT2HEX:
- PUT2HX: PUSH AF
- RRA
- RRA
- RRA
- RRA
- CALL PUTNIB
- POP AF
- PUTNIB: AND 00001111B
- ADD A,90H
- DAA
- ADC A,40H
- DAA
- JR OUTPUT
- ;
- ;
- ; PMSG PRINTS THE STRING OF ASCII CHARACTERS
- ; POINTED TO BY THE RELATIVE ADDRESS IN DE
- ; UNTIL AN EOT IS ENCOUNTERED IN THE STRING.
- ;
- EOT EQU 04H
- CR EQU 0DH
- LF EQU 0AH
- ;
-
- PNEXT: EX (SP),HL
- CALL PMSG
- EX (SP),HL
- RET
- ;
- PMSG: LD A,(HL)
- INC HL
- CP EOT
- RET Z
- CALL OUTPUT
- JR PMSG
- ;
- ;
- ; CRLFS OUTPUTS A RETURN-LINEFEED-SPACE
- ; TO THE CONSOLE DEVICE
- ;
- CRLFS: CALL PNEXT
- DEFB CR,LF,EOT
- SPACE: LD A,' '
- JR OUTPUT
- ;
- IF ROM
- ;
- ;
- ; ECHO INPUTS ONE CHARACTER FROM THE CONSOLE
- ; DEVICE, PRINTS IT ON THE CONSOLE OUTPUT AND
- ; THEN RETURNS IT IN REGISTER A WITH BIT 7 RESET
- ;
- ; OUTPUT PRINTS THE CHARACTER IN REGISTER A ON
- ; THE CONSOLE OUTPUT DEVICE AND THEN DOES A CHECK
- ; FOR CONSOLE INPUT TO FREEZE OR ABORT OUTPUT.
- ;
-
- ECHO: CALL CONIN ;INPUT A CHARACTER AND ECHO IT
- CP 7FH ;delete?
- JR NE,ECHO2
- LD A,8 ;yes, load a backspace
- ECHO2: PUSH AF
- CALL CONOUT
- POP AF
- CP 'Z'+1 ;make LC UC
- RET C
- SUB 20H ;CONVERT UPPER CASE TO LOWER CASE
- RET
- ;
- ENDIF ;ROM
- ;
- ;
- OUTPUT: CALL CONOUT
- CALL CONST ;SEE IF CONSOLE INPUT IS PENDING
- JR Z,OUTP2
- CALL CONIN
- CP CR ;SEE IF CARRIAGE RETURN WAS TYPED
- JR Z,OUTP1
- CP 'S'-40H ;<CTL-S>?
- JR NZ,OUTP3 ;If not put the char back on the queue
- CALL CONIN ;WAIT FOR ANOTHER INPUT CHARACTER
- JR OUTP2 ; THEN RETURN TO CALLING ROUTINE
-
- OUTP1: LD (ESCFLG),A ;SET ESCAPE FLAG TO NON-ZERO VALUE
- OUTP2: LD A,(ESCFLG)
- OR A ;RETURN CURRENT STATUS OF ESCAPE
- RET ; FLAG TO CALLING ROUTINE
- ;
- OUTP3: PUSH HL
- CALL REPLACE
- POP HL
- JR OUTP2 ;and return
- ;
- ;
- ;********************************************************
- ;* *
- ;* INTERRUPT SERVICE ROUTINES FOR KEYBOARD *
- ;* INPUT AND REAL-TIME CLOCK FUNCTIONS *
- ;* 3-Aug-80 *
- ;* *
- ;********************************************************
- ;
- ;
- ;
- ;
- KBDST: LD A,(FIFCNT) ;GET INPUT FIFO BYTECOUNT
- OR A ;TEST IF EQUAL ZERO
- RET Z ;EXIT WITH A=0 IF QUEUE IS EMPTY
- LD A,255
- RET ;ELSE SET A=255 TO INDICATE DATA READY
- ;
- ;
- ;
- KBDIN: CALL KBDST
- JR Z,KBDIN ;LOOP UNTIL KEYBOARD INPUT READY
- PUSH HL
- CALL REMOVE ;GET CHARACTER FROM INPUT QUEUE
- POP HL
- BIT 7,A
- ;If B7 set it must be HONEYWELL KYBD char code
- RET Z
- ; Else catch the cursor codes for Honeywell keyboard
- ; 81=UP, 83=right, 84=left, 82=down, 88= home
- ; E7=CLRSCREEN is caught in STASH immediately it is pressed
- PUSH HL
- PUSH BC
- LD HL,TBL1 ;Point at keycode table
- LD BC,TBL1.LENGTH
- CPIR ;Until match or no match
- JR NZ,RET1 ;Abort if no match
- LD BC,TBL1.LENGTH ;Point into next table
- ADD HL,BC
- LD A,(HL)
- RET1: POP BC
- POP HL
- RET
- ;
- TBL1: DB 81H
- DB 83H
- DB 84H
- DB 82H
- DB 0FFH ;a dummy entry for debugging
- TBL1.LENGTH: EQU $-TBL1
- DB 0 ;1 byte spare as HL is incremented past match
- TBL2: DB 05H ;Up line
- DB 04H ;Right char
- DB 13H ;Left char
- DB 18H ;Down line
- DB 0 ;our dummy entry again
- ;HOME is not processed, as not used by WORDSTAR
- ;
- ;
- ;
- ; We don't need software shift lock
- STASH:; LD HL,LOCK ;POINT TO SHIFT LOCK VARIABLES
- ; CP (HL) ;TEST IF A=SHIFT LOCK CHARACTER
- ; INC HL ; THEN POINT TO LOCK FLAG
- ; JR NZ,STASH2 ;JUMP IF NOT THE SHIFT CHARACTER
- ; INC (HL) ; ELSE COMPLIMENT THE SHIFT LOCK
- ; RET ; AND EXIT NOW
- ;
- STASH2:; BIT 0,(HL) ;TEST THE SHIFT LOCK FLAG
- ; JR Z,STASH3 ;JUMP IF SHIFT LOCK NOT SET
- ; CP 40H ;ELSE CHECK FOR SHIFABLE CHARACTER
- ; JR C,STASH3 ; AND JUMP IF NOT EQUAL OR GREATER
- ; CP 7FH ; THAN '@' AND LESS THAN RUBOUT
- ; JR NC,STASH3
- ; XOR 00100000B ;ELSE TOGGLE BIT 5 OF THE CHARACTER
- STASH3: LD C,A
- ;
- CP 0E7H ;Honeywell Keyboard's CLEAR SCREEN key
- JR NZ,NXT35
- CALL CLRSCN
- IN A,(BITDAT)
- RES 7,A
- OUT (BITDAT),A
- RET
- ;
- NXT35: LD HL,FIFCNT ;BUMP INPUT FIFO CHARACTER COUNT
- LD A,(HL)
- INC A
- CP 16
- RET NC ;EXIT NOW IF FIFO IS FULL
- LD (HL),A ; ELSE INCREMENT FIFO COUNT
- LD HL,FIFIN ;POINT HL TO FIFO INPUT OFFSET
- CALL INDEX
- LD (HL),C ;STORE CHARACTER IN FIFO @ HL
- RET
- ;
- ;
- ;
- ;
- REMOVE: LD HL,FIFCNT
- DEC (HL)
- LD HL,FIFOUT ;POINT HL TO FIFO OUTPUT OFFSET
- INDEX: LD A,(HL)
- INC A
- AND 00001111B ;INCREMENT FIFO POINTER
- LD (HL),A ; MODULO 16 AND REPLACE
- LD HL,FIFO
- ADD A,L ;INDEX INTO FIFO BY OFFSET IN A
- LD L,A
- LD A,(HL)
- RET
- ;
- REPLACE: LD HL,FIFCNT
- INC (HL)
- LD HL,FIFOUT
- INDEX2: LD A,(HL)
- DEC A
- AND 00001111B
- LD (HL),A
- RET
- ;
- ;
- ; SOFTWARE DISK MOTOR TURN-OFF TIMER ROUTINE
- ;
- DSKTMR: LD HL,MOTOR ;DECREMENT DISK TURN-OFF TIMER
- DEC (HL)
- RET NZ ;EXIT IF NOT TIMED OUT YET
- IN A,(BITDAT)
- OR 00000100B ;DISABLE ALL DRIVE SELECTS AND
- OUT (BITDAT),A ; TURN OFF THE SPINDLE MOTORS
- RET
- ;
- ;
- ; -- INTERRUPT SERVICE ROUTINE FOR PARALLEL KEYBOARD --
- ;
- KEYSRV: LD (SPSAVE),SP ;SAVE USER STACK POINTER AND
- LD SP,TMPSTK+16 ; SWITCH TO LOCAL STACK
- PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF ;SAVE MACHINE STATE
- IN A,(KBDDAT) ;READ KEYBOARD INPUT PORT
- CPL
- LD HL,(PINVEC) ;GET KBD INTERRUPT ROUTINE VECTOR
- JR DSPTCH ; AND JUMP TO DISPATCH POINT
- ;
- ;
- ;
- ; -- INTERRUPT SERVICE ROUTINE FOR ONE SECOND TIMER --
- ;
- TIMER: LD (SPSAVE),SP ;SAVE USER STACK POINTER AND
- LD SP,TMPSTK+16 ; SWITCH TO LOCAL STACK
- PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF
- LD HL,(TIKVEC) ;GET CLOCK INTERRUPT ROUTINE VECTOR
- JR DSPTCH ; AND JUMP TO DISPATCH POINT
- ;
- ;
- ;
- ; -- SERIAL INPUT INTERRUPT SERVICE ROUTINE FOR SIO --
- ;
- IF SIO.INTERRUPT
-
- SIOINT: LD (SPSAVE),SP ;SAVE USER STACK POINTER AND
- LD SP,TMPSTK+16 ; SWITCH TO LOCAL STACK
- PUSH HL
- PUSH DE
- PUSH BC
- PUSH AF ;SAVE MACHINE STATE
- IN A,(SIODPB) ;READ SIO DATA INPUT PORT
- AND 01111111B
- LD HL,(SINVEC) ;GET SERIAL INPUT ROUTINE VECTOR
-
- ENDIF ;SIO.INTERRUPT
-
- DSPTCH: CALL CALLHL ;CALL SUBROUTINE ADDRESSED BY H
- POP AF
- POP BC
- POP DE
- POP HL
- LD SP,(SPSAVE)
- EI ;RE-ENABLE INTERRUPTS AND RETURN
- RETI
- ;
- ;
- ; -- RX ERROR INTERRUPT SERVICE ROUTINE FOR SIO --
- ;
- ; ARRIVE HERE IF RECIEVE INTERRUPT FROM FRAMING, OVERRUN
- ; AND PARITY ERRORS. (PARITY CAN BE DISABLED)
- ;
- SIOERR:
- IF SIO.INTERRUPT
-
- LD (SPSAVE),SP ;SAVE USER STACK POINTER AND
- LD SP,TMPSTK+16 ; SWITCH TO LOCAL STACK
- PUSH AF
- CALL SIOIN2 ;CLEAR BAD CHARACTER FROM SIO
- LD A,'G'-64
- CALL SIOXMT ;OUTPUT A CTL-G AS A WARNING
- POP AF
- LD SP,(SPSAVE)
-
- ENDIF ;SIO.INTERRUPT
-
- IF NOT SIO.INTERRUPT
- SIOINT:
- ENDIF ;NOT SIO.INTERRUPT
-
- EI
- RETI
- ;
- ;
- CALLHL: JP (HL)
- ;
- ;
- ;
- ; POLLED MODE I/O ROUTINES FOR SIO CHANEL B
- ;
- SIOST: IN A,(SIOCPB) ;GET SIO STATUS REGISTER
- AND 00000001B
- RET Z ;ACC=0 IF NO DATA AVAILABLE
- LD A,255
- RET
- ;
- ;
- SIOIN: CALL SIOST ;TEST CONSOLE STATUS
- JR Z,SIOIN ;LOOP UNTIL DATA IS RECIEVED
- SIOIN2: LD A,00110000B ;RESET STATUS BITS IN SIO FOR
- OUT (SIOCPB),A ; PARITY/OVERRUN/FRAMING ERRORS,
- IN A,(SIODPB) ; THEN GET THE INPUT CHARACTER
- AND 7FH
- RET
- ;
- ;
- ; We dont need null padding
- SIOOUT: ;CP ' ' ;TEST FOR CONTROL CHARACTERS
- ; JR NC,SIOXMT ;JUMP IF PRINTABLE CHARACTER
- ; CALL SIOXMT ; ELSE SEND CONTROL CHARACTER
- ; LD A,(NULLS) ; AND THEN SEND NULLS AS PADDING
- ; INC A ;GET NULL PAD COUNT AND FIX SO
- ; JR PAD1 ; THAT COUNT=0 SENDS NO NULLS
-
- ;PAD: PUSH AF
- ; XOR A
- ; CALL SIOXMT ;OUTPUT A NULL TO THE SIO
- ; POP AF
- ;PAD1: DEC A
- ; JR NZ,PAD ;LOOP SENDING NULLS TO SIO
- ; RET
- ;
- ;
- SIOXMT: PUSH AF
- SIOX1: IN A,(SIOCPB)
- AND 00000100B ;TEST TBE STATUS BIT
- JR Z,SIOX1
- POP AF
- OUT (SIODPB),A ;OUTPUT DATA TO SIO
- RET
- ;
- ;
- ;************************************************
- ;* *
- ;* MEMORY-MAPPED CRT OUTPUT DRIVER *
- ;* *
- ;* Russell Smith 18-August-1980 *
- ;* *
- ;************************************************
- ;
- ;
- CRTMEM EQU 3000H ;Start of 3K CRT memory space
- CRTBAS EQU CRTMEM SHR 8 ;STARTING PAGE# OF 3K CRT SPACE
- CRTTOP EQU [CRTMEM+3072] SHR 8 ;ENDING PAGE# OF CRT SPACE
- ;
- ;
- CRTOUT:
- PUSH AF
- PUSH HL
- PUSH DE
- PUSH BC
- RES 7,A
- LD C,A
- DI ;KEEP THE WOLVES AWAY FOR A WHILE
- LD (SPSAVE),SP
- LD SP,TMPSTK+16 ;POINT SP TO TOP OF LOCAL STACK
- IN A,(BITDAT)
- SET 7,A ;SELECT ROM/CRT MEMORY BANK
- OUT (BITDAT),A
- ;
- ;FIRST REMOVE THE OLD CURSOR CHARACTER FROM THE SCREEN
- ;
- LD HL,CHRSAV ;GET CHARACTER NOW OVERLAYED BY CURSOR
- LD B,(HL)
- LD HL,(CURSOR) ;LOAD HL WITH CURSOR POINTER
- LD A,H
- AND 00001111B ;A LITTLE INSURANCE THAT HL CAN'T
- OR CRTBAS ; EVER POINT OUTSIDE THE CRT MEMORY
- LD H,A
- LD (HL),B ;REMOVE CURSOR BY RESTORING CHARACTER
- ;
- ; PROCESS CHARACTER PASSED IN C
- ;
- CALL OUTCH
- ;
- ;NOW STORE A NEW CURSOR CHARACTER AT THE CURSOR LOCATION
- ;
- LD A,(HL) ;GET CHARACTER AT NEW CURSOR LOCATION
- LD (CHRSAV),A ;SAVE FOR NEXT TIME 'CRTOUT' IS CALLED
- CP ' ' ;TEST IF CHARACTER IS A SPACE
- SET 7,A ;THEN TURN ON BIT 7 TO ENABLE BLINK
- JR NZ,CRT2 ;JUMP IF CHARACTER IS NON-BLANK
- LD A,(CSRCHR) ;ELSE GET CHARACTER USED FOR CURSOR
- CRT2: LD (HL),A ;STORE CHARACTER IN A AS CURSOR MARK
- LD (CURSOR),HL ;SAVE HL AS CURSOR POINTER
-
- LD SP,(SPSAVE)
- IN A,(BITDAT)
- RES 7,A ;SWITCH BACK THE LOWER 16K OF RAM
- OUT (BITDAT),A
- EI ;INTERRUPTS ARE SAFE AGAIN
- POP BC
- POP DE
- POP HL
- POP AF
- RET
- ;
- ;
- ;
- OUTCH: LD DE,LEADIN
- LD A,(DE) ;GET LEAD-IN SEQUENCE STATE
- OR A
- JP NZ,MULTI ;JUMP IF IN A LEAD-IN SEQUENCE
- LD A,C ; ELSE PROCESS CHARACTER IN C
- CP ' '
- JR C,CONTRL ;JUMP IF A CONTROL CHARACTER
- DISPLA: LD (HL),C ; ELSE STORE DISPLAYABLE CHARACTER
- INC HL ; AND ADVANCE POINTER TO NEXT COLUMN
- LD A,L
- AND 01111111B ;EXTRACT COLUMN# FROM HL
- CP 80
- RET C ;EXIT IF NOT PAST COLUMN 79
- CALL RETURN ; ELSE DO AUTOMATIC CARRIAGE RETURN
- CALL LFEED ; AND LINEFEED
- RET
- ;
- ;
- ;
- CONTRL: PUSH HL
- LD HL,CTLTAB ;SEARCH FOR CONTROL CHARACTER
- LD BC,CTLSIZ/3 ;HANDLING SUBROUTINE IN TABLE
- CALL SEARCH
- POP HL
- RET NZ ;EXIT IF NOT IMPLEMENTED
- PUSH BC
- RET ;DO SNEAKY JUMP TO PRESERVE REGISTERS
-
- CTLTAB: DEFB '_'-64
- DEFB '^'-64
- DEFB '['-64
- DEFB 'Z'-64
- DEFB 'X'-64
- DEFB 'Q'-64
- DEFB 'M'-64
- DEFB 'L'-64
- DEFB 'K'-64
- DEFB 'J'-64
- DEFB 'I'-64
- DEFB 'H'-64
- DEFB 'G'-64
-
- DEFW BELL ;CTL-G IS THE BELL
- DEFW BAKSPC ;CTL-H IS CURSOR LEFT
- DEFW TAB ;CTL-I IS TAB
- DEFW LFEED ;CTL-J IS CURSOR DOWN
- DEFW UPCSR ;CTL-K IS CURSOR UP
- DEFW FORSPC ;CTL-L IS CURSOR RIGHT
- DEFW RETURN ;CTL-M IS CARRIAGE RETURN
- DEFW CLREOS ;CTL-Q IS CLEAR TO END-OF-SCREEN
- DEFW CLREOL ;CTL-X IS CLEAR TO END-OF-LINE
- DEFW CLRSCN ;CTL-Z IS CLEAR SCREEN
- DEFW ESCAPE ;CTL-[ IS ESCAPE
- DEFW HOMEUP ;CTL-^ IS HOME UP
- DEFW STUFF ;CTL-_ IS DISPLAY CONTROL CHARS
-
- CTLSIZ EQU $-CTLTAB
- ;
- ;
- ESCAPE: LD A,1
- LD (DE),A ;SET LEAD-IN SEQUENCE STATE
- RET ; FOR XY CURSOR POSITIONING MODE
- ;
- ;
- STUFF: LD A,4
- LD (DE),A ;SET LEAD-IN SEQUENCE STATE
- RET ; FOR CONTROL CHAR OUTPUT MODE
- ;
- ;
- BAKSPC LD A,L ;CHECK FOR LEFT MARGIN
- AND 01111111B
- RET Z ;ABORT IF IN LEFTMOST COLUMN
- DEC HL ;BACK UP CURSOR POINTER
- RET
- ;
- ;
- FORSPC: LD A,L ;CHECK FOR RIGHTMOST COLUNM
- AND 01111111B
- CP 79
- RET NC ;DO NOTHING IF ALREADY THERE
- INC HL
- RET ;ELSE ADVANCE THE CURSOR POINTER
- ;
- ;
- TAB: LD DE,8 ;TABS ARE EVERY 8 COLUMNS
- LD A,L ;GET COLUMN COMPONENT OF
- AND 01111000B ; PREVIOUS TAB POSITION
- ADD A,E
- CP 80 ;EXIT IF NEXT TAB COLUMN WOULD
- RET NC ; BE PAST THE RIGHT MARGIN
- LD A,L
- AND 11111000B ;ELSE INCREMENT THE CURSOR
- LD L,A ; POINTER FOR REAL
- ADD HL,DE
- RET
- ;
- BELL:
- IF NOT CACHE
-
- IN A,(BITDAT)
- SET 4,A ;TOGGLE BIT 5 OF SYSTEM PIO TO
- OUT (BITDAT),A ;TRIGGER BELL HARDWARE TO SOUND
- ;Now delay for 120msec
- PUSH BC
- LD B,120 ;msec
- LPX2: LD C,8AH
- LPX3: NOP
- NOP
- NOP
- DEC C
- JR NZ,LPX3
- DJNZ LPX2
- POP BC ;Done delay
- RES 4,A
- OUT (BITDAT),A
- RET
- ENDIF ;NOT CACHE
-
- IF CACHE
-
- IN A,PIOBDAT ;We use GPPIO bit 7
- RES 7,A
- OUT PIOBDAT,A
- ;Now delay for 120msec
- PUSH BC
- LD B,120
- LPZ2: LD C,8AH
- LPZ3: NOP
- NOP
- NOP
- DEC C
- JR NZ,LPZ3
- DJNZ LPZ2
- POP BC
- SET 7,A
- OUT PIOBDAT,A
- RET
- ENDIF ;CACHE
- ;
- ;
- RETURN: LD A,L
- AND 10000000B
- LD L,A ;MOVE CURSOR POINTER BACK
- RET ; TO START OF LINE
- ;
- ;
- ; Now clear the screen
- CLRSCN: IN A,(BITDAT)
- SET 7,A
- OUT (BITDAT),A ;Select CRT bank
- LD HL,CRTMEM
- PUSH HL
- LD DE,CRTMEM+1
- LD BC,24*128
- LD (HL),' '
- LDIR ;FILL CRT MEMORY WITH SPACES
- POP HL ;POINT TO HOME CURSOR POSITION
- LD A,23
- LD (BASE),A ;MAKE BASE LINE# BE 23 AND
- OUT (SCROLL),A ; STORE IN SCROLL REGISTER
- RET
- ;
- ;
- CLREOL: PUSH HL ;SAVE CURSOR POINTER
- LD A,L
- AND 01111111B ;GET COLUMN# COMPONENT OF
- LD C,A ; CURSOR POINTER INTO C
- LD A,80 ;CALCULATE HOW MANY CHARACTERS
- SUB C ; REMAIN ON CURRENT LINE
- LD B,A
- CALL CLR ;CLEAR REST OF LINE @ HL
- POP HL
- RET
- ;
- ;
- CLREOS: CALL CLREOL ;CLEAR REMAINDER OF CURRENT ROW
- PUSH HL
- LD A,(BASE)
- LD C,A ;COPY BASE SCREEN ROW# TO C
- CLRS1: LD A,L
- RLA
- LD A,H
- RLA ;GET ROW# COMPONENT OF HL INTO A
- AND 00011111B
- CP C ;SEE IF HL IS AT BOTTOM ROW OF SCREEN
- JR Z,CLRS2 ; AND LEAVE CLEAR LOOP IF SO
- CALL DNCSR ;ELSE POINT HL TO NEXT ROW DOWN
- CALL CLRLIN ; AND FILL THAT LINE WITH SPACES
- JR CLRS1
-
- CLRS2: POP HL ;RESTORE ORIGINAL CURSOR POINTER
- RET
- ;
- ;
- UPCSR: LD DE,-128 ;SUBTRACT 1 FROM ROW# COMPONENT
- ADD HL,DE ; OF CURSOR POINTER IN HL
- LD A,H
- CP CRTBAS ;CHECK FOR UNDERFLOW OF POINTER
- RET NC
- LD H,CRTTOP-1 ;WRAP CURSOR AROUND MODULO 3K
- RET
- ;
- ;
- DNCSR: LD DE,128 ;ADD 1 TO ROW# COMPONENT
- ADD HL,DE ;OF CURSOR POINTER IN HL
- LD A,H
- CP CRTTOP ;CHECK FOR OVERFLOW OF POINTER
- RET C
- LD H,CRTBAS ;RESET POINTER MODULO 128*24
- RET
- ;
- ;
- ;
- LFEED: LD A,L
- RLA
- LD A,H
- RLA ;EXTRACT ROW# COMPONENT OF HL
- AND 00011111B
- LD C,A ;COPY ROW# INTO C FOR SCROLL TEST
- CALL DNCSR ;MOVE CURSOR TO NEXT ROW DOWN
- LD A,(BASE) ;TEST IF CURSOR WAS ON BOTTOM ROW
- CP C ; OF SCREEN BEFORE MOVING DOWN
- RET NZ ;EXIT IF NOT AT BOTTOM
-
- PUSH HL ;ELSE PREP TO SCROLL SCREEN UP
- CALL CLRLIN ;FILL NEW BOTTOM LINE WITH SPACES
- ADD HL,HL
- LD A,H ;GET ROW# COMPONENT OF HL INTO A
- AND 00011111B
- LD (BASE),A ;STORE NEW BASE LINE#
- OUT (SCROLL),A ;NOW SCROLL UP NEW BLANK BOTTOM LINE
- POP HL
- RET
- ;
- ;
- CLRLIN: LD A,L
- AND 10000000B ;POINT HL TO FIRST COLUMN OF ROW
- LD L,A
- LD B,80
- CLR: LD (HL),' ' ;STORE ASCII SPACES AT ADDRESS IN HL
- INC HL ; AND INCREMENT HL
- DJNZ CLR ;REPEAT NUMBER OF TIMES GIVEN BY B
- RET
- ;
- ;
- HOMEUP: LD C,' ' ;FAKE-OUT CURSOR ADDRESSING ROUTINE
- JR SETROW ; TO DO HOMEUP ALMOST FOR FREE
- ;
- ;
- MULTI: EX DE,HL ;UNCONDITIONALLY RESET THE LEAD-IN
- LD (HL),0 ; STATE TO ZERO BEFORE GOING ON
- EX DE,HL
- CP 1
- JR NZ,M2TST
- SETXY: LD A,C ;GET SECOND CHAR OF SEQUENCE
- CP '='
- RET NZ ;ABORT SEQUENCE IF NOT '='
- LD A,2
- LD (DE),A ;MAKE LEADIN=2 NEXT TIME
- RET
-
- M2TST: CP 2
- JR NZ,M3TST
- LD A,3
- LD (DE),A ;MAKE LEADIN=3 NEXT TIME
- SETROW: LD A,(BASE) ;ARRIVE HERE ON THIRD CHARACTER
- ADD A,C ; OF ESC,'=',ROW,COL SEQUENCE
- SUB ' '-1
- SETR2: SUB 24
- JR NC,SETR2 ;MAKE SURE ROW# IS BETWEEN 0 AND 23
- ADD A,24
- OR CRTMEM SHR 7 ;MERGE IN MSB'S OF CRT MEMORY
- LD H,A
- LD L,0
- SRL H
- RR L
- RET
-
- M3TST: CP 3
- JR NZ,M4TST
- SETCOL: LD A,C ;ARRIVE HERE ON FOURTH CHARACTER
- SUB ' ' ; OF ESC,'=',ROW,COL SEQUENCE
- SETC2: SUB 80
- JR NC,SETC2 ;MAKE SURE COL# IS BETWEEN 0 AND 79
- ADD A,80
- OR L ;MERGE IN COL# WITH L
- LD L,A
- RET
-
- M4TST: CALL DISPLA ;DISPLAY THE CONTROL CHARACTER
- RET ; PASSED IN C
- ;
- ;
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; FILTER FOR CDOS SYSTEM CALLS
- ; LAST CHANGE 12:Mar:81
- ;
- ; Written by Steve Hope, Trevor Marshall,
- ; Wait-Aid, Western Australia
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- FILTER:
- PUSH AF
- LD A,C
- CP 80H ;CP/M 0-80H
- JR GE,CDOS ;CHK IF CDOS COMPATIBLE
- CP 2 ;WRITE CONSOL NEEDS EXTRA CARE,A must be kept
- JR Z,SYSC2
- CP 11 ;Console status must return all
- JR Z,SYSC11
- CP 15 ;Open file must zero (DE)+32 (current record)
- CALL Z,SYSC15
- POP AF ;FIX STACK
- LD (PARAM1),HL ;save temporarily
- LD (PARAM2),DE
- LD (PARAM3),BC
- CALL BDOS+0BH ;Usually E011, Go execute BDOS
- LD BC,(PARAM3)
- LD DE,(PARAM2)
- PUSH AF
- LD A,C ;Check functions which return values in HL
- CP 27 ;Max 1.4 FN
- JR GE,RET67 ;All higher return HL
- CP 24 ;login code
- JR EQ,RET67
- CP 12 ;Get version
- JR EQ,RET67
- LD HL,(PARAM1)
- RET67:
- POP AF
- RET
- ;
- SYSC2:
- LD (SPSAV),SP ;the CP/M DIR command always bombs
- LD SP,STACK ;due to stack overflow unless
- LD A,E ;we give it some help
- CALL CONOUT ;Destroys nothing
- LD SP,(SPSAV)
- POP AF
- RET
- ;
- SYSC11: POP AF
- CALL CPMST
- OR A
- RET Z ;Don't alter HL unless we have to
- LD L,A ; required for CP/M compatibility
- RET
- ;
- SYSC15: PUSH HL ;This is required
- LD HL,32 ; for CDOS
- ADD HL,DE
- LD (HL),0
- POP HL
- RET ;thence to BDOS
- ;
- CDOS:
- CP 80H ;READ NO ECHO
- JR Z,RNEC
- CP 82H ;Set CTL-C abort (it doesn't)
- JR Z,SYSC82
- CP 86H ;FORMAT NAME TO FCB
- JR Z,FFCB
- ; CP 8EH ;CRT FUNCTION (XY POS)
- ; JP Z,CRT
- CP 89H ;MULTIPLY INTEGERS
- JP Z,MULT
- CP 8AH ;DIVIDE INTEGERS
- JP Z,DIVIDE
- CP 8BH
- JP Z,HOME ;Home selected disk
- CP 8DH ;Get version
- JP Z,GETVERSION
- CP 90H ;Read date
- JR Z,READ.DATE
- CP 92H ;Read time of day
- JR Z,READ.DATE ;Return zero, same as 90H
- CP 96H ;Turn motors off
- JR Z,MOTORS.OFF
- POP AF ;FIX STACK
- JP CALLERR ;ELSE ERROR FOR NOW
- ;
- RNEC: ;READ NO ECHO
- POP AF ;FIX STACK
- JP CPMIN ;And return with char in acc.
- ;
- READ.DATE: POP AF
- XOR A ; A=0
- LD C,A
- LD B,A ;BC=0
- RET ;***Done ***
- ;
- MOTORS.OFF: IN A,(BITDAT)
- OR A,01000100B ;Motors off, drive deselected
- OUT (BITDAT),A
- SYSC82: POP AF
- RET
-
- ;;;
- FFCB:
- POP AF ;FIX STACK
- PUSH DE ;SAVE DE
- LD B,(HL) ;GET FIRST CHAR
- INC HL
- LD A,(HL)
- CP ':' ;CHK IF DRIVE
- JR NZ,NOCOL
- INC HL ;PAST COL
- LD A,7
- AND B ;DRV #
- JR FBYTE
- NOCOL: DEC HL
- XOR A ;DEFAULT DRV
- FBYTE:
- LD (DE),A
- INC DE
- LD B,8
- ;
- NAME1:
- LD A,(HL)
- CP '*'
- JR EQ,FILLWILD
- CP 21H
- JR C,FILLL1
- INC HL
- CP '.'
- JR Z,FILLL1
- LD (DE),A
- INC DE
- DJNZ,NAME1
- JR EX1
- FILLWILD:
- LD A,'?'
- LD (DE),A
- INC DE
- DJNZ FILLWILD
- JR EX1
- FILLL1:
- LD A,' '
- LD (DE),A
- INC DE
- DJNZ,FILLL1
- EX1:
- ;;;;;;
- LD A,'.'
- CP (HL)
- JR NZ,EXT
- INC HL
- EXT: LD B,3
- NAME2:
- LD A,(HL)
- CP '*'
- JR EQ,WILDEXT
- CP 21H
- JR C,FILLL2
- INC HL
- CP '.'
- JR Z,FILLL2
- LD (DE),A
- INC DE
- DJNZ,NAME2
- JR EX2
- WILDEXT: LD A,'?'
- LD (DE),A
- INC DE
- DJNZ WILDEXT
- JR EX2
- FILLL2:
- LD A,' '
- LD (DE),A
- INC DE
- DJNZ,FILLL2
- EX2: ;Done, restore ready for exit
- XOR A
- LD (DE),A
- POP DE
- RET
-
-
- ;CRT:
- ; POP AF ;FIX STACK
- ; XOR A
- ; CP E ;CANT HANDLE ALL
- ; JR NZ,CRT3
- ; LD A,1AH ;Clearscreen char
- ; JP CRTOUT ;Neglect all other special fns
- ;CRT3: PUSH DE ;SAVE DE
- ; CALL PNEXT
- ; DB 1BH,'=',EOT
- ; POP DE ;RECOVER DE
- ; PUSH DE ;SAVE AGAIN
- ; LD A,1FH
- ; ADD E ;ROW
- ; CALL CONOUT
- ; POP DE
- ; PUSH DE
- ; LD A,1FH
- ; ADD D ;COL
- ; CALL CONOUT
- ; POP DE
- ; RET
- ;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- MULT: ;DE=HL*DE
- POP AF ;FIX STACK
- PUSH BC ;SAVE REGS
- PUSH HL
- LD L,16
- LD BC,0
- MLOOP:
- EX (SP),HL
- LD A,1
- AND A,E
- JR Z,M1
- PUSH HL
- ADD HL,BC
- EX (SP),HL
- POP BC
- M1:
- RR B
- RR C
- RR D
- RR E
- EX (SP),HL
- DEC L
- JR NZ,MLOOP
- POP HL
- POP BC
- RET
-
-
- DIVIDE: ;HL=HL/DE , DE=REMAINDER
- POP AF ;FIX STACK
- LD A,D
- OR A,E
- RET Z ;DIVIDE BY 0
- LD A,D
- CPL
- LD D,A
- LD A,E
- CPL
- LD E,A
- INC DE ;2'S COMP
- PUSH BC
- LD B,H
- LD C,L
- LD HL,0
- LD A,17
- DLOOP:
- PUSH HL
- ADD HL,DE
- JR NC,D1
- EX (SP),HL
- D1:
- POP HL
- RL C
- RL B
- RL L
- RL H
- DEC A
- JR NZ,DLOOP
- OR A,A
- RR H
- RR L
- EX DE,HL
- LD H,B
- LD L,C
- POP BC
- RET
-
- ;;;;;;;;
-
- CALLERR:
- CALL PNEXT
- DEFB CR,LF,'Illegal system call ',EOT
- LD A,C
- CALL PUT2HEX
- CALL PNEXT
- DB ',PC=',EOT
- POP HL ;GET CALL ADDR
- PUSH HL ;REt addr back on stack
- DEC HL ;start
- DEC HL
- DEC HL
- ;NOW PRINT ADDR OF ILLEGAL CALL
- CALL PUT4HS ;Print calling addres
- XOR A ;Set up return variable values=0
- LD BC,0
- LD DE,0
- LD HL,0
- RET ;Hope program will not bomb
- ;
- GETVERSION: POP AF
- LD BC,0107H ;Version 1.07
- RET
- ;
- ;
- ;
- ;************************************************
- ;* *
- ;* DISK INPUT/OUTPUT DRIVER SUBROUTINE PACKAGE *
- ;* FOR WESTERN DIGITAL 1771 DISK CONTROLLER *
- ;* *
- ;* bullet-proof error recovery added 12-APR-80 *
- ;* *
- ;************************************************
- ;
- ;
- ;EQUATES FOR DISK CONTROLLER PORTS AND COMMAND CODES
- ;
- STSREG EQU WD1771+0 ;STATUS REGISTER
- CMDREG EQU WD1771+0 ;COMMAND REGISTER
- TRKREG EQU WD1771+1 ;TRACK REGISTER
- SECREG EQU WD1771+2 ;SECTOR REGISTER
- DATREG EQU WD1771+3 ;DATA REGISTER
- ;
- RDCMD EQU 10001000B ;READ COMMAND
- WRTCMD EQU 10101000B ;WRITE COMMAND
- SKCMD EQU 00011100B ;SEEK COMMAND
- FINCMD EQU 11010000B ;FORCE INTR COMMAND
- RSTCMD EQU 00001100B ;RESTORE COMMAND
- HLOAD EQU 00000100B ;RD/WRT HEAD LOAD ENABLE
- ;
- RET EQU 0C9H ;SUBROUTINE RETURN INSTR OPCODE
- NMIVEC EQU 0066H ;THE NON-MASKABLE INTERRUPT IS
- ;USED FOR DATA SYNCRONIZATION BETWEEN
- ;THE Z-80 AND 1771 DISK CONTROLLER
- ;
- ;
- ;
- SETSEC: LD HL,SECTOR
- LD (HL),C
- XOR A ;To prevent errors being notified
- RET
- ;
- SETDMA: LD (IOPTR),BC
- XOR A
- RET
- ;
- ;
- SECTRAN: EX DE,HL ;ADD TRANSLATION TABLE ADDRESS
- ADD HL,BC ; PASSED IN DE TO SECTOR# IN BC
- LD L,(HL)
- LD H,0 ;LOOKUP PHYSICAL SECTOR NUMBER
- XOR A
- RET ; AND RETURN IT IN HL
- ;
- ;
- SELECT: LD HL,0 ;In case of error exit
- LD A,C ;GET UNIT# PASSED IN C AND
- CP 2 ; CHECK FOR MAXIMUM VALID#
- RET NC ;ERROR IF NUMBER > 1
- ;
- LD (SAVE.DRIVE),A ;Stash Unit# for DOSELECT later
- ; check that it is logged
- LD HL,TRKTAB ;Calculate trk ptr of requested drive
- LD A,L
- ADD C
- LD L,A ;Now pointing at the modified byte
- LD A,(HL) ;Has this drive been logged on?
- CP 0FFH
- LD A,C ;Get new dsk# to A ready for RET21
- JR NE,RET21 ;Only a number of FF indicates not logged
- ;so if anything else make no hardware changes yet
- ;If the drive is not logged we had better do so, as
- ; BDOS expects DPB info on its size
- CALL DOSELECT
- RET
- ;
- ;
- DOSELECT:
- LD A,(SAVE.DRIVE)
- LD C,A
- LD HL,UNIT ;POINT HL TO DRIVE SELECT DATA
- LD A,(HL) ;LOAD A WITH CURRENT UNIT#
- LD (HL),C ; AND STORE NEW UNIT# FROM C
- ;Check if drive is already current
- LD E,A ;Save current #
- SUB A,C
- JR Z,RET20 ;If so, exit
- ;
- LD D,C ;Save new drive
- IN A,(BITDAT)
- AND 11011000B ;MERGE IN NEW DRIVE UNIT# & side 0
- OR C ; IN PLACE OF THE CURRENT ONE
- OUT (BITDAT),A ; TO SELECT THE NEW DISK DRIVE
- ;Delay turnon until an operation is actually requested
- ; CALL TURNON ;After selecting drive
- ; BIT 7,A ;TEST DRIVE NOT READY BIT
- ; JR Z,SEL2 ; AND CONTINUE IF ITS READY
- ; LD HL,0 ;for BDOS
- ; LD A,10000000B ;else RETURN DRIVE-NOT-READY STATUS
- ; OR A
- ; RET
- SEL2:
- ;We will store the old track number and RECLEN for later
- LD C,D ;retrieve new drive
- LD A,E ;retrieve original UNIT byte
- CP 255 ;TEST IF NO DRIVE HAS BEEN SELECTED
- ; Else store last drive's parameters
- JR Z,SEL3 ;YET AND SKIP NEXT SEGMENT IF SO
- INC HL ;POINT TO HEAD POSITION TABLE
- ADD A,L ; AND ADD IN OLD UNIT# AS INDEX
- LD L,A
- LD A,(TRACK) ;Get current track position
- LD (HL),A ; AND STORE IN TABLE @ HL
- LD A,TRKTAB.LENGTH ;RECLENTAB next
- ADD A,L
- LD L,A
- LD A,(RECLEN)
- LD (HL),A ;Store it in reclen table
- SEL3: LD HL,RECLENTAB
- LD A,L
- ADD A,C ;INDEX INTO TABLE TO GET
- LD L,A ; RECLEN OF NEW DRIVE
- LD A,(HL)
- LD (RECLEN),A
- LD A,-TRKTAB.LENGTH ;Now get select data
- ADD A,L
- LD L,A
- LD A,(HL)
- CP 255 ;TEST IF NEW DRIVE HAS EVER BEEN
- JR NE,NXT111 ; SELECTED AND
- CALL LOGIN ;Do a LOGIN if not
- LD HL,0 ;for an error exit
- RET NZ
- ;If LOGIN fails leave drive logged off,HL=0
- NXT111: LD (TRACK),A ;Success,store the current head position
- ;Now wait for a while to allow time for head load solenoid
- IF IS5MHZ
- LD B,8 ;Loop four times
- ELSE
- LD B,4
- ENDIF ;IS5MHZ
-
- LP124: IN A,CTC3 ;Get current CTC3 value
- LD C,A ;Save it
- LP123: IN A,CTC3
- CP C ;Loop until it has changed
- JR NZ,LP123 ;The first may be a short cycle
- DJNZ LP124 ;the rest will be a full 5.5 msec at 5MHz
- ;
- RET20: LD A,(UNIT) ;get current unit
- RET21: LD H,0
- LD L,A ;Calculate DPHB addr
- ADD HL,HL
- ADD HL,HL
- ADD HL,HL
- ADD HL,HL ;MULTIPLY UNIT# BY 16
- LD DE,DPBASE
- ADD HL,DE ;ADD START ADDRESS OF DHP BLOCK
- XOR A ;No errors, HL points to DPBASE
- RET
- ;
- ;
- ;
- ; We log the disks in under HOME
- ; Home aways in S/D
- ;
- HOME:
- CALL DOSELECT
- RET NZ
- ;
- IN A,(BITDAT)
- SET 3,A ;select S/D
- RES 5,A ;select side 0
- OUT (BITDAT),A
- ;
- CALL TURNON ;CLEAR DISK CONTROLLER
- AND 10000001B ;Mask statuses
- RET NZ
- RESTOR: LD A,RSTCMD ;LOAD B WITH A RESTORE COMMAND
- CALL CMDOUT
- AND 10011000B ;Mask off TRK 0 status
- LD (TRACK),A ;SET TRACK# IN MEM TO ZERO (A is 0)
- RET ;If any errors trk# is wrong
- ;
- ;LOGIN checks the disk density
- ;
- LOGIN: CALL HOME
- RET NZ
-
- ;Now log on the disk to see if it is double or single density
- INC A ;read sector 1
- LD (SECTOR),A
- ;
- LD HL,(IOPTR)
- LD (OLDPTR),HL
- LD HL,LOGBUF ;default dsk buffer
- LD (IOPTR),HL
- ;
- LD A,80H ;Bit 7 set to indicate LOGread
- LD (RECLEN),A ;Default S/D
- CALL READ
- ;
- LD HL,(OLDPTR) ;Restore previos DMA addr
- LD (IOPTR),HL
- RET NZ ;to DSKERR
- ;
- LD HL,LOGBUF ;look for 'DS' on the label
- LD A,'D'
- CP (HL)
- JR NE,SINGLED
- INC HL
- LD A,'S'
- CP (HL)
- JR NE,SINGLED
- ; If we are here then it is at least double sided
- INC HL
- LD A,'D'
- CP (HL)
- JR NE,DOUBLES
- INC HL
- CP (HL)
- JR NE,DOUBLES
- ;Here it must be double sided double density
- LD A,11B ;128 bytes/sector +D/D + D/S
- JR SD2
- DOUBLES: LD A,10B ;128 bytes/sector +D/S
- JR SD2
- ; Load the sector length/2 for read/writes
- SINGLED: LD A,00B ;128 bytes/sector
- SD2: LD (RECLEN),A
- ;Now we must change the Disk Parameter Blocks
- LD HL,DPB0 ;The D/D disk parameter block
- LD BC,XLT0 ;The D/D interleave table
- BIT 0,A ;Test D/D flag
- JR NZ,SETPATCH ;If D/D then use those values
- LD HL,DPB1 ;Else load D/S values
- LD BC,XLT1
- BIT 1,A ;Test D/S flag
- JR NZ,SETPATCH
- LD HL,DPB2 ;Else load S/D DPBlk
- SETPATCH: ;Now have to calculate the patch address to use
- LD A,(UNIT)
- OR A ;Is it A:? (DPE0)
- JR NZ,NEXTPATCH ;No, patch DPE1
- LD (PATCH1),BC
- LD (PATCH2),HL
- JR DONEPATCH
- NEXTPATCH: LD (PATCH3),BC
- LD (PATCH4),HL
- DONEPATCH:
- XOR A
- RET
- ;
- ;
- ;
- SEEK:
- PUSH BC ;Save trk #
- CALL DOSELECT
- POP BC
- RET NZ
-
- CALL TURNON ;CLEAR DISK CONTROLLER
- BIT 7,A
- RET NZ ;EXIT IF DRIVE NOT READY
- LD A,(TRACK) ;Get current track#
- OUT TRKREG,A ;to the 1771
- LD HL,RECLEN ;Dont do next if D/D
- BIT 1,(HL) ;is it D/D ?
- SCF ;clr Carry
- CCF ;ready to select side 0
- JR Z,SK1 ;skip track/side calculation if S/D
- RR C ;now carry is side#, track is in C
- ;PA5 is side select
- SK1: IN A,(BITDAT) ;get side select mask
- RES 5,A ;default side 0 again
- LD B,0 ;use B as carry mask
- RR B ;carry into b7 of B
- RR B
- RR B ;now in b5 of B
- OR A,B ;OR BITDAT with B, the side select mask
- LD B,A ;save BITDAT (A) to B
- ;Are we reading a single or double density track?
- SET 3,B ;set up BITDAT mask for S/D
- BIT 5,B ;test side bit for side 1
- JR NZ,SK2 ;so that trk 0, side 0 is always S/D
- LD A,C
- OR A ;On side 0, is the trk # also = 0 ?
- JR Z,NSKP ;yes, always make trk 0, side 0, S/D
- SK2: BIT 0,(HL) ;(RECLEN) (Z=S/D)
- ; SET 3,B ;DD* bit is reset ready for single density
- JR Z,NSKP ; exit calculation if single density disk
- RES 3,B ;here it must be DD
- NSKP: LD A,B ;(get BITDAT mask back to A ready for)
- OUT (BITDAT),A
-
- LD A,(TRACK) ;GET old TRACK#
- SUB C ;Is new trk the same as the last?
- RET Z ;Yes,return with 0 in A
-
- LD A,C ;get new trk#
- LD (TRACK),A ; STORE TRACK# FOR SEEK
- OUT (DATREG),A ;OUTPUT TRACK # TO 1771
- LD A,SKCMD ;LOAD A WITH A SEEK COMMAND AND
- CALL CMDOUT
- AND 10011000B ;MASK TO READY,SEEK AND CRC ERROR
- PUSH AF
- ;
- ;Now a short delay to allow head to settle
- IF IS5MHZ
- LD B,6 ;Loop 6 times at 5MHz
- ELSE
- LD B,3
- ENDIF ;IS5MHZ
-
- LP24: IN A,CTC3 ;Get current CTC3 value
- LD C,A ;Save it
- LP23: IN A,CTC3
- CP C ;Loop until it has changed
- JR NZ,LP23 ;The first loop may be a short cycle
- DJNZ LP24 ;the rest will be a full 5.5 msec at 5MHz
- ;
- POP AF
- RET ;RETURN FINAL SEEK STATUS IN A
- ;
- ;
- ;We wont check if drive ready here, error handler will fix any exceptions
- ;Famous last words, system lost speed if following call to TURNON was omitted==
- WRITE: PUSH HL ;HL is required for SELECT errors
- CALL TURNON
- ; If disk is write protected prompt now
- BIT 6,A
- JP Z,NXT571 ;Z = OK
- CALL PNEXT ;Print to console
- DB CR,LF,7,'Disk is write protected',EOT
- CALL CPMIN ;Get any key to acknowledge message
- CALL TURNON ;Operator may be asleep
- NXT571: AND 11000001B
- POP HL
- RET NZ ;EXIT IF DRIVE NOT READY or still protected
- LD B,WRTCMD
- JR RDWRT
-
- READ:
- PUSH HL
- CALL TURNON
- AND 10000001B
- POP HL
- RET NZ ;EXIT IF DRIVE NOT READY
- LD B,RDCMD
- RDWRT: LD HL,CMDTYP
- LD (HL),B ;SAVE READ/WRITE COMMAND BYTE
- INC HL
- LD (HL),4 ;SET DISK OPERATION RE-TRY COUNT
- RW1: CALL SETUPNMI
- ;Are we reading a single or double density track?
- LD B,80H ;set up B for S/D
- SK4: ;B=NUMBER OF BYTES/SECTOR
- LD C,DATREG ;C=1771 DATA REGISTER PORT#
- LD A,(SECTOR) ;GET SECTOR NUMBER
- OUT (SECREG),A ;OUTPUT SECTOR# TO 1771
- CALL FORCE ;ISSUE A FORCE INTERRUPT COMMAND
- BIT 5,A ; TO TEST CURRENT HEAD LOAD STATUS
- LD A,(CMDTYP) ;GET READ OR WRITE COMMAND BYTE
- JR NZ,RW2 ;JUMP IF HEAD IS ALREADY LOADED
- OR HLOAD ; ELSE MERGE IN HLD BIT
- RW2:
- LD HL,RECLEN
- BIT 7,(HL)
-
- LD HL,(IOPTR) ;Set up DMA pointer
- OUT CMDREG,A ;START the 1771 reading/writing
-
- JP NZ,LOGLOOP ;Reclen test above
-
- BIT 5,A ;TEST IF COMMAND IS A READ OR WRITE
- JR NZ,WLOOP ; AND JUMP TO THE CORRECT LOOP
-
- RLOOP: HALT
- INI
- JP NZ,RLOOP
- RW6: CALL IRQ2
- AND 10011100B ;MASK OFF TO READY, NOT FOUND, CRC
- JR RW3 ; AND LOST DATA STATUS BITS
- ;
- LOGLOOP: LD B,7AH ;Bytes to discard
- LPZY2: HALT
- IN A,(C)
- DJNZ LPZY2 ;Speed not important as only S/D
- LD B,6
- LPZY3: HALT ;Now collect the data bytes
- INI
- JP NZ,LPZY3
- JR RW6
- ;
- WLOOP: HALT
- OUTI
- JP NZ,WLOOP
- CALL IRQ2
- AND 11111100B ;MASK OFF AS ABOVE PLUS WRITE FAULT
- RW3: RET Z ;RETURN IF NO DISK I/O ERRORS
- LD HL,RETRY
- DEC (HL) ;DECREMENT RE-TRY COUNT AND
- JR NZ,RW1 ;Execute command again if not=0
- OR A
- RET ;ELSE RETURN 1771 ERROR STATUS
-
- ;
- ;
- ;Forcing a D1 interrupt here hangs (197X app p3)
- CMDOUT: OUT CMDREG,A ;Output the command
- CALL SETUPNMI
- IRQ2: HALT
- CALL RESTORENMI
- IN A,STSREG
- RET
- ;
- FORCE: LD A,FINCMD
- OUT CMDREG,A
- LP7: IN A,STSREG
- BIT 0,A ;Still busy?
- JR NZ,LP7
- RET
- ;
- SETUPNMI: DI
- LD HL,NMIVEC
- LD D,(HL)
- LD A,0C9H
- LD (HL),A
- RET
- ;
- RESTORENMI: LD HL,NMIVEC
- LD (HL),D
- EI
- RET
- ;
- TURNON:
- LD A,30
- LD (MOTOR),A ;RE-LOAD THE MOTOR TURN-OFF TIMER
- ;Just testing the motors status here is no good if
- ; a new drive has just been selected
- ; Test to see if new drive is ready here
- CALL FORCE
- ; AND 11011001B ;do in main routines
- BIT 7,A ;Ready?
- RET Z ; AND EXIT IF STILL TURNED ON
- IN A,(BITDAT)
- AND 11111011B ;ELSE RE-ENABLE THE DRIVE SELECTS
- OUT (BITDAT),A ; AND ACTIVATE THE MOTOR RELAY
- PUSH BC
- LD B,0 ;SET READY LOOP MAX TIMEOUT
- ;
- TURN2: CALL WAIT ;WAIT 1/93 SECOND AND TEST READY
- RLA ;Test the ready status bit
- JR NC,TURN3 ;EXIT LOOP IF DRIVE READY
- DJNZ TURN2 ; ELSE TRY AGAIN UP TO 256 TIMES
- TURN3: LD B,4
- TURN4: CALL WAIT ;GIVE ABOUT 1/20 SECOND MORE DELAY
- DJNZ TURN4 ;to ensure no CRC errors
- ; CALL FORCE ;Done in WAIT
- ; AND 11011001B ;do in main routines
- POP BC
- RET
- ;
- ;
- WAIT: IN A,(CTC3) ;GET CURRENT CTC3 COUNT VALUE
- LD C,A
- WAIT2: IN A,(CTC3)
- CP C ;TEST IF CTC3 HAS CHANGED BY 1 COUNT
- JR Z,WAIT2 ; AND LOOP UNTIL IT CHANGES
- JR FORCE ; THEN GO TEST DRIVE READY STATUS
- ;
- ;
- ;****************************************
- ;* *
- ;* DISK I/O BUFFER, PARAMETER TABLES *
- ;* *
- ;****************************************
- ;
- DPBASE EQU $ ;BASE OF DISK PARAMETER BLOCKS
- ;Use two Single Sided Single Density Blocks
- ;Which can be patched as required
- DPE0:
- PATCH1: DW XLT1,0000H ;TRANSLATE TABLE
- DW 0000H,0000H ;SCRATCH AREA
- DW DIRBUF
- PATCH2: DW DPB2 ;DIR BUFF,PARM BLOCK
- DW CSV0,ALV0 ;CHECK, ALLOC VECTORS (Use largest ones always)
- DPE1:
- PATCH3: DW XLT1,0000H ;TRANSLATE TABLE
- DW 0000H,0000H ;SCRATCH AREA
- DW DIRBUF
- PATCH4: DW DPB2 ;DIR BUFF,PARM BLOCK
- DW CSV1,ALV1 ;CHECK, ALLOC VECTORS
- ;
- ; DOUBLE DENSITY DOUBLE SIDED
- ; DISKDEF 0,1,34H,4,4096,(77-2)*2*52/32,192,192,2
- DPB0 EQU $ ;DISK PARM BLOCK
- DW 52 ;SEC PER TRACK
- DB 5 ;BLOCK SHIFT
- DB 31 ;BLOCK MASK
- DB 0 ;EXTNT MASK
- DW 242 ;DISK SIZE-1
- DW 191 ;DIRECTORY MAX
- DB 192 ;ALLOC0
- DB 0 ;ALLOC1
- DW 48 ;CHECK SIZE
- DW 2 ;OFFSET
- ;
- ;SINGLE DENSITY DOUBLE SIDED
- ; DISKDEF 1,1,1AH,6,2048,(77-2)*2*1AH/16,128,128,2
- DPB1 EQU $ ;DISK PARM BLOCK
- DW 26 ;SEC PER TRACK
- DB 4 ;BLOCK SHIFT
- DB 15 ;BLOCK MASK
- DB 0 ;EXTNT MASK
- DW 242 ;DISK SIZE-1
- DW 127 ;DIRECTORY MAX
- DB 192 ;ALLOC0
- DB 0 ;ALLOC1
- DW 32 ;CHECK SIZE
- DW 2 ;OFFSET
- ;
- ;SINGLE DENSITY SINGLE SIDED
- ; DISKDEF 1,1,1AH,6,1024,(77-2)*1AH/8,64,64,2
- DPB2 EQU $ ;DISK PARM BLOCK
- DW 26 ;SEC PER TRACK
- DB 3 ;BLOCK SHIFT
- DB 7 ;BLOCK MASK
- DB 0 ;EXTNT MASK
- DW 242 ;DISK SIZE-1
- DW 63 ;DIRECTORY MAX
- DB 192 ;ALLOC0
- DB 0 ;ALLOC1
- DW 16 ;CHECK SIZE
- DW 2 ;OFFSET
- ;
- XLT0: ;TRANSLATE TABLE (Double Density)
- DB 1,5,9,13,17,21,25,29,33,37,41,45,49,2,6,10,14,18,22,26,30,34
- DB 38,42,46,50,3,7,11,15,19,23,27,31,35,39,43,47,51,4,8,12,16,20
- DB 24,28,32,36,40,44,48,52
- ;
- XLT1: ;TRANSLATE TABLE (IBM)
- 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
- ;
- DIRBUF: DS 128 ;DIRECTORY ACCESS BUFFER
- ;
- ALLOCATION.VECTORS: ;Must be zeroed on Warm Boot
- ALV0: DS 31 ;Double Sided, Double Density
- CSV0: DS 48
- ;
- ALV1: DS 31
- CSV1: DS 48
- VECTORS.LENTH: EQU $-ALLOCATION.VECTORS
- ;
- ;
- ;These are smaller, and not required
- ;ALV: DS 31 ;Double Sided Single Density
- ;CSV: DS 16
- ;ALV: DS 31 ;Single Sided Single Density same as DSSD
- ;CSV: DS 16
- ;
- ;
- LOGBUF: DS 6 ;For logging in disks
- ;
- SAVE.DRIVE: DS 1
- ;
- END.ROM: EQU $ !Ignore error
- ;
- ;
- ;********************************************************
- ;* *
- ;* STORAGE ALLOCATION FOR 256 BYTE FIXED RAM *
- ;* *
- ;********************************************************
- ;
- ORG 0FF00H ;Top page of RAM
- :
- MEM: EQU $
- ;
-
- VECTAB EQU $ ;INTERRUPT VECTOR TABLE STARTS HERE
- SIOVEC: DEFS 16 ;SPACE FOR 8 VECTORS FOR SIO
- CTCVEC: DEFS 8 ;SPACE FOR 4 VECTORS FOR CTC
- SYSVEC: DEFS 4 ;SPACE FOR 2 VECTORS FOR SYSTEM PIO
- GENVEC: DEFS 4 ;SPACE FOR 2 VECTORS FOR GENERAL PIO
- ;
- ;
- ;
- ; DISK I/O DRIVER VARIABLES
- ; Be careful not to straddle a Page Boundary with these
- UNIT: DEFS 1 ;CURRENTLY SELECTED DISK#
- TRKTAB: DEFS 2 ;2 DRIVE HEAD POSITION TABLE
- TRKTAB.LENGTH: EQU $-TRKTAB
- RECLENTAB: DS 2 ;2 Drive record length table
- MOTOR: DEFS 1 ;DRIVE MOTOR TURN-OFF TIMER
- RECLEN: DEFS 1 ;Current disk 'Record Length'
- TRACK: DEFS 1
- SECTOR: DEFS 1
- CMDTYP: DEFS 1 ;COMMAND BYTE FOR READS/WRITES
- RETRY: DEFS 1 ;DISK OPERATION RE-TRY COUNT
- IOPTR: DEFS 2 ;DISK I/O BUFFER POINTER
- OLDPTR: DS 2 ;A scratch location used by RESTORE
- RWFLAG: DS 1 ;Discriminates reads/writes
- ;
- ;
- ;
- ; KEYBOARD DATA INPUT FIFO VARIABLES
-
- FIFO: DEFS 16 ;CONSOLE INPUT FIFO
- FIFCNT: DEFS 1 ;FIFO DATA COUNTER
- FIFIN: DEFS 1 ;FIFI INPUT POINTER
- FIFOUT: DEFS 1 ;FIFO OUTPUT POINTER
- ;
- ;
- ; STACK POINTER SAVE AND LOCAL STACK FOR INTERRUPT ROUTINES
- TMPSTK: EQU $ ;Internal stack for all routines
- DEFS 16 ;LOCAL STACK FOR INTERRUPTS
- SPSAVE: DS 2 ;Save stack pointer
- ;
- ;
- ; 'SOFTWARE' VECTORS FOR INTERRUPT SERVICE ROUTINES
-
- TIKVEC: DEFS 2 ;ONE SECOND INTERRUPT ROUTINE VECTOR
- PINVEC: DEFS 2 ;PARALLEL CONSOLE INPUT VECTOR
- SINVEC: DEFS 2 ;SERIAL CONSOLE INPUT VECTOR
- ;
- ;
- ; CLOCK-TIMER INTERRUPT VARIABLES
-
- TIKCNT: DEFS 2 ;BINARY CLOCK TICK COUNTER
- DAY: DEFS 1 ;CALENDAR DAY
- MONTH: DEFS 1 ; MONTH
- YEAR: DEFS 1 ; YEAR
- HRS: DEFS 1 ;CLOCK HOURS REGISTER
- MINS: DEFS 1 ; MINUTES RETISTER
- SECS: DEFS 1 ; SECONDS REGISTER
- ;
- ; CRT OUTPUT DRIVER VARIABLES
-
- CURSOR: DEFS 2 ;CURSOR POINTER
- CHRSAV: DEFS 1 ;CHARACTER OVERLAYED BY CURSOR
- CSRCHR: DEFS 1 ;CHARACTER USED FOR A CURSOR
- BASE: DEFS 1 ;CURRENT CONTENTS OF SCROLL REGISTER
- LEADIN: DEFS 1 ;STATE OF LEAD-IN SEQUENCE HANDLER
- ;
- ;
- ; NULL PAD COUNT FOR SERIAL OUTPUT DELAY
-
- ;NULLS: DEFS 1 ;# OF NULLS SENT AFTER CONTROL CHARS.
- ;
- ;
- ; CONSOLE MONITOR PROGRAM VARIABLES
-
- PARAM1: DEFS 2 ;STORAGE FOR NUMBERS READ
- PARAM2: DEFS 2 ; FROM LINE INPUT BUFFER
- PARAM3: DEFS 2 ; BY 'PARAMS' SUBROUTINE
- PARAM4: DEFS 2
- ESCFLG: DEFS 1 ;CONSOLE ESCAPE FLAG
- COFLAG: DEFS 1 ;CONSOLE OUTPUT TOGGLE
- LAST: DEFS 2 ;LAST ADDRESS USED BY 'MEMDMP'
- HLSAV: DS 2 ;Storage of values at entry
- DESAV: DS 2
- BCSAV: DS 2
- SPSAV: DS 2
- ROUTINE.ADDRESS: DS 2 ;Where to restart on errors
- OFFSET: DS 1 ;the offset (function #)
- LINBUF: DEFS 64 ;CONSOLE LINE INPUT BUFFER
- ;
- STACK: EQU 0FFFFH ;Top of memory
- ;STACKLENGTH: EQU STACK-[LINBUF+64] !Ignore error
- ;
- END