/** Z80: portable Z80 emulator **********************************************/ /** **/ /** Debug.c **/ /** **/ /** This file contains the built-in debugging routine for the Z80 emulator **/ /** which is called on each Z80 step when Trap==TRUE **/ /** **/ /** Copyright (C) Marat Fayzullin 1995,1996 **/ /** Marcel de Kogel 1996 **/ /** You are not allowed to distribute this software commercially **/ /** Please, notify me, if you make any changes to this file **/ /****************************************************************************/ #ifdef DEBUG #include "Z80.h" #include <stdio.h> #include <string.h> #include <ctype.h> #include <conio.h> #include <allegro.h> #define MEM1DEFAULT 0x9000 #define MEM2DEFAULT 0x9800 #define XRES 256 #define YRES 256 #define HEADING_COLOUR LIGHTGREEN #define LINE_COLOUR LIGHTCYAN #define REGISTER_COLOUR WHITE #define FLAG_COLOUR WHITE #define BREAKPOINT_COLOUR YELLOW #define CODE_COLOUR WHITE #define MEM1_COLOUR WHITE #define MEM2_COLOUR WHITE #define ERROR_COLOUR RED #define PROMPT_COLOUR CYAN #define INSTRUCTION_COLOUR WHITE #define INPUT_COLOUR WHITE int DAsm(char *S,word A); char *Mnemonics[256] = { "NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA", "EX AF,AF'","ADD HL,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA", "DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA", "JR @h","ADD HL,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA", "JR NZ,@h","LD HL,#h","LD (#h),HL","INC HL","INC H","DEC H","LD H,*h","DAA", "JR Z,@h","ADD HL,HL","LD HL,(#h)","DEC HL","INC L","DEC L","LD L,*h","CPL", "JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (HL)","DEC (HL)","LD (HL),*h","SCF", "JR C,@h","ADD HL,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF", "LD B,B","LD B,C","LD B,D","LD B,E","LD B,H","LD B,L","LD B,(HL)","LD B,A", "LD C,B","LD C,C","LD C,D","LD C,E","LD C,H","LD C,L","LD C,(HL)","LD C,A", "LD D,B","LD D,C","LD D,D","LD D,E","LD D,H","LD D,L","LD D,(HL)","LD D,A", "LD E,B","LD E,C","LD E,D","LD E,E","LD E,H","LD E,L","LD E,(HL)","LD E,A", "LD H,B","LD H,C","LD H,D","LD H,E","LD H,H","LD H,L","LD H,(HL)","LD H,A", "LD L,B","LD L,C","LD L,D","LD L,E","LD L,H","LD L,L","LD L,(HL)","LD L,A", "LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E","LD (HL),H","LD (HL),L","HALT","LD (HL),A", "LD A,B","LD A,C","LD A,D","LD A,E","LD A,H","LD A,L","LD A,(HL)","LD A,A", "ADD B","ADD C","ADD D","ADD E","ADD H","ADD L","ADD (HL)","ADD A", "ADC B","ADC C","ADC D","ADC E","ADC H","ADC L","ADC (HL)","ADC A", "SUB B","SUB C","SUB D","SUB E","SUB H","SUB L","SUB (HL)","SUB A", "SBC B","SBC C","SBC D","SBC E","SBC H","SBC L","SBC (HL)","SBC A", "AND B","AND C","AND D","AND E","AND H","AND L","AND (HL)","AND A", "XOR B","XOR C","XOR D","XOR E","XOR H","XOR L","XOR (HL)","XOR A", "OR B","OR C","OR D","OR E","OR H","OR L","OR (HL)","OR A", "CP B","CP C","CP D","CP E","CP H","CP L","CP (HL)","CP A", "RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h", "RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h", "RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h", "RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h", "RET PO","POP HL","JP PO,#h","EX HL,(SP)","CALL PO,#h","PUSH HL","AND *h","RST 20h", "RET PE","LD PC,HL","JP PE,#h","EX DE,HL","CALL PE,#h","PFX_ED","XOR *h","RST 28h", "RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h", "RET M","LD SP,HL","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h" }; char *MnemonicsCB[256] = { "RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (HL)","RLC A", "RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (HL)","RRC A", "RL B","RL C","RL D","RL E","RL H","RL L","RL (HL)","RL A", "RR B","RR C","RR D","RR E","RR H","RR L","RR (HL)","RR A", "SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (HL)","SLA A", "SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (HL)","SRA A", "SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (HL)","SLL A", "SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (HL)","SRL A", "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A", "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A", "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A", "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A", "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A", "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A", "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A", "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A", "RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A", "RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A", "RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A", "RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A", "RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A", "RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A", "RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A", "RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A", "SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A", "SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A", "SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A", "SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A", "SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A", "SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A", "SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A", "SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A" }; char *MnemonicsED[256] = { "DB EDh,00h","DB EDh,01h","DB EDh,02h","DB EDh,03h", "DB EDh,04h","DB EDh,05h","DB EDh,06h","DB EDh,07h", "DB EDh,08h","DB EDh,09h","DB EDh,0Ah","DB EDh,0Bh", "DB EDh,0Ch","DB EDh,0Dh","DB EDh,0Eh","DB EDh,0Fh", "DB EDh,10h","DB EDh,11h","DB EDh,12h","DB EDh,13h", "DB EDh,14h","DB EDh,15h","DB EDh,16h","DB EDh,17h", "DB EDh,18h","DB EDh,19h","DB EDh,1Ah","DB EDh,1Bh", "DB EDh,1Ch","DB EDh,1Dh","DB EDh,1Eh","DB EDh,1Fh", "DB EDh,20h","DB EDh,21h","DB EDh,22h","DB EDh,23h", "DB EDh,24h","DB EDh,25h","DB EDh,26h","DB EDh,27h", "DB EDh,28h","DB EDh,29h","DB EDh,2Ah","DB EDh,2Bh", "DB EDh,2Ch","DB EDh,2Dh","DB EDh,2Eh","DB EDh,2Fh", "DB EDh,30h","DB EDh,31h","DB EDh,32h","DB EDh,33h", "DB EDh,34h","DB EDh,35h","DB EDh,36h","DB EDh,37h", "DB EDh,38h","DB EDh,39h","DB EDh,3Ah","DB EDh,3Bh", "DB EDh,3Ch","DB EDh,3Dh","DB EDh,3Eh","DB EDh,3Fh", "IN B,(C)","OUT (C),B","SBC HL,BC","LD (#h),BC", "DB EDh,44h","RETN","IM 0","LD I,A", "IN C,(C)","OUT (C),C","ADC HL,BC","LD BC,(#h)", "DB EDh,4Ch","RETI","DB EDh,4Eh","LD R,A", "IN D,(C)","OUT (C),D","SBC HL,DE","LD (#h),DE", "DB EDh,54h","DB EDh,55h","IM 1","LD A,I", "IN E,(C)","OUT (C),E","ADC HL,DE","LD DE,(#h)", "DB EDh,5Ch","DB EDh,5Dh","IM 2","LD A,R", "IN H,(C)","OUT (C),H","SBC HL,HL","LD (#h),HL", "DB EDh,64h","DB EDh,65h","DB EDh,66h","RRD", "IN L,(C)","OUT (C),L","ADC HL,HL","LD HL,(#h)", "DB EDh,6Ch","DB EDh,6Dh","DB EDh,6Eh","RLD", "IN F,(C)","DB EDh,71h","SBC HL,SP","LD (#h),SP", "DB EDh,74h","DB EDh,75h","DB EDh,76h","DB EDh,77h", "IN A,(C)","OUT (C),A","ADC HL,SP","LD SP,(#h)", "DB EDh,7Ch","DB EDh,7Dh","DB EDh,7Eh","DB EDh,7Fh", "DB EDh,80h","DB EDh,81h","DB EDh,82h","DB EDh,83h", "DB EDh,84h","DB EDh,85h","DB EDh,86h","DB EDh,87h", "DB EDh,88h","DB EDh,89h","DB EDh,8Ah","DB EDh,8Bh", "DB EDh,8Ch","DB EDh,8Dh","DB EDh,8Eh","DB EDh,8Fh", "DB EDh,90h","DB EDh,91h","DB EDh,92h","DB EDh,93h", "DB EDh,94h","DB EDh,95h","DB EDh,96h","DB EDh,97h", "DB EDh,98h","DB EDh,99h","DB EDh,9Ah","DB EDh,9Bh", "DB EDh,9Ch","DB EDh,9Dh","DB EDh,9Eh","DB EDh,9Fh", "LDI","CPI","INI","OUTI", "DB EDh,A4h","DB EDh,A5h","DB EDh,A6h","DB EDh,A7h", "LDD","CPD","IND","OUTD", "DB EDh,ACh","DB EDh,ADh","DB EDh,AEh","DB EDh,AFh", "LDIR","CPIR","INIR","OTIR", "DB EDh,B4h","DB EDh,B5h","DB EDh,B6h","DB EDh,B7h", "LDDR","CPDR","INDR","OTDR", "DB EDh,BCh","DB EDh,BDh","DB EDh,BEh","DB EDh,BFh", "DB EDh,C0h","DB EDh,C1h","DB EDh,C2h","DB EDh,C3h", "DB EDh,C4h","DB EDh,C5h","DB EDh,C6h","DB EDh,C7h", "DB EDh,C8h","DB EDh,C9h","DB EDh,CAh","DB EDh,CBh", "DB EDh,CCh","DB EDh,CDh","DB EDh,CEh","DB EDh,CFh", "DB EDh,D0h","DB EDh,D1h","DB EDh,D2h","DB EDh,D3h", "DB EDh,D4h","DB EDh,D5h","DB EDh,D6h","DB EDh,D7h", "DB EDh,D8h","DB EDh,D9h","DB EDh,DAh","DB EDh,DBh", "DB EDh,DCh","DB EDh,DDh","DB EDh,DEh","DB EDh,DFh", "DB EDh,E0h","DB EDh,E1h","DB EDh,E2h","DB EDh,E3h", "DB EDh,E4h","DB EDh,E5h","DB EDh,E6h","DB EDh,E7h", "DB EDh,E8h","DB EDh,E9h","DB EDh,EAh","DB EDh,EBh", "DB EDh,ECh","DB EDh,EDh","DB EDh,EEh","DB EDh,EFh", "DB EDh,F0h","DB EDh,F1h","DB EDh,F2h","DB EDh,F3h", "DB EDh,F4h","DB EDh,F5h","DB EDh,F6h","DB EDh,F7h", "DB EDh,F8h","DB EDh,F9h","DB EDh,FAh","DB EDh,FBh", "DB EDh,FCh","DB EDh,FDh","DB EDh,FEh","DB EDh,FFh" }; char *MnemonicsXX[256] = { "NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA", "EX AF,AF'","ADD I%,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA", "DJNZ @h","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA", "JR @h","ADD I%,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA", "JR NZ,@h","LD I%,#h","LD (#h),I%","INC I%","INC I%h","DEC I%h","LD I%h,*h","DAA", "JR Z,@h","ADD I%,I%","LD I%,(#h)","DEC I%","INC I%l","DEC I%l","LD I%l,*h","CPL", "JR NC,@h","LD SP,#h","LD (#h),A","INC SP","INC (I%+^h)","DEC (I%+^h)","LD (I%+^h),*h","SCF", "JR C,@h","ADD I%,SP","LD A,(#h)","DEC SP","INC A","DEC A","LD A,*h","CCF", "LD B,B","LD B,C","LD B,D","LD B,E","LD B,I%h","LD B,I%l","LD B,(I%+^h)","LD B,A", "LD C,B","LD C,C","LD C,D","LD C,E","LD C,I%h","LD C,I%l","LD C,(I%+^h)","LD C,A", "LD D,B","LD D,C","LD D,D","LD D,E","LD D,I%h","LD D,I%l","LD D,(I%+^h)","LD D,A", "LD E,B","LD E,C","LD E,D","LD E,E","LD E,I%h","LD E,I%l","LD E,(I%+^h)","LD E,A", "LD I%h,B","LD I%h,C","LD I%h,D","LD I%h,E","LD I%h,I%h","LD I%h,I%l","LD H,(I%+^h)","LD I%h,A", "LD I%l,B","LD I%l,C","LD I%l,D","LD I%l,E","LD I%l,I%h","LD I%l,I%l","LD L,(I%+^h)","LD I%l,A", "LD (I%+^h),B","LD (I%+^h),C","LD (I%+^h),D","LD (I%+^h),E","LD (I%+^h),H","LD (I%+^h),L","HALT","LD (I%+^h),A", "LD A,B","LD A,C","LD A,D","LD A,E","LD A,I%h","LD A,I%l","LD A,(I%+^h)","LD A,A", "ADD B","ADD C","ADD D","ADD E","ADD I%h","ADD I%l","ADD (I%+^h)","ADD A", "ADC B","ADC C","ADC D","ADC E","ADC I%h","ADC I%l","ADC (I%+^h)","ADC,A", "SUB B","SUB C","SUB D","SUB E","SUB I%h","SUB I%l","SUB (I%+^h)","SUB A", "SBC B","SBC C","SBC D","SBC E","SBC I%h","SBC I%l","SBC (I%+^h)","SBC A", "AND B","AND C","AND D","AND E","AND I%h","AND I%l","AND (I%+^h)","AND A", "XOR B","XOR C","XOR D","XOR E","XOR I%h","XOR I%l","XOR (I%+^h)","XOR A", "OR B","OR C","OR D","OR E","OR I%h","OR I%l","OR (I%+^h)","OR A", "CP B","CP C","CP D","CP E","CP I%h","CP I%l","CP (I%+^h)","CP A", "RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h", "RET Z","RET","JP Z,#h","PFX_CB","CALL Z,#h","CALL #h","ADC *h","RST 08h", "RET NC","POP DE","JP NC,#h","OUTA (*h)","CALL NC,#h","PUSH DE","SUB *h","RST 10h", "RET C","EXX","JP C,#h","INA (*h)","CALL C,#h","PFX_DD","SBC *h","RST 18h", "RET PO","POP I%","JP PO,#h","EX I%,(SP)","CALL PO,#h","PUSH I%","AND *h","RST 20h", "RET PE","LD PC,I%","JP PE,#h","EX DE,I%","CALL PE,#h","PFX_ED","XOR *h","RST 28h", "RET P","POP AF","JP P,#h","DI","CALL P,#h","PUSH AF","OR *h","RST 30h", "RET M","LD SP,I%","JP M,#h","EI","CALL M,#h","PFX_FD","CP *h","RST 38h" }; char *MnemonicsXCB[256] = { "RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (I%@h)","RLC A", "RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (I%@h)","RRC A", "RL B","RL C","RL D","RL E","RL H","RL L","RL (I%@h)","RL A", "RR B","RR C","RR D","RR E","RR H","RR L","RR (I%@h)","RR A", "SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (I%@h)","SLA A", "SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (I%@h)","SRA A", "SLL B","SLL C","SLL D","SLL E","SLL H","SLL L","SLL (I%@h)","SLL A", "SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (I%@h)","SRL A", "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(I%@h)","BIT 0,A", "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(I%@h)","BIT 1,A", "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(I%@h)","BIT 2,A", "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(I%@h)","BIT 3,A", "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(I%@h)","BIT 4,A", "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(I%@h)","BIT 5,A", "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(I%@h)","BIT 6,A", "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(I%@h)","BIT 7,A", "RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(I%@h)","RES 0,A", "RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(I%@h)","RES 1,A", "RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(I%@h)","RES 2,A", "RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(I%@h)","RES 3,A", "RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(I%@h)","RES 4,A", "RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(I%@h)","RES 5,A", "RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(I%@h)","RES 6,A", "RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(I%@h)","RES 7,A", "SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(I%@h)","SET 0,A", "SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(I%@h)","SET 1,A", "SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(I%@h)","SET 2,A", "SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(I%@h)","SET 3,A", "SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(I%@h)","SET 4,A", "SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(I%@h)","SET 5,A", "SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(I%@h)","SET 6,A", "SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(I%@h)","SET 7,A" }; int DAsm(char *S,word A) { char R[128],H[10],C,*T,*P; byte J; byte Offset = 0; word B; B=A;C='\0';J=0; switch(M_RDMEM(B)) { case 0xCB: B++;T=MnemonicsCB[M_RDMEM(B++)];break; case 0xED: B++;T=MnemonicsED[M_RDMEM(B++)];break; case 0xDD: B++;C='X'; if(M_RDMEM(B)!=0xCB) T=MnemonicsXX[M_RDMEM(B++)]; else { B++;Offset=M_RDMEM(B++);J=1;T=MnemonicsXCB[M_RDMEM(B++)]; } break; case 0xFD: B++;C='Y'; if(M_RDMEM(B)!=0xCB) T=MnemonicsXX[M_RDMEM(B++)]; else { B++;Offset=M_RDMEM(B++);J=1;T=MnemonicsXCB[M_RDMEM(B++)]; } break; default: T=Mnemonics[M_RDMEM(B++)]; } if((P=strchr(T,'^'))) { strncpy(R,T,P-T);R[P-T]='\0'; sprintf(H,"%02X",M_RDMEM(B++)); strcat(R,H);strcat(R,P+1); } else strcpy(R,T); if((P=strchr(R,'%'))) *P=C; if((P=strchr(R,'*'))) { strncpy(S,R,P-R);S[P-R]='\0'; sprintf(H,"%02X",M_RDMEM(B++)); strcat(S,H);strcat(S,P+1); } else if((P=strchr(R,'@'))) { strncpy(S,R,P-R);S[P-R]='\0'; if(!J) Offset=M_RDMEM(B++); strcat(S,Offset&0x80? "-":"+"); J=Offset&0x80? 256-Offset:Offset; sprintf(H,"%02X",J); strcat(S,H);strcat(S,P+1); } else if((P=strchr(R,'#'))) { strncpy(S,R,P-R);S[P-R]='\0'; sprintf(H,"%04X",M_RDMEM(B)+256*M_RDMEM(B+1)); strcat(S,H);strcat(S,P+1); B+=2; } else strcpy(S,R); return(B-A); } // Draw the screen outline void DrawDebugScreen(int TextCol, int LineCol) { int y; ScreenPutString("��� ����������������������������������������������������������������ͻ", LineCol, 0, 0); ScreenPutString("Registers", TextCol, 4, 0); ScreenPutString("�", LineCol, 0, 1); ScreenPutString("�", LineCol, 79, 1); ScreenPutString("��� ���������������� ������������������������������������������", LineCol, 0, 2); ScreenPutString("Flags", TextCol, 4, 2); ScreenPutString("Memory 1", TextCol, 27, 2); ScreenPutString("�", LineCol, 0, 3); ScreenPutString("�", LineCol, 23, 3); ScreenPutString("�", LineCol, 79, 3); ScreenPutString("��� �������������", LineCol, 0, 4); ScreenPutString("Code", TextCol, 4, 4); ScreenPutString("�", LineCol, 79, 4); for (y = 5; y < 11; y++) { ScreenPutString("�", LineCol, 0, y); ScreenPutString("�", LineCol, 23, y); ScreenPutString("�", LineCol, 79, y); } ScreenPutString("�", LineCol, 0, 11); ScreenPutString("��� ������������������������������������������", LineCol, 23, 11); ScreenPutString("Memory 2", TextCol, 27, 11); for (y = 12; y < 20; y++) { ScreenPutString("�", LineCol, 0, y); ScreenPutString("�", LineCol, 23, y); ScreenPutString("�", LineCol, 79, y); } ScreenPutString("��� ������������������������������������������������������������������", LineCol, 0, 20); ScreenPutString("Command", TextCol, 4, 20); for (y = 21; y < 24; y++) { ScreenPutString("�", LineCol, 0, y); ScreenPutString("�", LineCol, 79, y); } ScreenPutString("������������������������������������������������������������������������������ͼ", LineCol, 0, 24); } // Get a Number int GetNumber(int X, int Y, int Col) { char Num[16]; int Pos = 0; int Key; Num[Pos] = '\0'; ScreenSetCursor(Y, X); ScreenPutString(" ", Col, X, Y); while ((Key = (readkey()) & 0xff) != '\r') { Key = toupper(Key); switch(Key) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': Num[Pos++] = Key; Num[Pos] = '\0'; break; case '\b': if (Pos > 0) { Pos--; Num[Pos] = '\0'; } break; default: Key = 0; break; } if (Key) { ScreenPutString(" ", Col, X + Pos, Y); ScreenPutString(Num, Col, X, Y); ScreenSetCursor(Y, X + Pos); } } ScreenPutString(" ", Col, X, Y); return(strtol(Num, NULL, 16)); } /*** Single-step debugger ****************************/ /*** This function should exist if DEBUG is ***/ /*** #defined. When Trace=TRUE, it is called after ***/ /*** each command executed by the CPU and given ***/ /*** a pointer to the register file. ***/ /*****************************************************/ word MEM1 = MEM1DEFAULT; word MEM2 = MEM2DEFAULT; void Debug(reg *R) { int x, y; static int InDebug=FALSE; static int Update; static int Step; static int DebugTrace = FALSE; static int BreakPointValid = FALSE; static word BreakPoint = 0; dword ADD; byte VAL; int Key; int Colour; int InvalidKey; static char Flags[8] = "SZ.H.PNC"; char S[128],T[10]; byte J,I; word PC; // Check for breakpoint of F1 key to enter debugger if ((BreakPointValid && (R->PC.W.l == BreakPoint)) || key[KEY_F1]) { clear_keybuf(); set_gfx_mode(GFX_TEXT,80,25,0,0); DrawDebugScreen(HEADING_COLOUR, LINE_COLOUR); InDebug = TRUE; Update = TRUE; DebugTrace = FALSE; } Step = FALSE; // So that we will get back into debugger if needed Update = TRUE; // Cause a screen refresh while ((InDebug) && !Step) { if (Update) { for(J=0,I=R->AF.B.l;J<8;J++,I<<=1) T[J]=I&0x80? Flags[J]:'.'; T[8]='\0'; sprintf(S, "AF:%04X HL:%04X DE:%04X BC:%04X PC:%04X SP:%04X IX:%04X IY:%04X I:%02X R:%02X", R->AF.W.l, R->HL.W.l, R->DE.W.l, R->BC.W.l, R->PC.W.l, R->SP.W.l, R->IX.W.l, R->IY.W.l, R->I, R->R); ScreenPutString(S, REGISTER_COLOUR, 2, 1); ScreenPutString(T, FLAG_COLOUR, 2, 3); PC = R->PC.W.l; for(y = 0; y < 15; y++) { if (BreakPointValid && (PC == BreakPoint)) Colour = BREAKPOINT_COLOUR; else Colour = CODE_COLOUR; sprintf(S, "%04X: ", PC); ScreenPutString(S, Colour, 2, y + 5); PC += DAsm(S, PC); ScreenPutString(S, Colour, 8, y + 5); } PC = MEM1; for (y = 0; y < 8; y++) { sprintf(S, "%04X:", PC); ScreenPutString(S, MEM1_COLOUR, 25, y + 3); for (x = 0; x < 16; x++) { sprintf(S, "%02X", M_RDMEM(PC++)); ScreenPutString(S, MEM1_COLOUR, 31 + (x * 3), y + 3); } } PC = MEM2; for (y = 0; y < 8; y++) { sprintf(S, "%04X:", PC); ScreenPutString(S, MEM2_COLOUR, 25, y + 12); for (x = 0; x < 16; x++) { sprintf(S, "%02X", M_RDMEM(PC++)); ScreenPutString(S, MEM2_COLOUR, 31 + (x * 3), y + 12); } } ScreenPutString("Command>", PROMPT_COLOUR, 2, 21); ScreenSetCursor(21, 10); Update = FALSE; } if (!DebugTrace) { Key = readkey(); ScreenPutString(" ", INSTRUCTION_COLOUR, 2, 22); InvalidKey = FALSE; // Assume a valid key sprintf(S, "%c", Key & 0xff); ScreenPutString(S, INPUT_COLOUR, 10, 21); switch (Key & 0xff) { case '1': ScreenPutString("Enter new address for memory 1", INSTRUCTION_COLOUR, 2, 22); MEM1 = GetNumber(10, 21, INPUT_COLOUR); Update = TRUE; break; case '2': ScreenPutString("Enter new address for memory 2", INSTRUCTION_COLOUR, 2, 22); MEM2 = GetNumber(10, 21, INPUT_COLOUR); Update = TRUE; break; case 'b': case 'B': ScreenPutString("Enter new breakpoint address", INSTRUCTION_COLOUR, 2, 22); BreakPoint = GetNumber(10, 21, INPUT_COLOUR); BreakPointValid = TRUE; Update = TRUE; break; case 'c': case 'C': Update = FALSE; InDebug = FALSE; set_gfx_mode(GFX_AUTODETECT,XRES,YRES,0,0); break; case 'd': case 'D': BreakPointValid = FALSE; Update = TRUE; break; case 'e': case 'E': ScreenPutString("Enter address to edit", INSTRUCTION_COLOUR, 2, 22); ADD = GetNumber(10, 21, INPUT_COLOUR); ScreenPutString("Enter New Value ", INSTRUCTION_COLOUR, 2, 22); VAL = GetNumber(10, 21, INPUT_COLOUR); M_WRMEM(ADD, VAL); Update = TRUE; break; case 'r': case 'R': ScreenPutString("Change which register ?", INSTRUCTION_COLOUR, 2, 22); readkey(); Update = TRUE; break; case 's': case 'S': case ' ': case '\r': Step = TRUE; break; case 't': case 'T': DebugTrace = TRUE; Step = TRUE; break; case 'v': case 'V': set_gfx_mode(GFX_AUTODETECT,XRES,YRES,0,0); Interrupt(); while (!readkey()) continue; // do nothing set_gfx_mode(GFX_TEXT,80,25,0,0); DrawDebugScreen(HEADING_COLOUR, LINE_COLOUR); Update = TRUE; break; case 27: // ESC CPURunning = 0; InDebug = FALSE; break; default: InvalidKey = TRUE; break; } if (InvalidKey) { ScreenPutString("Unknown Command", ERROR_COLOUR, 2, 22); } else { ScreenPutString(" ", INPUT_COLOUR, 10, 21); ScreenPutString(" ", INSTRUCTION_COLOUR, 2, 22); } } else { Step = TRUE; if (keypressed()) { clear_keybuf(); DebugTrace = FALSE; } } } // Do a final check for exit if (key[KEY_ESC]) CPURunning = 0; } #endif