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