PAGEWIDTH 96 TITLE 'CP/M-80 EMULATOR FOR CP/M-86' ; *** Z80.A86 *** VERSION 1.2 09/25/84 ; ; WRITTEN BY PAT HESTER 08/12/83 ; MODIFIED BY BILL EARNEST FOR CP/M-86 ; LAST EDIT 9/25/84 ; 09/25/84 ADD REL JMPS, REG EXCHGS FOR Z80 ; 09/22/84 ADD INTERNAL REPARSE WHICH CPM-86 HASNT ; 09/18/84 CUT .CMD FILE SIZE FOR FASTER LOADING (WDE) ; 09/17/84 FLAG USAGE FIXED, MP/M FUNCTS REPLACED SO ; CAN BE RUN UNDER CP/M-86. WILL NOW RUN WM.COM OK (WDE) ; ; GENCMD Z80 EXTRA[MC00] ; ; INVOCATION: ; Z80 filename<.typ> (typ defaults to .COM) ; ; **** 8080 OP CODES ARE ALLOWED *** ; **** A FEW Z-80 INSTR. ARE SUPPORTED (NOT MANY) **** ; **** PROGRAMS MUST USE STRICT CP/M CALLS THRU 0 AND 5 **** ; **** THE BIOS JUMP TABLE MUST NOT BE ACCESSED **** ; **** EXCEPT FOR CONIN, CONOU, CONST, LIST **** ; **** NO GAME PLAYING WITHIN CP/M **** ; ; REGISTER USAGE: ; SI Z80 INSTRUCTION POINTER ; BDOS EQU 0E0H ;BDOS INTERRUPT VECTOR BDOS_LIST EQU 5 ;LIST OUTPUT BDOS_DIRECT EQU 6 ;DIRECT CONSOLE I/O BDOS_PRINT EQU 9 ;PRINT STRING BDOS_INPUT EQU 10 ;READ CONSOLE BUFFER BDOS_OPENF EQU 15 ;OPEN FILE BDOS_CLOSEF EQU 16 ;CLOSE FILE BDOS_READ_NEXT EQU 20 ;READ SEQUENTIAL BDOS_GET_DISK EQU 25 ;RETURN CURRENT DISK NUMBER BDOS_DMA_OFFSET EQU 26 ;SET DMA OFFSET BDOS_DMA_BASE EQU 51 ;SET DMA BASE BDOS_TERMINATE EQU 0 ;TERMINATE PROCESS ;BDOS_PARSE EQU 152 ;PARSE FILE NAME ; CR EQU 0DH ;CARRAIGE RETURN LF EQU 0AH ;LINE FEED BEL EQU 07H ;RING BELL ; ZJMP EQU 0C3H ;Z80 JUMP OP CODE ZJZ EQU 0CAH ;Z80 JUMP ON ZERO ZRET EQU 0C9H ;Z80 RETURN CODE ZCALL EQU 0CDH ;Z80 CALL OP CODE ZLDCNN EQU 0EH ;Z80 LD C,nn OP CODE ZLDENN EQU 01EH ;Z80 LD E,nn OP CODE ZLDEC EQU 059H ;Z80 LD E,C OP CODE ZORA EQU 0B7H ;Z80 ORA A CODE CSEG CALL INITIALIZE ;SET UP CP/M-80 AREAS, ETC CALL LOAD_Z80 ;LOAD Z80 PROGRAM INTO ESEG JC EXIT CALL RUN_Z80 ;EMULATION EXIT: MOV DX,OFFSET MSG_TERMINATE CALL PRINT MOV DL,0 ;RELEASE MEMORY MOV CL,BDOS_TERMINATE INT BDOS ;TERMINATE PROCESS ; INITIALIZE: PUSH ES MOV CL,BDOS_GET_DISK INT BDOS MOV Z80_DISK,AL ;Z80 CURRENT DISK POP ES MOV SI,OFFSET BIOSIMG MOV DI,OFFSET Z80_BIOSV MOV CX,OFFSET BIOIMGE-OFFSET BIOSIMG REP MOVSB ;SETUP BIOS VECTORS IN USER SPACE ; MOV SI,OFFSET TBUF+1 MOV DI,OFFSET Z80_TAIL BNKLP: LODS AL OR AL,AL JZ HELP CMP AL,' ' JE BNKLP EATLP: LODS AL OR AL,AL JZ INIDUN CMP AL,' ' JNE EATLP MOV BL,-1 DEC SI PUSH SI TAILLP: LODS AL STOS AL INC BL ;COUNT BYTE OR AL,AL ;TEST BYTE JNZ TAILLP MOV Z80_DMA,BL ;TAIL SIZE POP SI MOV DI,OFFSET Z80_FCB CALL GETFN MOV DI,OFFSET Z80_FCB+16 CALL GETFN INIDUN: RET ; HELP: MOV DX,OFFSET HLP_MSG CALL PRINT1 POP AX ;ADJUST STACK FOR INIT RETURN JMP EXIT ; GETFN: call nitf call gstart jnz ntblnk ret ntblnk: call getdrv call getps RET ; nitf: push di xor al,al stos al mov al,' ' mov cx,11 rep stos al xor al,al mov cx,4 rep stos al pop di ret ; gstart: call getch jz isdelm dec si ret isdelm: cmp al,';' jne ntsemic ret ntsemic: or al,al jnz gstart ret ; getch: lods al cmp al,'.' jne t1 ret t1: cmp al,',' jne t2 ret t2: cmp al,';' jne t2a ret t2a: cmp al,' ' jne t3 ret t3: cmp al,':' jne t4 ret t4: cmp al,'=' jne t5 ret t5: cmp al,'<' jne t6 ret t6: cmp al,'>' jne t7 ret t7: or al,al ret ; getdrv: inc si lods al dec si dec si cmp al,':' jnz gdret lods al sub al,'@' stos al inc si ret gdret: inc di ret ; getps: mov cx,8 call getnam cmp al,'.' ;dot terminator? jnz gtpret ftpont: cmp cl,0 jz getft inc di dec cl jmps ftpont getft: mov cx,3 call getnam gtpret: ret ; getnam: call getch jnz gnl1 ret gnl1: cmp al,'*' jz ambig stos al dec cl jnz getnam jmps getdel ambig: mov al,'?' qfill: rep stos al getdel: call getch jnz getdel ret ; LOAD_Z80: PUSH ES mov al,fcbt1 cmp al,' ' jne typset mov fcbt1,'C' mov fcbt2,'MO' typset: MOV CL,BDOS_OPENF MOV DX,OFFSET FCB INT BDOS ;OPEN Z80 PROGRAM FILE INC AL ;0FFH=ERROR POP ES JZ LOAD_ERROR PUSH ES MOV CL,BDOS_DMA_BASE MOV DX,ES ;DMA BASE AT ESEG ORIGIN INT BDOS ;SET IT MOV DX,OFFSET Z80_TPA ;BEGIN LOAD THE FILE AT 0100H LOAD_LOOP: PUSH DX MOV CL,BDOS_DMA_OFFSET INT BDOS ;DMA NOW POINTS TO NEXT 128 BYTE BLOCK MOV CL,BDOS_READ_NEXT MOV DX,OFFSET FCB INT BDOS ;READ NEXT RECORD OR AL,AL ;0 INDICATES READ OK JNZ LOAD_EXIT ;END OF FILE POP DX ADD DX,128 ;POINT TO NEXT BLOCK JMP LOAD_LOOP LOAD_EXIT: POP DX ;RESTORE STACK MOV CL,BDOS_CLOSEF MOV DX,OFFSET FCB INT BDOS ;CLOSE IT UP MOV DX,OFFSET Z80_DMA ;SET DEFAULT DMA MOV CL,BDOS_DMA_OFFSET INT BDOS POP ES CLC ;RESET ERROR RET LOAD_ERROR: MOV DX,OFFSET MSG_NO_FILE CALL PRINT POP ES STC ;SET ERROR RET RUN_Z80: MOV SI,0100H ;INITIALIZE Z80 IP TO BASE OF TPA ; PUSHF RUN_LOOP: CMP SI,0C000H ;TOP OF Z80 MEMORY JNB Z80_RANGE_ERROR ;JUMP OUT OF RANGE CMP SI,0BFF8H ;BDOS CALL VECTOR JE Z80_BDOS_CALL Z80_OK: MOV DI,ES:[SI] ;DI[L] CONTAINS Z80 INSTRUCTION AND DI,00FFH ;REMOVE HIGH ORDER BYTE SAL DI,1 ;MULTIPLY BY 2 FOR JUMP OFFSET INC SI ;BUMP Z80 INSTRUCTION ADDRESS MOV BX,ES:[SI] ;WORD AFTER OP CODE MOV CX,JTABLE[DI] ;CX IS ADDRESS OF OP ROUTINE ; POPF ; PUSH ES ; LAHF SAHF CALL CX ;EXECUTE INSTRUCTION ; POP ES ; PUSHF LAHF JMP RUN_LOOP ;NEXT PLEASE Z80_BDOS_CALL: PUSH AX MOV CH,0 MOV CL,Z_C MOV DX,Z_DE PUSH SI PUSH DS PUSH ES PUSH ES POP DS INT BDOS POP ES POP DS MOV Z_HL,BX MOV Z_A,AL MOV Z_DE,DX POP SI CALL Z80_RET POP AX JMP RUN_LOOP Z80_RANGE_ERROR: CMP SI,0FFFFH JE Z80_END ;BOOT PUSH ES MOV DX,OFFSET MSG_RANGE_ERROR CALL PRINT POP ES Z80_END: ; POPF RET ; JTABLE: NOLIST INCLUDE JUMPADDR.Z80 ;JUMP ADDRESS TABLE LIST EDTBL: NOLIST INCLUDE EDADDR.Z80 LIST CBTBL: NOLIST INCLUDE CBADDR.Z80 LIST ; INCLUDE CODE8086.Z80 ;8086 INSTS. FOR Z80 OP CODES INCLUDE CODECB.Z80 INCLUDE CODEED.Z80 PRINT: PUSH ES PUSH DX MOV DX,OFFSET MSG_Z80 CALL PRINT1 POP DX CALL PRINT1 MOV DX,OFFSET MSG_CR_LF CALL PRINT1 POP ES RET ; PRINT1: MOV CL,BDOS_PRINT INT BDOS RET DSEG ORG 05CH FCB: rb 9 fcbt1 rb 1 fcbt2 rw 1 ORG 06CH FCB2: ORG 080H TBUF: ORG 0100H ;PAST UDA Z_REGISTERS: ;PRIMARY REGISTER SET Z_C RB 1 ;REGISTER C Z_B RB 1 ;REGISTER B Z_E RB 1 ;REGISTER E Z_D RB 1 ;REGISTER D Z_L RB 1 ;REGISTER L Z_H RB 1 ;REGISTER H Z_F RB 1 ;REGISTER F...Z80 CONTROL FLAGS Z_A RB 1 ;REGISTER A ORG 0100H Z_BC RW 1 ;REGISTER BC Z_DE RW 1 ;REGISTER DE Z_HL RW 1 ;REGISTER HL Z_AF RW 1 ;REGISTER AF Z_SP DW 0BFF0H ;Z80 STACK POINTER ; Z_ALTR RW 3 Z_ALTA RW 1 Z_X RW 1 Z_Y RW 1 Z_TEMP RW 3 ;SCRATCH FOR SWAP MSG_NO_FILE DB 'NO Z80 FILE$' MSG_TERMINATE DB 'EXITING TO CP/M-86$' MSG_RANGE_ERROR DB 'BRANCH OUTSIDE ADDRESS SPACE$' MSG_Z80_OP DB 'Z80 OP CODE DETECTED, ONLY 8080 ALLOWED$' MSG_Z80 DB CR,LF,'z80-->$' MSG_CR_LF DB CR,LF,'$' HLP_MSG DB 'Syntax: Z80 cmd ',cr,lf DB 'Where cmd is 8080 file (default .COM)',cr,lf DB 'and are the normal arguments.',cr,lf,'$' ; START OF HI RAM IMAGE BIOSIMG: DB ZJMP DW 0FFFFH ;JP COLDBOOT DB ZJMP DW 0FFFFH ;JP WARMBOOT DB ZJMP DW OFFSET ZBIOS1 ;JP CONST DB ZJMP DW OFFSET ZBIOS2 ;JP CONIN DB ZJMP DW OFFSET ZBIOS3 ;JP CONOUT DB ZJMP DW OFFSET ZBIOS4 ;JP LIST DB ZJMP DW 0FFFEH ;JP PUNCH (NG) DB ZJMP DW 0FFFEH ;JP READER (NG) DB ZJMP DW 0FFFEH ;JP HOME (NG) DB ZJMP DW 0FFFEH ;JP SELDSK (NG) DB ZJMP DW 0FFFEH ;JP SETTRK (NG) DB ZJMP DW 0FFFEH ;JP SETSEC (NG) DB ZJMP DW 0FFFEH ;JP SETDMA (NG) DB ZJMP DW 0FFFEH ;JP READ (NG) DB ZJMP DW 0FFFEH ;JP WRITE (NG) DB ZJMP DW 0FFFEH ;JP LISTST (NG) DB ZJMP DW 0FFFEH ;JP SECTTRANS (NG) ; DB ZLDCNN,BDOS_DIRECT ;LD C,BDOS_DIRECT (RAW I/O) DB ZLDENN,0FEH ;LD E,BDOS_GET_STATUS DB ZCALL DW 0BFF8H ;JP BDOS DB ZRET ; DB ZLDCNN,BDOS_DIRECT ;LD C,BDOS_DIRECT (RAW I/O) DB ZLDENN,0FFH ;LD E,BDOS_INPUT_CHAR DB ZCALL DW 0BFF8H ;JP BDOS DB ZORA ; ORA A DB ZJZ DW OFFSET ZBIOS2 DB ZRET ; DB ZLDEC ;LD E,C DB ZLDCNN,BDOS_DIRECT ;RAW I/O DB ZCALL DW 0BFF8H ;JP BDOS DB ZRET ; DB ZLDEC ;LD E,C DB ZLDCNN,BDOS_LIST ;LD C,OUTPUT DB ZCALL DW 0BFF8H ;JP BDOS DB ZRET ; RB 155 DW 0FFFFH ;FORCE REBOOT RB 14 BIOIMGE: ; ESEG Z80_BOOT DB 0C3H ;JP BOOT DW 0BF03H ;0FFFFH RETURNS TO 8086 Z80_IOBYTE DB 0 ;IOBYTE Z80_DISK DB 0 ;CURRENT DISK Z80_BDOS DB 0C3H ;JMP BDOS DW 0BFF8H ;SET FOR 48K TPA ORG 05CH ;Z80 FCB Z80_FCB: DB 0,' ',' ',0,0,0,0 ;ONLY ONE VALID DB 0,' ',' ',0,0,0,0 ;NOT PARSED ORG 080H Z80_BUF: Z80_DMA DB 0 Z80_TAIL: ORG 0100H ;BEGINNING OF Z80 TPA Z80_TPA: ORG 0BF00H ;BIOS JUMP TABLE Z80_BIOSV: RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 RB 1 RW 1 ZBIOS1: ;GET CONSOLE STATUS RB 8 ZBIOS2: ;GET ONE CHARACTER RB 12 ZBIOS3: ;SEND ONE CHARACTER RB 7 ZBIOS4: ;ONE CHAR TO LIST RB 7 ; ORG 0BFF0H RW 1 ; ORG 0BFFFH RB 1 ;MAKE SURE MP/M-86 DOES END