/** 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