home *** CD-ROM | disk | FTP | other *** search
- ;;; RM80 V2.0 - RESIDENT MONITOR FOR AN 8080 / Z80 SYSTEM
- ;
- ; LAWRENCE E. HUGHES III
- ; 8080 SOFTWARE DEVELOPMENT CENTER
- ; 1506 MYRICK ROAD
- ; TALLAHASSEE, FLORIDA 32303
-
- ORG 5800H
- TBUF: DS 1024 ;TAPE BUFFER
- NBUF: DS 11 ;FILENAME BUFFER
- TUNIT: DS 1 ;TAPE UNIT BUFFER
- PRN: DS 1 ;PHYSICAL RECORD NUMBER
- CTPC: DS 1 ;CASSETTE TAPE PAGE COUNT
- IBUF: DS 128 ;INPUT BUFFER
- STACK: DS 64 ;SYSTEM STACK AREA
- PFLAG1: DS 1 ;PARAMETER FLAGS
- PFLAG2: DS 1
- PARAM1: DS 2 ;PARAMETERS
- PARAM2: DS 2
- CBUF: DS 6 ;COMMAND BUFFER
- INCH: DS 1 ;CHARACTER BUFFERS FOR LINK
- OUTCH: DS 1
- DMPAD: DS 2 ;DUMP ADDRESS
- CRC: DS 2 ;TEMP STORAGE FOR TAPE CRC
- LDERR: DS 1 ;LOADER ERROR COUNT
- OFLST: DS 1 ;OBJECT FILE LOADER STATE
- OFLCE: DS 1 ;OBJECT FILE LOADER CHECKSUM ERROR FLAG
- OFLLA: DS 2 ;OBJECT FILE LOADER LOAD ADDRESS
- OFLOS: DS 2 ;OBJECT FILE LOADER OFFSET
- OFLBC: DS 1 ;OBJECT FILE LOADER BYTE COUNT
- OFLCS: DS 1 ;OBJECT FILE LOADER CHECKSUM
- OFLBB: DS 1 ;OBJECT FILE LOADER BYTE BUFFER
- OFLSW: DS 1 ;OBJECT FILE LOADER SWITCH (NON-ZERO = ON)
- TFLSW: DS 1 ;TEXT FILE LOADER SWITCH (NON-ZERO = ON)
- TFLFWA: DS 2 ;TEXT FILE LOADER FIRST WORD ADDRESS
- TFLLWA: DS 2 ;TEXT FILE LOADER LAST WORD ADDRESS
- TEMP: DS 3 ;TEMPORARY AREA FOR IN AND OUT COMMANDS
-
- NULL EQU 00H
- SOH EQU 01H
- STX EQU 02H
- ETX EQU 03H
- BS EQU 08H
- LF EQU 0AH
- CR EQU 0DH
- DEL EQU 7FH
-
- ;;; MAIN PROGRAM - GET COMMAND, SCAN IT AND BRANCH
-
- ORG 0C000H
- JMP RM80
- JMP RACC ;READ ASCII CHAR FROM CONSOLE
- JMP CRDAC ;CHECK FOR RDA FROM CONSOLE
- JMP WACC ;WRITE ASCII CHAR TO CONSOLE
- JMP CTBEC ;CHECK FOR TBE FROM CONSOLE
- JMP RACM ;READ ASCII CHARACTER FROM MODEM
- JMP CRDAM ;CHECK FOR RDA FROM MODEM
- JMP WACM ;WRITE ASCII CHARACTER TO MODEM
- JMP CTBEM ;CHECK FOR TBE FROM MODEM
- JMP CTRR ;READ PHYSICAL RECORD FROM TAPE
- JMP CTWR ;WRITE PHYSICAL RECORD TO TAPE
- JMP MOVEUP ;MOVE BLOCK OF MEMORY TOWARDS 0000
- JMP MOVEDN ;MOVE BLOCK OF MEMORY TOWARDS FFFF
- JMP DMP ;DUMP BLOCK OF MEMORY IN HEX/ASCII
- JMP RASC ;READ ASCII STRING FROM CONSOLE
- JMP DHS ;DECODE HEX STRING
-
- RM80: LXI SP,STACK+64
- CALL INITC ;INITIALIZE CONSOLE
- CALL INITM ;INITIALIZE MODEM
- CALL INITT ;INITIALIZE TAPE
- LXI H,0 ;CLEAR OBJECT FILE LOADER OFFSET
- SHLD OFLOS
- CALL WEOLC
- LXI H,RM80S1 ;PRINT 'RM80 V2.0'
- CALL WASC
-
- RM801: MVI A,')' ;ISSUE PROMPT CHAR
- CALL WACC
- LXI H,IBUF ;READ COMMAND INTO IBUF
- CALL RASC
- MVI M,' ' ;INSURE AT LEAST ONE BLANK AT END
- INX H
- MVI M,CR
- LXI D,IBUF ;PARSE COMMAND
- LXI H,CBUF ;SCAN OFF KEYWORD INTO CBUF
- MVI C,6 ;MAX KEYWORD SIZE
- RM802: LDAX D ;FETCH NEXT CHAR FROM IBUF
- INX D
- CPI 61H ;IF LC, CONVERT TO UC
- JC $+5
- SUI 20H
- CPI ' ' ;EXIT AT END-OF-KEYWORD
- JZ RM803
- MOV M,A ;STORE IN CBUF
- INX H
- DCR C ;LOOP IF 5 OR LESS CHARS SO FAR
- JNZ RM802
- JMP RM80X ;ELSE TAKE ERROR EXIT
- RM803: INR C ;BLANK FILL REST OF CBUF
- DCR C
- JZ RM804
- MVI M,' '
- INX H
- JMP RM803+1
- RM804: XRA A ;CLEAR PARAMETER FLAGS
- STA PFLAG1
- STA PFLAG2
- CALL DHS ;DECODE FIRST PARAMETER INTO HL
- JC RM80X ;BRANCH ON ERROR
- STA PFLAG1
- SHLD PARAM1 ;SAVE FIRST PARAMETER
- CALL DHS ;DECODE SECOND PARAMETER
- JC RM80X ;BRANCH ON ERROR
- STA PFLAG2
- SHLD PARAM2 ;SAVE SECOND PARAMETER
- LDA PFLAG1 ;IF NO FIRST PARAM, DEFAULT TO 100H
- ORA A
- JNZ $+9
- LXI H,100H
- SHLD PARAM1
- LDA PFLAG2 ;IF NO SECOND PARAM, DEFAULT TO PARAM1
- ORA A
- JNZ $+9
- LHLD PARAM1
- SHLD PARAM2
- RM805: LXI H,CTAB ;LOOKUP KEYWORD IN COMMAND TABLE
- RM806: LXI D,CBUF
- MVI C,5 ;NUMBER OF BYTES TO COMPARE
- MVI B,1 ;SET MATCH FLAG
- RM807: LDAX D ;FETCH NEXT BYTE OF KEYWORD
- CMP M ;COMPARE WITH NEXT BYTE OF TABLE
- JZ $+5 ;JUMP IF GOOD COMPARE
- MVI B,0 ;CLEAR MATCH FLAG
- INX D ;INCREMENT POINTERS
- INX H
- DCR C ;LOOP THRU ENTIRE KEYWORD
- JNZ RM807
- DCR B ;TEST MATCH FLAG
- JZ RM808 ;JUMP IF GOOD MATCH
- INX H ;ELSE SKIP ADDR FIELD
- INX H
- MOV A,M ;LOOP IF NOT END OF TABLE
- ORA A
- JNZ RM806
- LXI H,RM80S2 ;PRINT 'ILLEGAL COMMAND'
- CALL WASC
- JMP RM801 ;AND LOOP
- RM808: MOV E,M ;FETCH ADDR FIELD INTO DE
- INX H
- MOV D,M
- LXI B,RM801 ;CREATE A RETURN ADDRESS
- PUSH B
- PUSH D ;FORCE JUMP ADDR ONTO STACK
- LHLD PARAM2 ;DE = SECOND PARAMETER
- XCHG
- LHLD PARAM1 ;HL = FIRST PARAMETER
- RET ;WOULD YOU PREFER 'POP PC'?
-
- RM80X: LXI H,RM80S3 ;PRINT 'SYNTAX ERROR'
- CALL WASC
- JMP RM801 ;AND LOOP
-
- RM80S1: DB 'RM80 V2.0',CR,LF,0
- RM80S2: DB 'ILLEGAL COMMAND',CR,LF,0
- RM80S3: DB 'SYNTAX ERROR',CR,LF,0
-
- ; COMMAND TABLE
-
- CTAB: DB 'DUMP '
- DW DUMP
- DB 'TYPE '
- DW TYPE
- DB 'ENTER'
- DW ENTER
- DB 'TEXT '
- DW TEXT
- DB 'MOVE '
- DW MOVE
- DB 'FILL '
- DW FILL
- DB 'GO '
- DW GO
- DB 'STORE'
- DW STORE
- DB 'FETCH'
- DW FETCH
- DB 'CHECK'
- DW CHECK
- DB 'UNIT '
- DW UNIT
- DB 'WRITE'
- DW WRITE
- DB 'READ '
- DW READ
- DB 'LOAD '
- DW LOAD
- DB 'SCAN '
- DW SCAN
- DB 'LINK '
- DW LINK
- DB 'SOLO '
- DW SOLO
- DB 'IN '
- DW RIP
- DB 'OUT '
- DW WOP
- DB 0 ;END OF COMMAND TABLE
-
- ;; RIP - READ INPUT PORT (AND DISPLAY)
-
- RIP: MVI A,0DBH ;JAM INPUT INSTRUCTION
- STA TEMP+0
- MOV A,L ;PORT ADDRESS
- STA TEMP+1
- MVI A,0C9H ;JAM RETURN INSTRUCTION
- STA TEMP+2
- CALL TEMP ;EXECUTE INPUT COMMAND
- CALL WHBC ;WRITE BYTE IN HEX
- JMP WEOLC ;EXIT VIA WEOLC
-
- ;; WOP - WRITE OUTPUT PORT
-
- WOP: MVI A,0D3H ;JAM OUTPUT INSTRUCTION
- STA TEMP+0
- MOV A,L ;PORT NUMBER
- STA TEMP+1
- MVI A,0C9H ;JAM RETURN INSTRUCTION
- STA TEMP+2
- MOV A,E ;BYTE TO OUTPUT
- CALL TEMP ;EXECUTE OUTPUT COMMAND
- JMP WEOLC ;EXIT VIA WEOLC
-
- ;; DUMP - RM80 DUMP COMMAND
-
- DUMP: LDA PFLAG1 ;JUMP IF NO PARAMETERS
- ORA A
- JZ DUMP1
- CALL DIFF ;DE=DE-HL+1
- INX D
- SHLD DMPAD ;SET DUMP ADDRESS TO REAL FWA
- JMP DMP ;PERFORM DUMP AND RETURN
- DUMP1: LXI H,0 ;SET DUMP ADDRESS TO ZERO
- SHLD DMPAD
- DUMP2: LXI H,TBUF ;READ NEXT RECORD FROM TAPE
- LXI B,NBUF
- CALL CTRR
- CALL WEOLC
- CALL CTPH ;PRINT HEADER INFO (NAME, TYPE, ETC)
- MOV A,D ;SAVE PAGE COUNT
- STA CTPC
- LXI H,TBUF ;DUMP RECORD
- CALL DMP
- LDA CTPC ;FETCH PAGE COUNT
- CPI 4 ;LOOP UNLESS SHORT RECORD
- JNC DUMP2
- RET
-
- ;; TYPE - RM80 TYPE COMMAND
-
- TYPE: LDA PFLAG1 ;JUMP IF NO PARAMETERS
- ORA A
- JZ TYPE2
- CALL DIFF ;DE = DE-HL+1
- INX D
- TYPE1: MOV A,D ;EXIT WHEN DE=0
- ORA E
- JZ WEOLC
- MOV A,M ;FETCH NEXT BYTE
- CPI 'Z'-40H ;EXIT IF END-OF-FILE CHAR
- JZ WEOLC
- INX H
- CALL WACC ;WRITE IT - USER ASKED FOR IT
- DCX D ;DECREMENT COUNT AND LOOP
- JMP TYPE1
- TYPE2: LXI H,TBUF ;READ NEXT RECORD FROM TAPE
- LXI B,NBUF
- CALL CTRR
- MOV A,D ;SAVE PAGE COUNT
- STA CTPC
- LXI H,TBUF ;TYPE CONTENTS OF RECORD
- TYPE3: MOV A,D ;EXIT WHEN COUNT=0
- ORA E
- JZ TYPE4
- MOV A,M ;WRITE NEXT BYTE
- CPI 'Z'-40H ;EXIT IF END-OF-FILE CHAR
- JZ WEOLC
- INX H
- CALL WACC
- DCX D ;DECREMENT COUNT
- JMP TYPE3
- TYPE4: LDA CTPC ;FETCH PAGE COUNT
- CPI 4 ;LOOP IF NOT SHORT RECORD
- JNC TYPE2
- JMP WEOLC ;WRITE END-OF-LINE AND RETURN
-
- ;; ENTER - RM80 ENTER COMMAND
-
- ENTER: MOV A,H ;PROMPT WITH CURRENT LOAD ADDRESS
- CALL WHBC
- MOV A,L
- CALL WHBC
- MVI A,'?'
- CALL WACC
- MVI A,' '
- CALL WACC
- PUSH H ;SAVE LOAD ADDRESS
- LXI H,IBUF ;READ INPUT LINE
- CALL RASC
- DCR B ;EXIT ON EMPTY LINE
- JZ ENTER3
- LXI D,IBUF ;DECODE AND LOAD BYTES ON THIS LINE
- ENTER1: CALL DHS ;DECODE NEXT BYTE
- JC ENTERX
- ORA A ;EXIT AT END OF LINE
- JZ ENTER2
- MOV A,L
- POP H ;RESTORE LOAD ADDRESS
- MOV M,A ;LOAD BYTE INTO MEMORY
- INX H ;INCREMENT LOAD ADDRESS
- PUSH H ;SAVE LOAD ADDRESS AWAY AGAIN
- JMP ENTER1 ;LOOP
- ENTER2: POP H ;RESTORE LOAD ADDRESS
- JMP ENTER ;AND GO ON WITH NEXT LINE
- ENTER3: POP H ;CLEAR STACK AND EXIT
- JMP WEOLC
- ENTERX: POP H
- LXI H,ENTERS1
- JMP WASC
-
- ENTERS1: DB 'ERROR',CR,LF,0
-
- ;; TEXT - RM80 TEXT COMMAND
-
- TEXT: PUSH H ;SAVE LOAD ADDRESS
- MOV A,H ;PROMPT WITH CURRENT LOAD ADDRESS
- CALL WHBC
- MOV A,L
- CALL WHBC
- MVI A,'?'
- CALL WACC
- MVI A,' '
- CALL WACC
- LXI H,IBUF
- CALL RASC ;READ NEXT LINE FROM CONSOLE
- DCR B ;EXIT ON EMPTY LINE (JUST CR)
- JZ TEXT2
- INR B
- POP H ;RESTORE LOAD ADDRESS
- LXI D,IBUF ;STORE LINE IN MEMORY
- TEXT1: LDAX D ;FETCH NEXT CHAR FROM IBUF
- INX D
- MOV M,A ;STORE IN MEMORY
- INX H
- DCR B ;DECREMENT COUNT
- JNZ TEXT1 ;LOOP UNTIL END-OF-LINE
- MVI M,LF ;STORE A LINE FEED AFTER CR
- INX H
- JMP TEXT ;LOOP
- TEXT2: POP H ;CLEAR STACK AND RETURN
- RET
-
- ;; MOVE - RM80 MOVE COMMAND
-
- MOVE: CALL DIFF ;DE = DE-HL+1
- INX D
- PUSH D
- PUSH H
- LXI H,MOVES1 ;PRINT 'TO?'
- CALL WASC
- LXI H,IBUF ;READ RESPONSE
- CALL RASC
- LXI D,IBUF ;DECODE VALUE
- CALL DHS
- JNC MOVE0 ;JUMP IF NO ERRORS
- POP H
- POP D
- JMP PERR
- MOVE0: XCHG ;DE = BC = FWA DEST.
- MOV B,D
- MOV C,E
- POP H ;HL = FWA SOURCE
- CALL DIFF ;DE = FWA DEST - FWA SOURCE
- POP D ;DE = SOURCE SIZE
- JNC MOVEDN ;FWA DEST > FWA SOURCE
- JMP MOVEUP ;FWA DEST < FWA SOURCE
-
- MOVES1: DB 'TO? ',0
-
- ;; FILL - RM80 FILL COMMAND
-
- FILL: CALL DIFF
- INX D
- PUSH H
- PUSH D
- LXI H,FILLS1 ;PRINT 'WITH? '
- CALL WASC
- LXI H,IBUF ;READ ANSWER
- CALL RASC
- LXI D,IBUF ;DECODE IT
- CALL DHS
- JNC FILL0 ;JUMP IF OK
- POP D ;ELSE CLEAR STACK AND TAKE ERROR EXIT
- POP H
- JMP PERR
- FILL0: MOV B,L ;B = FILL BYTE
- POP D
- POP H
- FILL1: MOV A,D ;RETURN WHEN COUNT=0
- ORA E
- RZ
- MOV M,B ;STORE FILL BYTE
- INX H
- DCX D ;DECREMENT COUNT AND LOOP
- JMP FILL1
-
- FILLS1: DB 'WITH? ',0
-
- ;; GO - RM80 GO COMMAND
-
- GO: PCHL ;SHUFFLE OFF TO PARAM1
-
- ;; STORE - RM80 STORE COMMAND
-
- STORE: CALL DIFF ;DE = DE-HL+1
- INX D
- LDA TUNIT ;TURN ON MOTOR
- OUT CASSTA
- MVI B,15 ;WAIT 1.5 SECONDS
- CALL WTS
- MVI A,3CH ;WRITE START BYTE
- CALL CTWBX
- MVI A,0E6H ;WRITE SYNC BYTE
- CALL CTWBX
- MVI B,0 ;CLEAR CHECKSUM
- STORE1: MOV A,M ;FETCH NEXT BYTE
- INX H
- CALL CTWBX ;WRITE IT
- DCX D ;DECREMENT COUNT
- MOV A,D ;LOOP UNTIL COUNT=0
- ORA E
- JNZ STORE1
- MOV A,B ;WRITE CHECKSUM
- CALL CTWBX
- MVI B,5 ;WAIT 0.5 SECONDS
- CALL WTS
- XRA A ;TURN OFF MOTOR
- OUT CASSTA
- RET
-
- CTWBX: PUSH PSW ;AWAIT TBE (INVERTED)
- IN CASSTA
- ANI CASTBE
- JNZ $-4
- POP PSW
- OUT CASDAT ;WRITE BYTE
- CMA ;DISPLAY ON LIGHTS
- OUT 0FFH
- CMA
- PUSH PSW ;ADD BYTE INTO CHECKSUM
- ADD B
- MOV B,A
- POP PSW
- RET
-
- ;; FETCH - RM80 FETCH COMMAND
-
- FETCH: CALL DIFF ;DE = DE-HL+1
- INX D
- LDA TUNIT ;TURN ON MOTOR AND ENTER HUNT MODE
- ORI CASEHM
- OUT CASSTA
- MVI B,0 ;CLEAR CHECKSUM
- FETCH1: CALL CTRBX ;READ NEXT BYTE
- MOV M,A ;STORE IT
- INX H
- DCX D ;DECREMENT COUNT
- MOV A,D ;LOOP UNTIL COUNT=0
- ORA E
- JNZ FETCH1
- FETCH2: MOV C,B ;SAVE NEW CHECKSUM
- CALL CTRBX ;READ OLD ONE
- MOV B,A
- XRA A ;TURN OFF MOTOR
- OUT CASSTA
- MOV A,B ;RETURN IF CHECKSUMS COMPARE GOOD
- CMP C
- RZ
- LXI H,FETCHS1 ;ELSE PRINT 'CHECKSUM ERROR'
- JMP WASC
-
- FETCHS1: DB 'CHECKSUM ERROR',CR,LF,0
-
- CTRBX: IN CASSTA ;AWAIT RDA (INVERTED)
- ANI CASRDA
- JNZ $-4
- IN CASDAT ;READ BYTE
- CMA ;DISPLAY ON LIGHTS
- OUT 0FFH
- CMA
- PUSH PSW ;ADD BYTE INTO CHECKSUM
- ADD B
- MOV B,A
- POP PSW
- RET
-
- ;; CHECK - RM80 CHECK COMMAND
-
- CHECK: CALL DIFF ;DE = DE-HL+1
- INX D
- LDA TUNIT ;TURN ON MOTOR AND ENTER HUNT MODE
- ORI CASEHM
- OUT CASSTA
- MVI B,0 ;CLEAR CHECKSUM
- CHECK1: CALL CTRBX ;READ NEXT BYTE
- DCX D ;DECREMENT COUNT
- MOV A,D ;LOOP UNTIL COUNT=0
- ORA E
- JNZ CHECK1
- JMP FETCH2 ;REST IS SAME AS FETCH
-
- ;; UNIT - RM80 UNIT COMMAND
-
- UNIT: MOV A,L
- STA TUNIT
- RET
-
- ;; SCAN - RM80 SCAN COMMAND
-
- SCAN: LXI H,TBUF ;READ NEXT RECORD
- LXI B,NBUF
- CALL CTRR
- CALL CTPH ;PRINT HEADER INFO
- MOV A,D ;IF END-OF-FILE, SKIP ONE LINE
- CPI 4
- CC WEOLC
- JMP SCAN ;LOOP (EXIT VIA CONSOLE BREAKIN)
-
- ;; WRITE - RM80 WRITE COMMAND
-
- WRITE: LDA PFLAG1 ;JUMP IF 1ST PARAM ABSENT
- ORA A
- RZ
- LDA PFLAG2 ;JUMP IF 2ND PARAM PRESNT
- ORA A
- JNZ WRITE1
- MOV D,L ;DE = (PARAM1+1)*256-1 = LWA
- INR D
- MVI E,0
- DCX D
- LXI H,100H ;SET DEFAULT FWA
- WRITE1: CALL DIFF ;DE = DE-HL+1 = FILE SIZE
- INX D
- PUSH D
- XRA A ;PRN = 0
- STA PRN
- CALL GFNC ;GET CP/M FILE NAME FROM CONSOLE
- WRITE2: MOV A,D ;JUMP IF LESS THAN ONE PRU LEFT
- CPI 4
- JC WRITE3
- PUSH D ;SAVE FILE SIZE
- LXI D,400H ;SET PHYS REC SIZE
- LXI B,NBUF ;POINT TO NAME BUFFER
- CALL CTWR ;WRITE FULL PRU
- POP D ;RESTORE FILE SIZE
- MOV A,D ;DE = DE - 400H
- SUI 4
- MOV D,A
- JMP WRITE2
- WRITE3: LXI B,NBUF ;POINT TO NAME BUFFER
- CALL CTWR ;WRITE LAST PRU (SHORT)
- POP D ;RESTORE FILE SIZE
- MOV A,D ;PRINT FILE SIZE IN HEX
- CALL WHBC
- MOV A,E
- CALL WHBC
- LXI H,WRITES1 ;PRINT 'BYTES WRITTEN' AND EXIT
- JMP WASC
-
- WRITES1: DB ' BYTES WRITTEN',CR,LF,0
-
- ;; READ - RM80 READ COMMAND
-
- READ: PUSH H
- READ1: LXI H,TBUF ;READ NEXT RECORD
- LXI B,NBUF
- CALL CTRR
- CALL CTPH
- MOV A,D ;SAVE PAGE COUNT
- STA CTPC
- LXI H,TBUF
- READ2: MOV A,D ;EXIT WHEN COUNT = 0
- ORA E
- JZ READ4
- MOV A,M ;FETCH NEXT BYTE FROM TBUF
- INX H
- XTHL
- MOV M,A ;STORE AT LOAD ADDRESS
- INX H ;INCREMENT LOAD ADDRESS
- XTHL
- DCX D ;DECREMENT COUNT
- JMP READ2
- READ4: LDA CTPC ;FETCH PAGE COUNT
- CPI 4 ;LOOP IF NOT SHORT RECORD
- JNC READ1
- POP H ;CLEAR STACK
- RET
-
- ;; LOAD - RM80 LOAD COMMAND
-
- LOAD: XRA A ;INIT OBJECT FILE LOADER
- STA OFLST
- STA OFLCE
- STA LDERR ;CLEAR LOADER ERROR COUNT
- LOAD1: LXI H,TBUF
- LXI B,NBUF
- CALL CTRR ;READ NEXT RECORD
- CALL CTPH
- MOV A,D ;SAVE PAGE COUNT
- STA CTPC
- LXI H,TBUF
- LOAD2: MOV A,D ;EXIT WHEN COUNT=0
- ORA E
- JZ LOAD4
- MOV A,M ;FETCH NEXT BYTE
- INX H
- CALL OFL ;INVOKE OBJECT FILE LOADER ON BYTE
- LDA OFLCE ;JUMP IF NO CHECKSUM ERROR
- ORA A
- JZ LOAD3
- LDA LDERR ;INCREMENT LOADER ERROR COUNT
- INR A
- STA LDERR
- XRA A ;RESET CHECKSUM ERROR FLAG
- STA OFLCE
- LOAD3: DCX D ;DECREMENT COUNT AND LOOP
- JMP LOAD2
- LOAD4: LDA CTPC ;FETCH PAGE COUNT
- CPI 4 ;LOOP IF NOT SHORT RECORD
- JNC LOAD1
- LXI H,LOADS1 ;PRINT 'ERROR COUNT = '
- CALL WASC
- LDA LDERR ;PRINT ERROR COUNT
- CALL WHBC
- JMP WEOLC ;EXIT VIA WEOLC
-
- LOADS1: DB 'ERROR COUNT = ',0
-
- ;; LINK - RM80 LINK COMMAND
-
- LINK: XRA A ;CLEAR CHAR BUFFERS
- STA INCH
- STA OUTCH
- STA OFLSW ;START WITH OBJECT FILE LOADER OFF
- STA TFLSW ;START WITH TEXT FILE LOADER OFF
- SHLD TFLFWA ;SET FWA FOR TEXT FILE LOADER
- SHLD TFLLWA ;SET LWA FOR TEXT FILE LOADER
- LINK1: CALL CRDAC ;ANYTHING FROM CONSOLE?
- JNC LINK2 ;JUMP IF NOT
- CALL RACC ;ELSE READ CHAR FROM CONSOLE
- CPI 20H ;IF CONTROL CODE TYPED, CALL PCC
- CC PCC
- JC LINK2 ;JUMP IF CODE PROCESSED
- ORI 80H ;SAVE IT AWAY FOR LATER
- STA OUTCH
- LINK2: CALL CTBEC ;CONSOLE READY FOR DATA?
- JNC LINK3 ;JUMP IF NOT
- LDA INCH ;DO WE GOT ANY GOODIES FOR IT?
- ORA A
- JP LINK3 ;JUMP IF NOT
- ANI 7FH ;ELSE WRITE CHAR TO CONSOLE
- CALL WACC
- XRA A ;CLEAR INPUT CHAR BUFFER
- STA INCH
- LINK3: CALL CRDAM ;ANYTHING FROM MODEM?
- JNC LINK4 ;JUMP IF NOT
- CALL RACM ;ELSE READ CHAR FROM MODEM
- MOV B,A ;IF OFL ENABLED, CALL OFL
- LDA OFLSW
- ORA A
- MOV A,B
- JZ $+12
- PUSH PSW
- CALL OFL
- POP PSW
- CMA
- OUT 0FFH
- CMA
- MOV B,A ;IF TFL ENABLED, CALL TFL
- LDA TFLSW
- ORA A
- MOV A,B
- JZ $+10
- CALL TFL
- CMA
- OUT 0FFH
- CMA
- ORI 80H ;SAVE IT AWAY FOR LATER
- STA INCH
- LINK4: CALL CTBEM ;MODEM READY FOR MORE DATA?
- JNC LINK5 ;JUMP IF NOT
- LDA OUTCH ;DO WE GOT ANY GOODIES FOR IT
- ORA A
- JP LINK5 ;JUMP IF NOT
- ANI 7FH ;ELSE WRITE CHAR TO MODEM
- CALL WACM
- XRA A ;CLEAR OUTPUT CHAR BUFFER
- STA OUTCH
- LINK5: JMP LINK1 ;LOOP
-
- PCC: CPI 'X'-40H ;JUMP IF NOT CONTROL-X
- JNZ PCC1
- POP H ;CLEAR STACK AND EXIT
- JMP WEOLC
- PCC1: CPI 'O'-40H ;JUMP IF NOT CTRL-O
- JNZ PCC2
- MVI A,1 ;ENABLE OBJECT FILE LOADER
- STA OFLSW
- STC
- RET
- PCC2: CPI 'N'-40H ;JUMP IF NOT CTRL-N
- JNZ PCC3
- XRA A ;DISABLE OBJECT FILE LOADER
- STA OFLSW
- STC
- RET
- PCC3: CPI 'R'-40H ;JUMP IF NOT CTRL-R
- JNZ PCC4
- MVI A,1 ;ENABLE TEXT FILE LOADER
- STA TFLSW
- STC
- RET
- PCC4: CPI 'Q'-40H ;JUMP IF NOT CTRL-Q
- JNZ PCC5
- XRA A ;DISABLE TEXT FILE LOADER
- STA TFLSW
- LHLD TFLLWA ;WRITE MEMORY BUFFER TO TAPE
- DCX H
- XCHG
- LHLD TFLFWA
- CALL WRITE1
- STC
- RET
- PCC5: CPI 'S'-40H ;JUMP IF NOT CTRL-S
- JNZ PCC6
- JMP TFS ;SEND TEXT FILE (FROM TAPE)
- PCC6: STC ;FESS UP THAT WE DON'T KNOW BOUT THIS ONE
- CMC
- RET
-
- TFL: ORA A ;IGNORE NULLS
- RZ
- PUSH H
- LHLD TFLLWA
- MOV M,A
- INX H
- SHLD TFLLWA
- POP H
- RET
-
- TFS: LXI H,TBUF ;READ NEXT RECORD
- LXI B,NBUF
- CALL CTRR
- MOV A,D
- STA CTPC
- LXI H,TBUF
- TFS1: MOV A,D ;EXIT WHEN COUNT=0
- ORA E
- JZ TFS3
- MOV A,M ;FETCH NEXT CHARACTER
- INX H
- CPI 'Z'-40H ;EXIT IF CNTRL-Z
- JZ TFS4
- ORA A
- JZ TFS2
- CPI LF ;DO NOT SEND LINE FEEDS
- JZ TFS2
- CALL WACM ;WRITE CHAR TO MODEM
- CALL WACC ;WRITE CHAR TO CONSOLE
- CPI CR ;JUMP IF NOT CR
- JNZ TFS2
- CALL RACM ;AWAIT LINE FEED
- CPI LF
- JNZ $-5
- CALL WACC ;ECHO LINE FEED TO CONSOLE
- TFS2: CALL CRDAC ;CHECK FOR CONSOLE BREAKIN
- JNC $+11 ;JUMP IF NOT PRESENT
- CALL RACC ;READ CHARACTER
- CPI 'T'-40H ;EXIT IF CTRL-T
- JZ TFS4
- DCX D ;DECREMENT COUNT AND LOOP
- JMP TFS1
- TFS3: LDA CTPC ;FETCH PAGE COUNT
- CPI 4 ;LOOP IF NOT SHORT RECORD
- JNC TFS
- TFS4: CALL WEOLC
- STC
- RET
-
- ;; SOLO - RM80 SOLO COMMAND
-
- SOLO: SHLD OFLOS
- RET
-
- ;;; GENERAL PURPOSE UTILITIES
- ;
- ; LAWRENCE E. HUGHES III
- ; 8080 SOFTWARE DEVELOPMENT CENTER
- ; 1506 MYRICK ROAD
- ; TALLAHASSEE, FLORIDA 32303
-
- ;; MOVEUP - MOVE BLOCK OF MEMORY TOWARDS ZERO
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF SOURCE
- ; BC........FWA OF DEST
- ; DE........NUMBER OF BYTES TO MOVE
-
- MOVEUP: MOV A,D
- ORA E
- RZ
- MOV A,M
- INX H
- STAX B
- INX B
- DCX D
- JMP MOVEUP
-
- ;; MOVEDN - MOVE BLOCK OF MEMORY TOWARDS FFFF
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF SOURCE
- ; BC........FWA OF DEST
- ; DE........NUMBER OF BYTES TO MOVE
-
- MOVEDN: DAD D
- MOV A,C
- ADD E
- MOV C,A
- MOV A,B
- ADC D
- MOV B,A
- MOVEDN1: MOV A,D
- ORA E
- RZ
- DCX H
- MOV A,M
- DCX B
- STAX B
- DCX D
- JMP MOVEDN1
-
- ;; PERR - PRINT 'ERROR'
-
- PERR: LXI H,PERRS1
- JMP WASC
-
- PERRS1: DB 'ERROR',CR,LF,0
-
- ;; DIFF - DE = DE - HL
-
- DIFF: MOV A,E
- SUB L
- MOV E,A
- MOV A,D
- SBB H
- MOV D,A
- RET
-
- ;; GFNC - GET FILE NAME FROM CONSOLE
-
- GFNC: PUSH H
- PUSH D
- CALL WEOLC
- LXI H,GFNS1 ;PRINT 'FILENAME?'
- CALL WASC
- LXI H,IBUF ;READ RESPONSE INTO IBUF
- CALL RASC
- LXI D,IBUF ;DECODE FILE NAME INTO NBUF
- LXI H,NBUF
- CALL DFN
- POP D
- POP H
- RET
-
- GFNS1: DB 'FILENAME? ',0
-
- ;; DFN - DECODE FILE NAME (CP/M FORMAT)
- ;
- ; ENTRY CONDITIONS
- ; DE........FWA OF STRING TO DECODE
- ; HL........FWA OF BUFFER TO ACCEPT DECODED FILENAME
- ;
- ; EXIT CONDITIONS
- ; C-FLAG....SET IFF ERRORS OCCURRED (FIELD TOO LONG)
-
- DFN: MVI C,9 ;DECODE NAME FIELD
- DFN1: LDAX D ;FETCH NEXT BYTE FROM STRING
- INX D
- CPI 61H ;IF LC, CONVERT TO UC
- JC $+5
- SUI 20H
- CPI CR ;JUMP IF END OF STRING
- JZ DFN2
- CPI ' ' ;JUMP IF END OF FIELD
- JZ DFN2
- CPI '.' ;JUMP IF END OF NAME
- JZ DFN2
- DCR C ;EXIT IF NAME TOO LONG
- JZ DFNX
- MOV M,A ;STORE BYTE IN NAME FIELD OF BUFFER
- INX H
- JMP DFN1 ;LOOP
- DFN2: DCR C ;BLANK FILL REST OF NAME FIELD OF BUFFER
- JZ DFN3
- MVI M,' '
- INX H
- JMP DFN2
- DFN3: MVI C,4
- CPI '.' ;JUMP IF NO TYPE FIELD IN STRING
- JNZ DFN5
- DFN4: LDAX D ;FETCH NEXT BYTE FROM STRING
- INX D
- CPI 61H ;IF LC, CONVERT TO UC
- JC $+5
- SUI 20H
- CPI CR ;JUMP IF END OF STRING
- JZ DFN5
- CPI ' ' ;JUMP IF END OF FIELD
- JZ DFN5
- DCR C ;EXIT IF TYPE TOO LONG
- JZ DFNX
- MOV M,A ;STORE BYTE IN TYPE FIELD OF BUFFER
- INX H
- JMP DFN4 ;LOOP
- DFN5: DCR C ;BLANK FILL REST OF TYPE FIELD OF BUFFER
- JZ DFN6
- MVI M,' '
- INX H
- JMP DFN5
- DFN6: STC ;NORMAL EXIT
- CMC
- RET
- DFNX: STC ;ERROR EXIT
- RET
-
- ;; OFL - INTEL HEX OBJECT FILE LOADER (FINITE STATE MACHINE)
- ;
- ; ENTRY CONDITIONS
- ; A.........OBJECT FILE BYTE
- ; OFLST.....STATE COUNTER (INIT BY USER TO ZERO)
- ; OFLLA.....LOAD ADDRESS
- ; OFLBC.....BYTE COUNT
- ; OFLCS.....CHECKSUM
- ; OFLCE.....CHECKSUM ERROR - INIT BY USER TO ZERO
- ; SET NON-ZERO IF ERROR OCCURS, MUST BE
- ; RE-CLEARED TO ZERO BY USER
-
- OFL: PUSH PSW
- LDA OFLST ;JUMP IF STATE >= 1
- CPI 1
- JNC OFL1
- POP PSW
- CPI ':' ;IGNORE ALL CHARS UNTIL COLON FOUND
- RNZ
- MVI A,1 ;ADVANCE TO STATE 1
- STA OFLST
- XRA A ;CLEAR CHECKSUM
- STA OFLCS
- RET
-
- OFL1: CPI 2 ;JUMP IF STATE >= 2
- JNC OFL2
- INR A
- STA OFLST
- CALL OFLCB ;CLEAR BYTE BUFFER
- POP PSW
- JMP OFLAD ;ACCUM. 1ST DIGIT OF BYTE COUNT
-
- OFL2: CPI 3 ;JUMP IF STATE >= 3
- JNC OFL3
- INR A
- STA OFLST
- POP PSW
- CALL OFLAD ;ACCUM. 2ND DIGIT OF BYTE COUNT
- STA OFLBC ;SAVE RESULT AS BYTE COUNT
- JMP OFLUC ;ADD RESULT INTO CHECKSUM
-
- OFL3: CPI 4 ;JUMP IF STATE >= 4
- JNC OFL4
- INR A
- STA OFLST
- CALL OFLCB ;CLEAR BYTE BUFFER
- POP PSW
- JMP OFLAD ;ACCUM. 1ST DIGIT OF HI ADDR
-
- OFL4: CPI 5 ;JUMP IF STATE >= 5
- JNC OFL5
- INR A
- STA OFLST
- POP PSW
- CALL OFLAD ;ACCUM 2ND DIGIT OF HI ADDR
- STA OFLLA+1 ;SAVE HI BYTE OF LOAD ADDRESS
- JMP OFLUC ;ADD RESULT INTO CHECKSUM
-
- OFL5: CPI 6 ;JUMP IF STATE >= 6
- JNC OFL6
- INR A
- STA OFLST
- CALL OFLCB ;CLEAR BYTE BUFFER
- POP PSW ;ACCUM. 1ST DIGIT OF LO ADDR
- JMP OFLAD
-
- OFL6: CPI 7 ;JUMP IF STATE >= 7
- JNC OFL7
- INR A
- STA OFLST
- POP PSW
- CALL OFLAD ;ACCUM. 2ND DIGIT OF LO ADDR
- STA OFLLA ;SAVE LO BYTE OF LOAD ADDRESS
- PUSH H
- PUSH D
- LHLD OFLLA ;ADD IN OFFSET
- XCHG
- LHLD OFLOS
- DAD D
- SHLD OFLLA
- POP D
- POP H
- JMP OFLUC ;ADD RESULT INTO CHECKSUM
-
- OFL7: CPI 9 ;JUMP IF STATE >= 9
- JNC OFL8
- INR A
- STA OFLST
- POP PSW ;IGNORE NEXT DIGIT OF REC TYPE
- RET
-
- OFL8: CPI 10 ;JUMP IF STATE >= 10
- JNC OFL10
- INR A
- STA OFLST
- LDA OFLBC ;EXIT IF BYTE COUNT = 0
- ORA A
- JZ OFL9
- CALL OFLCB ;CLEAR BYTE BUFFER
- POP PSW
- JMP OFLAD ;ACCUM. 1ST DIGIT OF NEXT DATA BYTE
-
- OFL9: MVI A,11 ;SET STATE TO 12 (ALL DATA BYTES READ)
- STA OFLST
- JMP OFL11
-
- OFL10: CPI 11 ;JUMP IF STATE >= 11
- JNC OFL11
- DCR A
- STA OFLST
- POP PSW
- CALL OFLAD ;ACCUM. 2ND DIGIT OF NEXT DATA BYTE
- PUSH H ;LOAD BYTE AT LOAD ADDRESS
- LHLD OFLLA
- MOV M,A
- INX H ;INCREMENT LOAD ADDRESS
- SHLD OFLLA
- POP H
- CALL OFLUC ;ADD BYTE INTO CHECKSUM
- LDA OFLBC ;DECREMENT BYTE COUNT
- DCR A
- STA OFLBC
- RET
-
- OFL11: CPI 12 ;JUMP IF STATE >= 12
- JNC OFL12
- INR A
- STA OFLST
- CALL OFLCB ;CLEAR BYTE BUFFER
- POP PSW
- JMP OFLAD ;ACCUM. 1ST DIGIT OF CHECKSUM
-
- OFL12: POP PSW
- CALL OFLAD ;ACCUM. 2ND DIGIT OF CHECKSUM
- CALL OFLUC ;ADD INTO NEW CHECKSUM (SHOULD YIELD ZERO)
- STA OFLCE ;STORE RESULT AS CHECKSUM ERROR FLAG
- XRA A ;RETURN TO STATE ZERO
- STA OFLST
- RET
-
- ;; OFLCB - CLEAR BYTE BUFFER
-
- OFLCB: XRA A
- STA OFLBB
- RET
-
- ;; OFLAD - ACCUMULATE (HEX) DIGIT
-
- OFLAD: SUI '0' ;SUBTRACT ASCII BIAS
- CPI 10 ;JUMP IF 0-9
- JC $+5
- SUI 7 ;ADJUST A-F
- PUSH B
- MOV B,A
- LDA OFLBB ;FETCH BYTE BUFFER
- ADD A ;MULTIPLY BY 16
- ADD A
- ADD A
- ADD A
- ADD B ;ADD IN NEW DIGIT
- STA OFLBB ;REPLACE RESULT
- POP B
- RET
-
- ; OFLUC - UPDATE CHECKSUM
-
- OFLUC: PUSH H
- LXI H,OFLCS ;POINT TO CHECKSUM
- ADD M ;ADD IN NEW BYTE
- MOV M,A
- POP H
- RET
-
- ;; DMP - DUMP MEMORY IN HEX AND ASCII TO CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF BLOCK TO DUMP
- ; DE........NUMBER OF BYTES TO DUMP
- ; DMPAD.....ADDR PRINTED AT START OF EACH LINE,
- ; INIT BY USER, INCREMENTED BY DMP
-
- DMP: MOV A,D ;EXIT VIA WEOLC IF DE=0
- ORA E
- JZ WEOLC
- CALL CRDAC ;CHECK FOR CONSOLE RDA
- JNC DMP0 ;IF NO RDA, JUMP
- CALL RACC ;ELSE DISCARD CHAR TYPED
- JMP WEOLC ;AND EXIT VIA WEOLC
- DMP0: CALL WEOLC ;START NEW LINE
- LDA DMPAD+1 ;WRITE DUMP ADDR IN HEX
- CALL WHBC
- LDA DMPAD
- CALL WHBC
- PUSH H ;SAVE FWA
- PUSH D ;SAVE BYTE COUNT
- MVI C,16 ;NUMBER OF BYTES PER LINE
- DMP1: MOV A,D ;JUMP IF DONE
- ORA E
- JZ DMP2
- MVI A,' ' ;PRINT 1 BLANK
- CALL WACC
- MOV A,M ;FETCH NEXT BYTE
- INX H
- CALL WHBC ;WRITE TO CONSOLE IN HEX
- PUSH H ;DMPAD = DMPAD + 1
- LHLD DMPAD
- INX H
- SHLD DMPAD
- POP H
- DCX D ;DECREMENT COUNT
- DCR C ;CONTINUE UNTIL 16 BYTES DUMPED
- JNZ DMP1
- JMP DMP3 ;GO DUMP BYTES IN ASCII
- DMP2: INR C ;EXIT WHEN C=0
- DCR C
- JZ DMP3
- MVI A,' ' ;PRINT 3 SPACES
- CALL WACC
- CALL WACC
- CALL WACC
- JMP DMP2+1 ;CONTINUE
- DMP3: POP D ;RESTORE BYTE COUNT
- POP H ;RESTORE POINTER
- MVI A,' ' ;PRINT 2 SPACES
- CALL WACC
- CALL WACC
- MVI C,16 ;NUMBER OF BYTES PER LINE
- DMP4: MOV A,D ;EXIT VIA WEOLC IF DONE
- ORA E
- JZ WEOLC
- MOV A,M ;FETCH NEXT BYTE
- INX H
- ANI 7FH ;DISCARD PARITY BIT
- CPI 20H ;SUBSTITUTE PERIOD FOR CTRL CHARS
- JNC $+5
- MVI A,'.'
- CPI 7FH
- JC $+5
- MVI A,'.'
- CALL WACC ;PRINT BYTE IN ASCII
- DCX D ;DECREMENT COUNT
- DCR C ;CONTINUE UNTIL C = 0
- JNZ DMP4
- JMP DMP ;PROCEED TO NEXT LINE
-
- ;; WHBC - WRITE HEX BYTE TO CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; A.........BYTE TO WRITE IN HEX
-
- WHBC: PUSH PSW ;PRINT FIRST DIGIT
- RRC
- RRC
- RRC
- RRC
- CALL WHDC
- POP PSW ;PRINT SECOND DIGIT
- PUSH PSW
- CALL WHDC
- POP PSW
- RET
-
- ;; WHDC - WRITE HEX DIGIT TO CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; A.........BITS 3-0 CONTAIN BINARY VALUE OF DIGIT
-
- WHDC: ANI 0FH ;DISCARD TOP 4 BITS
- CPI 10 ;ADJUST 10-15
- JC $+5
- ADI 7
- ADI '0' ;CONVERT TO ASCII
- JMP WACC ;GO PRINT DIGIT AND RETURN
-
- ;; WEOLC - WRITE END OF LINE TO CONSOLE
-
- WEOLC: PUSH PSW
- MVI A,CR
- CALL WACC
- MVI A,LF
- CALL WACC
- POP PSW
- RET
-
- ;; WASC - WRITE ASCII STRING TO CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF STRING, TERMINATED BY ZERO BYTE
-
- WASC: MOV A,M ;FETCH NEXT BYTE IN STRING
- INX H
- ORA A ;RETURN IF END-OF-STRING
- RZ
- CALL WACC ;PRINT CHAR
- JMP WASC
-
- ;; WASCX - WRITE ASCII STRING TO CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF STRING
- ; B.........NUMBER OF CHARS TO WRITE
-
- WASCX: INR B
- DCR B
- RZ
- MOV A,M
- INX H
- CALL WACC
- JMP WASCX+1
-
- ;; RASC - READ ASCII STRING FROM CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF 128 BYTE BUFFER TO READ INTO
- ;
- ; EXIT CONDITIONS
- ; HL........POINTS TO LAST CHAR STORED (CR)
- ; B.........NUMBER OF BYTES STORED
-
- RASC: PUSH H ;SAVE BUFFER POINTER
- MVI B,0 ;COUNT = 0
- RASC1: CALL RACC ;READ NEXT CHAR FROM CONSOLE
- CPI 'U'-40H ;JUMP IF NOT CTRL-U
- JNZ RASC2
- CALL WEOLC ;ABORT OLD LINE
- POP H ;RESTORE BUFFER POINTER
- JMP RASC ;START OVER
- RASC2: CPI BS
- JZ RASC25
- CPI DEL
- JNZ RASC3
- RASC25: INR B
- DCR B
- JZ RASC1
- DCX H ;DELETE CHAR
- DCR B
- MVI A,BS
- CALL WACC
- JMP RASC1
- RASC3: MOV M,A ;STORE CHAR IN BUFFER
- INR B ;INCREMENT COUNT
- MOV A,B ;JUMP IF STILL ROOM IN BUFFER
- ORA A
- JP RASC4
- MVI M,CR ;FORCE A CR INTO LAST BYTE OF BUFFER
- POP H ;RESTORE BUFFER POINTER
- RET
- RASC4: MOV A,M ;FETCH CHAR BACK INTO A
- CPI CR ;EXIT IF CHAR = CR
- JZ RASC5
- INX H ;NOW INCREMENT BUFFER POINTER
- CALL WACC ;ECHO CHAR TO CONSOLE AND LOOP
- JMP RASC1
- RASC5: INX SP ;CLEAR TOP OF STACK
- INX SP
- JMP WEOLC
-
- ;; DHS - DECODE HEX STRING (TERM. BY BLANK OR CR)
- ;
- ; ENTRY CONDITIONS
- ; DE........FWA OF STRING TO DECODE
- ;
- ; EXIT CONDITIONS
- ; HL........VALUE OF HEX STRING
- ; A.........NUMBER OF LEGAL DIGITS FOUND
- ; DE........POINTS TO LAST CHAR SCANNED
- ; C-FLAG....SET IFF ERRORS
-
- DHS: LXI H,0 ;HL = 0
- PUSH B
- MVI B,0 ;CLEAR 'DIGITS FOUND' COUNT
- DHS1: LDAX D ;SKIP LEADING BLANKS, IF ANY
- CPI CR ;CHECK FOR END-OF-LINE
- JZ DHS5
- INX D
- CPI ' '
- JZ DHS1
- DHS2: DAD H ;HL = HL * 16
- DAD H
- DAD H
- DAD H
- CPI 61H ;IF LC, CONVERT TO UC
- JC $+5
- SUI 20H
- SUI '0' ;CONVERT TO BINARY
- JC DHSX
- CPI 10 ;JUMP IF DIGIT < 10
- JC $+5
- SUI 7 ;ADJUST FOR A-F
- CPI 16
- JNC DHSX
- ADD L ;HL = HL + NEW DIGIT
- MOV L,A
- JNC $+4
- INR H
- INR B ;INCREMENT 'DIGITS FOUND' COUNT
- LDAX D
- CPI CR
- JZ DHS5
- CPI ' '
- JZ DHS5
- INX D
- JMP DHS2
- DHS5: LDAX D ;NORMAL EXIT
- MOV A,B
- POP B
- STC
- CMC
- RET
- DHSX: DCX D ;ERROR EXIT
- LDAX D
- POP B
- STC
- RET
-
- ;;; CONSOLE DRIVER (IMSAI SIO-2 PORT A)
- ;
- ; LAWRENCE E. HUGHES III
- ; 8080 SOFTWARE DEVELOPMENT CENTER
- ; 1506 MYRICK ROAD
- ; TALLAHASSEE, FLORIDA 32303
-
- CONDAT EQU 12H ;DATA PORT
- CONSTA EQU 13H ;STATUS PORT
- CONRDA EQU 02H ;READ-DATA-AVAILABLE MASK
- CONTBE EQU 01H ;TRANSMIT-BUFFER-EMPTY MASK
-
- ;; RACC - READ ASCII CHAR FROM CONSOLE
- ;
- ; EXIT CONDITIONS
- ; A.........7-BIT ASCII CHARACTER (D7=0)
-
- RACC: CALL CRDAC ;LOOP UNTIL CONSOLE RDA OCCURS
- JNC $-3
- IN CONDAT ;READ DATA BYTE
- ANI 7FH ;CLEAR TOP BIT
- RET
-
- ;; CRDAC - CHECK FOR RDA ON CONSOLE
- ;
- ; EXIT CONDITIONS
- ; C-FLAG....SET IFF RDA OCCURED
-
- CRDAC: IN CONSTA ;READ STATUS PORT
- ANI CONRDA ;MASK OFF RDA FLAG
- JZ $+5 ;JUMP IF NOT PRESENT
- STC ;ELSE SET CARRY AND RETURN
- RET
- STC ;CLEAR CARRY AND RETURN
- CMC
- RET
-
- ;; WACC - WRITE ASCII CHARACTER TO CONSOLE
- ;
- ; ENTRY CONDITIONS
- ; A.........ASCII CHARACTER TO WRITE
-
- WACC: PUSH PSW ;SAVE CHAR
- CALL CTBEC ;LOOP UNTIL CONSOLE TBE OCCURS
- JNC $-3
- POP PSW ;RESTORE CHAR
- OUT CONDAT ;WRITE CHAR AND RETURN
- RET
-
- ;; CTBEC - CHECK FOR TBE ON CONSOLE
- ;
- ; EXIT CONDITIONS
- ; C-FLAG...SET IF TBE OCCURRED
-
- CTBEC: IN CONSTA ;READ STATUS PORT
- ANI CONTBE ;MASK OFF TBE FLAG
- JZ $+5 ;JUMP IF NOT PRESENT
- STC ;ELSE SET CARRY AND RETURN
- RET
- STC ;CLEAR CARRY AND RETURN
- CMC
- RET
-
- ;; INITC - INITIALIZE CONSOLE PORT
-
- INITC: XRA A ;CLEAR USART
- OUT CONSTA
- OUT CONSTA
- OUT CONSTA
- MVI A,40H ;DO AN INTERNAL RESET
- OUT CONSTA
- MVI A,6EH ;SELECT ASYNC, ETC
- OUT CONSTA
- MVI A,27H ;ISSUE CTS, DSR, ENABLE RX AND TX
- OUT CONSTA
- IN CONDAT ;CLEAR READ BUFFERS IN CHIP
- IN CONDAT
- RET
-
- ;;; MODEM DRIVER (IMSAI SIO-2 PORT B)
- ;
- ; LAWRENCE E. HUGHES III
- ; 8080 SOFTWARE DEVELOPMENT CENTER
- ; 1506 MYRICK ROAD
- ; TALLAHASSEE, FLORIDA 32303
-
- MODDAT EQU 14H ;DATA PORT
- MODSTA EQU 15H ;STATUS PORT
- MODRDA EQU 02H ;READ-DATA AVAILABLE MASK
- MODTBE EQU 01H ;TRANSMIT-BUFFER-EMPTY MASK
-
- ;; RACM - READ ASCII CHAR FROM MODEM
- ;
- ; EXIT CONDITIONS
- ; A.........7-BIT ASCII CHARACTER (D7 = 0)
-
- RACM: CALL CRDAM ;LOOP UNTIL MODEM RDA OCCURS
- JNC $-3
- IN MODDAT ;READ DATA BYTE
- ANI 7FH ;CLEAR TOP BIT
- RET
-
- ;; CRDAM - CHECK FOR RDA ON MODEM
- ;
- ; EXIT CONDITIONS
- ; C-FLAG....SET IFF RDA OCCURRED
-
- CRDAM: IN MODSTA ;READ STATUS PORT
- ANI MODRDA ;MASK IFF RDA FLAG
- JZ $+5 ;JUMP IF NOT PRESENT
- STC ;ELSE SET CARRY FLAG AND RETURN
- RET
- STC ;CLEAR CARRY AND RETURN
- CMC
- RET
-
- ;; WACM - WRITE ASCII CHARACTER TO MODEM
- ;
- ; ENTRY CONDITIONS
- ; A.........ASCII CHAR TO WRITE
-
- WACM: PUSH PSW ;SAVE CHAR
- CALL CTBEM ;LOOP UNTIL MODEM TBE OCCURS
- JNC $-3
- POP PSW ;RESTORE CHAR
- OUT MODDAT ;WRITE CHAR AND RETURN
- RET
-
- ;; CTBEM - CHECK FOR TBE ON MODEM
- ;
- ; EXIT CONDITIONS
- ; C-FLAG....SET IFF TBE OCCURRED
-
- CTBEM: IN MODSTA ;READ STATUS PORT
- ANI MODTBE ;MASK OFF TBE FLAG
- JZ $+5 ;JUMP IF NOT PRESENT
- STC ;ELSE SET CARRY FLAG AND RETURN
- RET
- STC ;CLEAR CARRY FLAG AND RETURN
- CMC
- RET
-
- ;; INITM - INITIALIZE MODEM PORT
-
- INITM: XRA A ;CLEAR USART
- OUT MODSTA
- OUT MODSTA
- OUT MODSTA
- MVI A,40H ;DO AN INTERNAL RESET
- OUT MODSTA
- MVI A,6EH ;SELECT ASYNC, ETC.
- OUT MODSTA
- MVI A,27H ;ISSUE RTS, DSR, ENABLE RX AND TX
- OUT MODSTA
- IN MODDAT ;CLEAR READ BUFFERS IN CHIP
- IN MODDAT
- RET
-
- ;;; CASSETTE TAPE DRIVER (MODIFIED TARBELL INTERFACE)
- ;
- ; LAWRENCE E. HUGHES III
- ; 8080 SOFTWARE DEVELOPMENT CENTER
- ; 1506 MYRICK ROAD
- ; TALLAHASSEE, FLORIDA 32303
-
- CASDAT EQU 6FH ;DATA PORT
- CASSTA EQU 6EH ;STATUS PORT
- CASRDA EQU 10H ;READ-DATA-AVAILABLE MASK (INVERTED)
- CASTBE EQU 20H ;TRANSMIT-BUFFER-EMPTY MASK (INVERTED)
- CASEHM EQU 10H ;ENTER HUNT MODE COMMAND
- CASCRC EQU 8005H ;CRC POLYNOMIAL (CRC-16)
-
- ;; INITT - INITIALIZE TAPE INTERFACE
-
- INITT: XRA A
- OUT CASSTA
- MVI A,1 ;DEFAULT TO TAPE UNIT 1
- STA TUNIT
- RET
-
- ;; CTRR - READ PHYSICAL RECORD FROM CASSETTE TAPE
- ;
- ; ENTRY CONDITIONS
- ; HL........ADDR OF BUFFER TO ACCEPT DATA
- ; BC........ADDR OF 11 BYTE BUFFER TO ACCEPT FILENAME
- ; TUNIT.....UNIT NO. SPECIFIER (1 OR 2)
- ;
- ; EXIT CONDITIONS
- ; DE........PHYSICAL RECORD SIZE (BYTES)
- ; PRN.......PHYSICAL RECORD NUMBER
- ; C-FLAG....SET MEANS READ ERROR OCCURRED
-
- CTRR: LDA TUNIT ;GET UNIT NUMBER
- ORI CASEHM ;OR IN HUNT MODE BIT
- OUT CASSTA ;TURN ON SELECTED UNIT'S MOTOR
- CALL CTRB ;READ BYTE FROM TABLE
- JC RM80 ;EXIT ON CONSOLE BREAKIN
- CPI SOH ;LOOP IF NOT SOH (NOISE)
- JNZ CTRR
- CTRR1: PUSH H ;SAVE BUFFER ADDR
- LXI H,0 ;CLEAR CRC
- SHLD CRC
- MOV H,B ;READ FILENAME INTO BUFFER
- MOV L,C
- LXI D,11
- CALL CTRS
- CALL CTRB ;READ PHYSICAL RECORD NUMBER INTO PRN
- STA PRN
- CALL CTRB ;READ PHYSICAL RECORD SIZE INTO DE
- MOV D,A
- CALL CTRB
- MOV E,A
- CALL CTRB ;ERROR EXIT IF NEXT BYTE NOT STX
- CPI STX
- JNZ CTRR2
- POP H ;RESTORE DATA BUFFER ADDR
- PUSH D ;SAVE PHYS REC SIZE
- CALL CTRS ;READ DATA BYTES
- CALL CTRB ;ERROR EXIT IF NEXT BYTE NOT ETX
- CPI ETX
- JNZ CTRR2
- CALL CTRB ;READ TAPE CRC
- CALL CTRB
- LHLD CRC ;OUR CRC SHOULD NOW BE ZERO
- MOV A,H
- ORA L
- JNZ CTRR2
- POP D ;RESTORE PHYS REC SIZE
- XRA A ;TURN OFF MOTOR
- OUT CASSTA
- STC ;CLEAR ERROR FLAG AND RETURN
- CMC
- RET
- CTRR2: POP D ;RESTORE PHYS REC SIZE
- XRA A ;TURN OFF MOTOR
- OUT CASSTA
- STC ;SET ERROR FLAG AND RETURN
- RET
-
- ;; CTRS - READ STRING FROM CASSETTE TAPE
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA TO READ INTO
- ; DE........NUMBER OF BYTES TO READ
-
- CTRS: MOV A,D ;RETURN IF COUNT=0
- ORA E
- RZ
- CALL CTRB ;READ NEXT BYTE
- JC RM80 ;EXIT ON CONSOLE BREAKIN
- MOV M,A ;STORE IN MEMORY
- INX H
- DCX D ;DECREMENT COUNT AND LOOP
- JMP CTRS
-
- ;; CTRB - READ BYTE FROM CASSETTE TAPE
- ;
- ; EXIT CONDITIONS
- ; C-FLAG....SET IFF CONSOLE BREAKIN
-
- CTRB: CALL CRDAC ;EXIT ON CONSOLE BREAKIN
- RC
- IN CASSTA ;CHECK FOR RDA (INVERTED)
- ANI CASRDA
- JNZ CTRB
- IN CASDAT ;READ BYTE
- CMA ;DISPLAY ON LIGHTS
- OUT 0FFH
- CMA
- JMP UCRC ;UPDATE CRC AND RETURN
-
- ;; CTWR - WRITE PHYSICAL RECORD TO CASSETTE TAPE
- ;
- ; ENTRY CONDITIONS
- ; TUNIT.....UNIT NUMBER TO WRITE TO
- ; HL........ADDR OF BUFFER TO BE WRITTEN
- ; DE........NUMBER OF BYTES TO WRITE (PHYS REC SIZE)
- ; PRN.......PHYSICAL RECORD NUMBER (INIT TO ZERO BY USER,
- ; INCREMENTED BY CTWR AUTOMATICALLY)
- ; BC........ADDR OF BUFFER CONTAINING FILENAME
-
- CTWR: PUSH H ;SAVE DATA BUFFER ADDR
- PUSH D ;SAVE PHYS REC SIZE
- PUSH B ;SAVE FILENAME BUFFER ADDR
- LDA TUNIT ;TURN ON MOTOR
- OUT CASSTA
- MVI B,15 ;WAIT 1.5 SECONDS
- CALL WTS
- MVI A,3CH ;WRITE START BYTE
- CALL CTWB
- MVI A,0E6H ;WRITE SYNC BYTE
- CALL CTWB
- MVI A,SOH ;WRITE SOH
- CALL CTWB
- LXI H,0 ;CLEAR CRC
- SHLD CRC
- POP H ;RESTORE FILENAME BUFFER ADDR
- LXI D,11 ;WRITE FILENAME TO TAPE
- CALL CTWS
- LDA PRN ;WRITE PHYSICAL RECORD NUMBER
- CALL CTWB
- INR A ;INCREMENT PRN
- STA PRN
- POP D ;RESTORE PHYS REC SIZE
- MOV A,D ;WRITE PHYS REC SIZE
- CALL CTWB
- MOV A,E
- CALL CTWB
- MVI A,STX ;WRITE STX
- CALL CTWB
- POP H ;RESTORE BUFFER POINTER
- PUSH D ;SAVE PHYS REC SIZE
- CALL CTWS ;WRITE DATA BYTES
- MVI A,ETX ;WRITE ETX
- CALL CTWB
- PUSH H ;SAVE THE UPDATED BUFFER POINTER
- LHLD CRC ;WRITE CRC WE'VE BEEN CREATING
- MOV A,H
- CALL CTWB
- MOV A,L
- CALL CTWB
- POP H ;RESTORE THE UPDATED BUFFER POINTER
- XRA A ;SEND A NULL
- CALL CTWB
- POP D ;RESTORE PHYS REC SIZE
- XRA A ;TURN OFF MOTOR
- OUT CASSTA
- MVI B,5 ;WAIT 0.5 SECONDS AND RETURN
- JMP WTS
-
- ;; CTWS - WRITE STRING TO CASSETTE TAPE
- ;
- ; ENTRY CONDITIONS
- ; HL........FWA OF STRING TO WRITE
- ; DE........NUMBER OF BYTES TO WRITE
-
- CTWS: MOV A,D ;RETURN IF COUNT = 0
- ORA E
- RZ
- MOV A,M ;FETCH NEXT BYTE
- INX H
- CALL CTWB ;WRITE IT
- DCX D ;DECREMENT COUNT AND LOOP
- JMP CTWS
-
- ;; CTWB - WRITE BYTE TO CASSETTE TAPE
- ;
- ; ENTRY CONDITIONS
- ; A.........BYTE TO WRITE
-
- CTWB: PUSH PSW
- IN CASSTA ;AWAIT TBE (INVERTED)
- ANI CASTBE
- JNZ $-4
- POP PSW
- OUT CASDAT ;WRITE BYTE
- CMA ;DISPLAY ON LIGHTS, FALL THRU TO UCRC
- OUT 0FFH
- CMA
- JMP UCRC
-
- ;; CTPH - PRINT HEADER INFO
-
- CTPH: PUSH H
- PUSH B
- PUSH PSW
- LXI H,CTPHS1 ;PRINT 'NAME = '
- CALL WASC
- LXI H,NBUF ;PRINT NAME
- MVI B,8
- CALL WASCX
- LXI H,CTPHS2 ;PRINT ' TYPE = '
- CALL WASC
- LXI H,NBUF+8 ;PRINT TYPE
- MVI B,3
- CALL WASCX
- LXI H,CTPHS3 ;PRINT ' SIZE = '
- CALL WASC
- MOV A,D ;PRINT SIZE (IN HEX)
- CALL WHBC
- MOV A,E
- CALL WHBC
- LXI H,CTPHS4 ;PRINT ' PRN = '
- CALL WASC
- LDA PRN ;PRINT PRN (IN HEX)
- CALL WHBC
- LXI H,CTPHS5 ;PRINT ' CRC = '
- CALL WASC
- LXI H,CTPHS6 ;PRINT CRC STATUS
- POP PSW
- PUSH PSW
- JNC $+6
- LXI H,CTPHS7
- CALL WASC
- CALL WEOLC
- POP PSW
- POP B
- POP H
- RET
-
- CTPHS1: DB 'NAME = ',0
- CTPHS2: DB ' TYPE = ',0
- CTPHS3: DB ' SIZE = ',0
- CTPHS4: DB ' PRN = ',0
- CTPHS5: DB ' CRC = ',0
- CTPHS6: DB 'GOOD',0
- CTPHS7: DB 'BAD',0
-
- ;; UCRC - UPDATE CRC
- ;
- ; ENTRY CONDITIONS
- ; A.........NEW DATA BYTE
- ; CRC.......2 BYTE BUFFER CONTAINING CRC
-
- UCRC: PUSH PSW ;SAVE REGS
- PUSH B
- PUSH D
- PUSH H
- MOV B,A ;SAVE DATA BYTE
- MVI C,8 ;LOOP COUNT
- UCRC1: ANI 80H ;MASK OFF MSB OF DATA BYTE
- LHLD CRC ;FETCH CRC INTO HL
- XRA H ;XOR MSB OF DATA BYTE INTO CRC
- MOV H,A
- DAD H ;LEFT SHIFT CRC 1 BIT
- JNC UCRC2 ;JUMP IF NO CARRY
- MOV A,H ;HL = HL XOR CRC POLYNOMIAL
- XRI CASCRC SHR 8
- MOV H,A
- MOV A,L
- XRI CASCRC AND 0FFH
- MOV L,A
- UCRC2: SHLD CRC ;REPLACE CRC
- DCR C ;DECREMENT LOOP COUNT
- JZ UCRC3 ;EXIT WHEN ENTIRE BYTE PROCESSED
- MOV A,B ;SHIFT DATA BYTE LEFT 1 BIT
- ADD A
- MOV B,A
- JMP UCRC1 ;LOOP
- UCRC3: POP H ;RESTORE REGS AND RETURN
- POP D
- POP B
- POP PSW
- STC
- CMC
- RET
-
- ;; WTS - WAIT TENTHS OF A SECOND
- ;
- ; ENTRY CONDITIONS
- ; B - NUMBER OF TENTHS TO WAIT
-
- WTS: INR B ;EXIT WHEN B=0
- DCR B
- RZ
- PUSH H ;WAIT ONE TENTH SECOND
- LXI H,8330
- WTS1: DCX H
- MOV A,H
- ORA L
- JNZ WTS1
- POP H
- DCR B ;DECREMENT COUNT AND LOOP
- JMP WTS
-
- END
- ERT TO BINARY
- JC DHSX
- CPI 10 ;JUMP IF DIGIT < 10
- JC $+5
- SUI