TITLE 'Z80-ASSEMBLER TO CP/M LINKAGES'
;
; EQUATE TABLE
;
CR EQU 13
LF EQU 10
ENTRY EQU 5 ;FDOS ENTRY
BOOT EQU 0 ;WARM START
SETDMA EQU 26 ;CP/M FUNCTION NUMBER
OPNFIL EQU 15 ;OPEN FILE
CLSFIL EQU 16 ;CLOSE FILE
DELFIL EQU 19 ;DELETE FILE
MAKFIL EQU 22 ;CREATE FILE
RDNR EQU 20 ;READ NEXT RECORD
WRNR EQU 21 ;WRITE NEXT RECORD
PRBUF EQU 9 ;PRINT STRING
DFCB EQU 5CH ;CP/M DEFAULT FCB
DEFBUF EQU 80H ;CP/M DEFAULT I/O ADDR
PASSNO EQU 1B03H ;CURRENT PASS NO.
;
GETCON EQU 0F009H ;MONITOR CONSOLE INPUT
PUTCON EQU 0F00CH ;MONITOR CONSOLE OUTPUT
CTLZ EQU 1AH ;^Z = EOF MARK
;
;
ORG 102H
JP CONIN
JP CONOUT
JP LSTO
JP RDRIN
JP PCHO
JP MEMCHK
JP BOOT
;
ORG 2400H ;PUT ABOVE SYMBOL TABLE
;
SRCFCB DEFB 0 ;FCB STARTS WITH 0
SRCFN DEFM ' ' ;RESERVE 8 CHARS FOR FILE NAME
DEFM 'Z80' ;USE EXTENSION OF Z80
DEFS 21 ;21 BYTES FOR CP/M
SRCPTR DEFS 2 ;FOR CHARACTER POINTER
SRCOPN DEFM 'C' ;DECLARE CLOSED
;
LSTFCB DEFB 0 ;LISTING FILE SETUP
LSTFN DEFM ' '
DEFM 'PRN' ;PRINT FILE
DEFS 21
LSTPTR DEFS 2
LSTOPN DEFM 'C'
;
HEXFCB DEFB 0 ;SAME FOR HEX FILE
HEXFN DEFM ' '
DEFM 'HEX'
DEFS 21
HEXPTR DEFS 2
HEXOPN DEFM 'C'
;
MEMCHK LD A, 0FFH ;MAX MEM = 23FFH
LD B, 23H
RET
;
CONOUT PUSH BC ;NO REGISTERS MAY BE DESTROYED
PUSH DE
PUSH HL
OUT4 LD A,C
CALL PUTCON
;
GENRET POP HL ;GENERAL RETURN FOR ALL SUBR'S
POP DE
POP BC
RET
;
;
OPNOUT PUSH DE ;OPEN (DE) FCB FOR OUTPUT
LD C, DELFIL ;FIRST DELETE CURRENT
CALL ENTRY
POP DE
LD C, MAKFIL ;THEN RE-CREATE
JP ENTRY
;
CONIN PUSH BC ;CONSOLE INP IS ONLY COMMON
PUSH DE ; POINT FOR ALL PASSES SO DO
PUSH HL ; SETUP HERE
;
LD A, (SRCOPN) ;IS SRC OPEN?
CP 'O'
CALL NZ, CPYFCB ;IF NOT, CREATE FCB'S
LD HL, (NXTPAS) ;POINT TO PASS SEQUENCE
LD A, (HL) ;GET NEXT PASS NUMBER
INC HL ;UPDATE POINTER
LD (NXTPAS), HL ;SAVE POINTER
PUSH AF
;
CP 'Q' ;QUIT ?
CALL Z FLUSH ;YES, FLUSH BUFFERS
POP AF
PUSH AF
;
CP '1' ;PASS 1?
JR Z, PASS1
CP '2' ;PASS 2?
JP Z, PASS2
CP '3' ;PASS 3?
JP Z, PASS3
CP '4' ;PASS 4 USES CONSOLE OUTPUT
JR Z, PASS1
INPRET POP AF ;IF NONE OF ABOVE, EXIT
JR GENRET
;
NXTPAS DEFW SEQNO ;SEQUENCE # POINTER
SEQNO DEFM '1423Q' ;DEFAULT SEQUENCE
CPYFCB LD HL, DFCB+9 ;POINT TO FILE EXTENSION
LD DE, SEQNO+2 ;POINT TO PASS 2 FLAG
LD A, 'N' ;IF N, SKIP PASS
CP (HL) ;SKIP IT?
JR NZ DOIT ;NO, DO LISTING
LD (DE), A ;SKIP IT
DOIT INC HL ;POINT TO HEX SWITCH
INC DE ;POINT TO PASS 3 FLAG
CP (HL) ;SKIP IT?
JR NZ COPYIT ;NO, DO HEX FILE
LD (DE), A ;DON'T DO IT
COPYIT LD BC, 8H ;SETUP FOR LDIR
;
LD DE, SRCFN ;DESTINATION
PUSH BC
CALL MOVFCB
;
LD DE, LSTFN
POP BC
PUSH BC
CALL MOVFCB
;
LD DE, HEXFN
POP BC
;
MOVFCB LD HL, DFCB+1 ;FILE NAME STARTS IN POS 1
LDIR
RET
;
PASS1 XOR A ;MAKE SURE OPEN FIRST
LD (SRCFCB+12), A ; EXTENT
LD DE, SRCFCB
LD C, OPNFIL
CALL ENTRY
CP 0FFH ;SUCESSFUL?
JR Z, NOSRC ; NO, LET US KNOW
LD A, 'O' ; DECLARE OPEN
LD (SRCOPN), A
XOR A ;FIRST RECORD IS #0
LD (SRCFCB+32), A
LD HL, SRCBUF+1024
LD (SRCPTR), HL
JR INPRET
;
NOSRC LD DE, NFMSG ;NO FILE MESSAGE
ERROUT LD C, PRBUF ;PRINT STRING FUNCTION
CALL ENTRY
CALL GETCON ;WAIT FOR KEYSTROKE TO EXIT
JP BOOT
;
NFMSG DEFB CR
DEFB LF
DEFM 'NO SOURCE FILE FOUND'
DEFB CR
DEFB LF
DEFM '$'
;
PASS2 LD A, (HEXOPN) ;HEX FILE OPEN FROM PREV?
CP 'O'
CALL Z, FLUSH ;YES, FLUSH AND CLOSE
;
LD DE, LSTFCB ;OPEN LISTING FILE
CALL OPNOUT
CP 0FFH ;SUCESSFUL?
JR Z, DSKERR ;NO, ERROR MSG
LD A, 'O'
LD (LSTOPN),A ;DECLARE OPEN
XOR A ;START WITH RECORD 0
LD (LSTFCB+32), A
LD HL, LSTBUF ;DECLARE EMPTY
LD (LSTPTR), HL
JR PASS1 ;GO OPEN SRC
;
DSKERR LD DE, ERRMSG
JR ERROUT ;GOTO ERROR OUTPUT RTN
;
ERRMSG DEFB CR
DEFB LF
DEFM 'DISK ERROR, ASSEMBLY ABORTED'
DEFB CR
DEFB LF
DEFM '$'
;
PASS3 LD A, (LSTOPN) ;LIST STILL OPEN?
CP 'O'
CALL Z, FLUSH ;YES, FLUSH AND CLOSE
LD DE, HEXFCB
CALL OPNOUT ;OPEN HEX FILE FOR OUTPUT
CP 0FFH ;SUCESS?
JR Z, DSKERR ;NO, ABORT
;
LD A, 'O'
LD (HEXOPN),A ;DECLARE OPEN
XOR A
LD (HEXFCB+32), A
LD HL, HEXBUF ;DECLARE EMPTY
LD (HEXPTR), HL
JP PASS1 ;GO OPEN SRC
;
FLUSH LD A, (HEXOPN) ;HEX FILE OPEN?
CP 'O' ; IF O, YES
JR Z, HEXFL
;
LD A, (LSTOPN) ;LIST FILE OPEN?
CP 'O' ; IF O, YES
RET NZ ; NO OPEN OUTPUT FILES, EXIT
;
LD DE, LSTBUF ;DE POINTS TO START
LD HL, (LSTPTR) ;HL POINTS TO CURRENT CHAR
LD BC, LSTFCB ;NEED FCB PTR FOR CP/M
JR MTBUF
;
HEXFL LD DE, HEXBUF ;COMMENTS AS FOR LST FILE
LD HL, (HEXPTR)
LD BC, HEXFCB
;
MTBUF LD A, L ;FIND IF ON RECORD BOUNDARY
AND 127
JR Z, MTBUF2 ;IF Z, YES
LD (HL), CTLZ ;PUT ^Z AS EOF MARK
;
MTBUF2 PUSH BC ;SAVE FCB PTR
OR A ;CLEAR CARRY
SBC HL, DE ;CALC # BYTES IN BUFFER
JR NZ, AREREC ;IF NZ, ARE RECORDS TO WRITE
POP BC ;ELSE EXIT
RET
;
AREREC LD B, 7 ;B = SHIFT COUNTER
DIV128 SRL H ; BYTES/128 = # RECORDS
RR L
DJNZ DIV128 ;LOOP TIL DONE
;
LD B, L ;B = # RECORDS
OR A ;FIND IF EVEN RECORD AGAIN
JR Z, EVNREC
;
INC B ;DON'T WANT TO LOSE PARTIAL
EVNREC EX DE, HL ;HL = BUFFER POINTER
POP DE ;DE = FCB POINTER
;
CALL FLBUF ;WRITE BUFFER TO DISK
LD C, CLSFIL ;CLOSE FUNCTION
PUSH DE
CALL ENTRY
POP DE
LD HL, 35 ;(DE+35) = FILE OPEN FLAG
ADD HL, DE
EX DE, HL
LD (HL), 'C' ;DECLARE CLOSED
RET
;
FLBUF PUSH BC ;B=#RECS, C=CHAR
PUSH HL ;HL=BUFFER POINTER
PUSH DE ;DE=FCB PTR
;
EX DE, HL ;DE NOW = BUFFER PTR
LD C, SETDMA
CALL ENTRY ;DMA NOW = BUFFER
;
POP DE ;GET FCB PTR BACK
PUSH DE
LD C, WRNR ;WRITE NEXT REC FUNCTION
CALL ENTRY
;
OR A ;SET FLAGS
JP NZ, DSKERR
;
POP DE
POP HL
POP BC
;
DEC B
RET Z ;IF Z, ALL RECORDS WRITTEN
;
LD A, L
ADD A, 128 ;UPDATE DATA POINTER
LD L, A
JR NC, FLBUF
INC H
JR FLBUF
;
PCHO PUSH BC
PUSH DE
PUSH HL
LD HL, (HEXPTR) ;BUFFER POINTER
LD A,H ;GET HIGH ORDER
CP 34H ;FULL?
JR Z, DMPHEX ;IF Z, BUFFER FULL
;
HEXCHR LD (HL),C
INC HL ;NOT FULL, JUST STORE CHAR
LD (HEXPTR), HL
JP GENRET
;
DMPHEX PUSH BC ;SAVE CHAR
LD B, 8 ;8 RECORD BUFFER
LD HL, HEXBUF ;SETUP FOR FLBUF
LD DE, HEXFCB
CALL FLBUF
;
POP BC ;GET CHAR BACK
LD HL, HEXBUF ;START AT BEGINNING AGAIN
JR HEXCHR
;
LSTO PUSH BC
PUSH DE
PUSH HL
LD A,(PASSNO) ;GET CURRENT PASS
CP 4 ;IS IT PASS 4 ?
JP Z, OUT4 ;IF YES, OUTPUT TO CONSOLE
LD HL, (LSTPTR) ;NO, OUTPUT TO .PRN
LD A, H
CP 30H ;FULL?
JR Z, DMPLST ;YES, FLUSH
;
LSTCHR LD (HL), C ;STORE CHAR IN I/O BUFFER
INC HL ;UPDATE POINTER
LD (LSTPTR), HL
JP GENRET
;
DMPLST PUSH BC
LD B, 8 ;BUFFER = 8 RECORDS
LD HL, LSTBUF ;START AT BEGINNING
LD DE, LSTFCB ;FCB FOR CP/M
CALL FLBUF
;
POP BC ;GET THIS OUTPUT CHAR BACK
LD HL, LSTBUF ;RESTART AT BEGINNING
JR LSTCHR
;
RDRIN PUSH BC
PUSH DE
PUSH HL
LD HL, (SRCPTR) ;GET SRC POINTER
LD A, H
CP 2CH ;PAST END?
JR Z, SRCRD ;YES, GO GET MORE
;
NXTCHR LD A, (HL) ;GET CHAR
INC HL
LD (SRCPTR), HL ;SAVE POINTER
JP GENRET
;
SRCRD LD BC, 0880H ;B=#RECS, C=BYTES/REC
LD DE, SRCBUF ;DESTINATION
;
NXTREC PUSH DE
PUSH BC
LD C, SETDMA
CALL ENTRY
;
LD DE, SRCFCB
LD C, RDNR ;READ NEXT RECORD
CALL ENTRY
;
POP BC
POP DE
CP 1 ;1 MEANS FILE DONE
JR Z, SRCDON
;
LD A, E ;UPDATE DESTINATION
ADD A, C
LD E, A
JR NC, DOK
INC D
DOK DEC B ;DONE 8 RECORDS?
JR NZ, NXTREC ;NO, CONTINUE
;
SRCDON LD HL, SRCBUF ;START AT BEGINNING
JR NXTCHR
;
;
ORG 2800H ;I/O BUFFERS
SRCBUF DEFS 1024
LSTBUF DEFS 1024
HEXBUF DEFS 1024
;
END