MSXHawk: More trace logger and bug fixes

This commit is contained in:
alyosha-tas 2020-01-16 18:53:11 -05:00
parent 1c3e823ea2
commit 6637510379
6 changed files with 302 additions and 169 deletions

View File

@ -53,6 +53,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MSX_get_video(IntPtr core, int[] videobuf); public static extern void MSX_get_video(IntPtr core, int[] videobuf);
#region Tracer
/// <summary> /// <summary>
/// type of the cpu trace callback /// type of the cpu trace callback
/// </summary> /// </summary>
@ -68,6 +69,27 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MSX_settracecallback(IntPtr core, TraceCallback callback); public static extern void MSX_settracecallback(IntPtr core, TraceCallback callback);
/// <summary>
/// get the trace logger header length
/// </summary>
/// <param name="core">opaque state pointer</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MSX_getheaderlength(IntPtr core);
/// <summary>
/// get the trace logger disassembly length, a constant
/// </summary>
/// <param name="core">opaque state pointer</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MSX_getdisasmlength(IntPtr core);
/// <summary>
/// get the trace logger register string length, a constant
/// </summary>
/// <param name="core">opaque state pointer</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MSX_getregstringlength(IntPtr core);
/// <summary> /// <summary>
/// get the trace logger header /// get the trace logger header
/// </summary> /// </summary>
@ -75,16 +97,7 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
/// <param name="h">pointer to const char *</param> /// <param name="h">pointer to const char *</param>
/// <param name="callback">null to clear</param> /// <param name="callback">null to clear</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MSX_getheader(IntPtr core, StringBuilder h); public static extern void MSX_getheader(IntPtr core, StringBuilder h, int l);
/// <summary>
/// get the trace logger header length
/// </summary>
/// <param name="core">opaque state pointer</param>
/// <param name="h">pointer to const char *</param>
/// <param name="callback">null to clear</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MSX_getheaderlength(IntPtr core);
/// <summary> /// <summary>
/// get the register state from the cpu /// get the register state from the cpu
@ -92,8 +105,9 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
/// <param name="core">opaque state pointer</param> /// <param name="core">opaque state pointer</param>
/// <param name="r">pointer to const char *</param> /// <param name="r">pointer to const char *</param>
/// <param name="t">call type</param> /// <param name="t">call type</param>
/// <param name="l">copy length, must be obtained from appropriate get legnth function</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MSX_getregisterstate(IntPtr core, StringBuilder h, int t); public static extern void MSX_getregisterstate(IntPtr core, StringBuilder h, int t, int l);
/// <summary> /// <summary>
/// get the register state from the cpu /// get the register state from the cpu
@ -101,7 +115,9 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
/// <param name="core">opaque state pointer</param> /// <param name="core">opaque state pointer</param>
/// <param name="d">pointer to const char *</param> /// <param name="d">pointer to const char *</param>
/// <param name="t">call type</param> /// <param name="t">call type</param>
/// <param name="l">copy length, must be obtained from appropriate get legnth function</param>
[DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)] [DllImport("MSXHAWK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void MSX_getdisassembly(IntPtr core, StringBuilder h, int t); public static extern void MSX_getdisassembly(IntPtr core, StringBuilder h, int t, int l);
#endregion
} }
} }

View File

@ -39,9 +39,16 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
InputCallbacks = new InputCallbackSystem(); InputCallbacks = new InputCallbackSystem();
int new_header_size = LibMSX.MSX_getheaderlength(MSX_Pntr); Header_Length = LibMSX.MSX_getheaderlength(MSX_Pntr);
StringBuilder new_header = new StringBuilder(new_header_size); Disasm_Length = LibMSX.MSX_getdisasmlength(MSX_Pntr);
LibMSX.MSX_getheader(MSX_Pntr, new_header); Reg_String_Length = LibMSX.MSX_getregstringlength(MSX_Pntr);
StringBuilder new_header = new StringBuilder(Header_Length);
LibMSX.MSX_getheader(MSX_Pntr, new_header, Header_Length);
Console.WriteLine(Header_Length + " " + Disasm_Length + " " + Reg_String_Length);
Tracer = new TraceBuffer { Header = new_header.ToString() }; Tracer = new TraceBuffer { Header = new_header.ToString() };
@ -74,15 +81,18 @@ namespace BizHawk.Emulation.Cores.Computers.MSX
private LibMSX.TraceCallback tracecb; private LibMSX.TraceCallback tracecb;
// these will be constant values assigned during core construction
private int Header_Length;
private int Disasm_Length;
private int Reg_String_Length;
private void MakeTrace(int t) private void MakeTrace(int t)
{ {
StringBuilder new_d = new StringBuilder(Disasm_Length);
StringBuilder new_r = new StringBuilder(Reg_String_Length);
LibMSX.MSX_getdisassembly(MSX_Pntr, new_d, t, Disasm_Length);
StringBuilder new_d = new StringBuilder(500); LibMSX.MSX_getregisterstate(MSX_Pntr, new_r, t, Reg_String_Length);
StringBuilder new_r = new StringBuilder(500);
LibMSX.MSX_getdisassembly(MSX_Pntr, new_d, t);
LibMSX.MSX_getregisterstate(MSX_Pntr, new_r, t);
Tracer.Put(new TraceInfo Tracer.Put(new TraceInfo
{ {

View File

@ -19,6 +19,7 @@ namespace MSXHawk
MemMap.vdp_pntr = &vdp; MemMap.vdp_pntr = &vdp;
MemMap.psg_pntr = &psg; MemMap.psg_pntr = &psg;
cpu.mem_ctrl = &MemMap; cpu.mem_ctrl = &MemMap;
vdp.INT_FLAG = &cpu.FlagI;
}; };
VDP vdp; VDP vdp;
@ -79,7 +80,11 @@ namespace MSXHawk
//vdp.ProcessOverscan(); //vdp.ProcessOverscan();
} }
} }
/*
while (cpu.TotalExecutedCycles < 211936) {
cpu.ExecuteOne();
}
*/
return MemMap.lagged; return MemMap.lagged;
} }
@ -95,48 +100,64 @@ namespace MSXHawk
} }
} }
void SetTraceCallback(void (*callback)(int)) #pragma region Tracer
void SetTraceCallback(void (*callback)(int))
{ {
cpu.TraceCallback = callback; cpu.TraceCallback = callback;
} }
void GetHeader(char* h)
{
memcpy(h, cpu.TraceHeader, *(&cpu.TraceHeader + 1) - cpu.TraceHeader);
}
int GetHeaderLength() int GetHeaderLength()
{ {
return *(&cpu.TraceHeader + 1) - cpu.TraceHeader; return 105 + 1;
} }
void GetRegisterState(char* r, int t) int GetDisasmLength()
{ {
if (t == 0) return 48 + 1;
{
memcpy(r, cpu.CPURegisterState().c_str(), cpu.CPURegisterState().length() + 1);
}
else
{
memcpy(r, cpu.No_Reg, *(&cpu.No_Reg + 1) - cpu.No_Reg);
}
} }
void GetDisassembly(char* d, int t) int GetRegStringLength()
{
return 86 + 1;
}
void GetHeader(char* h, int l)
{
memcpy(h, cpu.TraceHeader, l);
}
// the copy length l must be supplied ahead of time from GetRegStrngLength
void GetRegisterState(char* r, int t, int l)
{ {
if (t == 0) if (t == 0)
{ {
memcpy(d, cpu.CPUDisassembly().c_str(), cpu.CPUDisassembly().length() + 1); memcpy(r, cpu.CPURegisterState().c_str(), l);
}
else if (t == 1)
{
memcpy(d, cpu.NMI_event, *(&cpu.NMI_event + 1) - cpu.NMI_event);
} }
else else
{ {
memcpy(d, cpu.IRQ_event, *(&cpu.IRQ_event + 1) - cpu.IRQ_event); memcpy(r, cpu.No_Reg, l);
} }
} }
// the copy length l must be supplied ahead of time from GetDisasmLength
void GetDisassembly(char* d, int t, int l)
{
if (t == 0)
{
memcpy(d, cpu.CPUDisassembly().c_str(), l);
}
else if (t == 1)
{
memcpy(d, cpu.NMI_event, l);
}
else
{
memcpy(d, cpu.IRQ_event, l);
}
}
#pragma endregion
}; };
} }

View File

@ -46,23 +46,36 @@ MSXHAWK_EXPORT void MSX_settracecallback(MSXCore* p, void (*callback)(int)) {
p->SetTraceCallback(callback); p->SetTraceCallback(callback);
} }
// return the cpu trace header #pragma region Tracer
MSXHAWK_EXPORT void MSX_getheader(MSXCore* p, char* h) {
p->GetHeader(h);
}
// return the cpu trace header length // return the cpu trace header length
MSXHAWK_EXPORT int MSX_getheaderlength(MSXCore* p) { MSXHAWK_EXPORT int MSX_getheaderlength(MSXCore* p) {
return p->GetHeaderLength(); return p->GetHeaderLength();
} }
// return the cpu disassembly length
MSXHAWK_EXPORT int MSX_getdisasmlength(MSXCore* p) {
return p->GetDisasmLength();
}
// return the cpu register string length
MSXHAWK_EXPORT int MSX_getregstringlength(MSXCore* p) {
return p->GetRegStringLength();
}
// return the cpu trace header
MSXHAWK_EXPORT void MSX_getheader(MSXCore* p, char* h, int l) {
p->GetHeader(h, l);
}
// return the cpu register state // return the cpu register state
MSXHAWK_EXPORT void MSX_getregisterstate(MSXCore* p, char* r, int t) { MSXHAWK_EXPORT void MSX_getregisterstate(MSXCore* p, char* r, int t, int l) {
p->GetRegisterState(r, t); p->GetRegisterState(r, t, l);
} }
// return the cpu disassembly // return the cpu disassembly
MSXHAWK_EXPORT void MSX_getdisassembly(MSXCore* p, char* d, int t) { MSXHAWK_EXPORT void MSX_getdisassembly(MSXCore* p, char* d, int t, int l) {
p->GetDisassembly(d, t); p->GetDisassembly(d, t, l);
} }
#pragma endregion

View File

@ -13,7 +13,7 @@ namespace MSXHawk
#pragma region VDP #pragma region VDP
// external pointers to CPU // external pointers to CPU
bool* INT_FLAG; bool* INT_FLAG = nullptr;
// external flags to display background or sprites // external flags to display background or sprites
bool SHOW_BG, SHOW_SPRITES; bool SHOW_BG, SHOW_SPRITES;

View File

@ -118,8 +118,6 @@ namespace MSXHawk
interruptMode = value; interruptMode = value;
} }
char replacer[32] = {};
#pragma endregion #pragma endregion
#pragma region Constant Declarations #pragma region Constant Declarations
@ -339,163 +337,205 @@ namespace MSXHawk
Regs[R] = ((Regs[R] & 0x80) | temp_R); Regs[R] = ((Regs[R] & 0x80) | temp_R);
break; break;
case RD: case RD:
Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Read_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case WR: case WR:
Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Write_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case RD_INC: case RD_INC:
Read_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Read_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case RD_INC_TR_PC: case RD_INC_TR_PC:
Read_INC_TR_PC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Read_INC_TR_PC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case RD_OP: case RD_OP:
if (cur_instr[instr_pntr++] == 1) { Read_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); } if (cur_instr[instr_pntr++] == 1) { Read_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]); }
else { Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); } else { Read_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]); }
instr_pntr += 3;
switch (cur_instr[instr_pntr++]) switch (cur_instr[instr_pntr])
{ {
case ADD8: case ADD8:
ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADD8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case ADC8: case ADC8:
ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADC8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case SUB8: case SUB8:
SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); SUB8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case SBC8: case SBC8:
SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); SBC8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case AND8: case AND8:
AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); AND8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case XOR8: case XOR8:
XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); XOR8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case OR8: case OR8:
OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); OR8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case CP8: case CP8:
CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); CP8_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
case TR: case TR:
TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); TR_Func(cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
break; break;
} }
instr_pntr += 3;
break; break;
case WR_INC: case WR_INC:
Write_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Write_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case WR_DEC: case WR_DEC:
Write_DEC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Write_DEC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case WR_TR_PC: case WR_TR_PC:
Write_TR_PC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Write_TR_PC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case WR_INC_WA: case WR_INC_WA:
Write_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Write_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
Regs[W] = Regs[A]; Regs[W] = Regs[A];
break; break;
case TR: case TR:
TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); TR_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case TR16: case TR16:
TR16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); TR16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case ADD16: case ADD16:
ADD16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADD16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case ADD8: case ADD8:
ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADD8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case SUB8: case SUB8:
SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); SUB8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case ADC8: case ADC8:
ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADC8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case ADC16: case ADC16:
ADC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADC_16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case SBC8: case SBC8:
SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); SBC8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case SBC16: case SBC16:
SBC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); SBC_16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case INC16: case INC16:
INC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); INC16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case INC8: case INC8:
INC8_Func(cur_instr[instr_pntr++]); INC8_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case DEC16: case DEC16:
DEC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); DEC16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case DEC8: case DEC8:
DEC8_Func(cur_instr[instr_pntr++]); DEC8_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case RLC: case RLC:
RLC_Func(cur_instr[instr_pntr++]); RLC_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case RL: case RL:
RL_Func(cur_instr[instr_pntr++]); RL_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case RRC: case RRC:
RRC_Func(cur_instr[instr_pntr++]); RRC_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case RR: case RR:
RR_Func(cur_instr[instr_pntr++]); RR_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case CPL: case CPL:
CPL_Func(cur_instr[instr_pntr++]); CPL_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case DA: case DA:
DA_Func(cur_instr[instr_pntr++]); DA_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case SCF: case SCF:
SCF_Func(cur_instr[instr_pntr++]); SCF_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case CCF: case CCF:
CCF_Func(cur_instr[instr_pntr++]); CCF_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case AND8: case AND8:
AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); AND8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case XOR8: case XOR8:
XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); XOR8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case OR8: case OR8:
OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); OR8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case CP8: case CP8:
CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); CP8_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case SLA: case SLA:
SLA_Func(cur_instr[instr_pntr++]); SLA_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case SRA: case SRA:
SRA_Func(cur_instr[instr_pntr++]); SRA_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case SRL: case SRL:
SRL_Func(cur_instr[instr_pntr++]); SRL_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case SLL: case SLL:
SLL_Func(cur_instr[instr_pntr++]); SLL_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case BIT: case BIT:
BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); BIT_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case I_BIT: case I_BIT:
I_BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); I_BIT_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case RES: case RES:
RES_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); RES_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case SET: case SET:
SET_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); SET_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case EI: case EI:
EI_pending = 2; EI_pending = 2;
@ -512,7 +552,8 @@ namespace MSXHawk
EXCH_16_Func(L_s, H_s, L, H); EXCH_16_Func(L_s, H_s, L, H);
break; break;
case EXCH_16: case EXCH_16:
EXCH_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); EXCH_16_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case PREFIX: case PREFIX:
src_t = PRE_SRC; src_t = PRE_SRC;
@ -548,10 +589,12 @@ namespace MSXHawk
break; break;
case ASGN: case ASGN:
ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ASGN_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case ADDS: case ADDS:
ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); ADDS_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2], cur_instr[instr_pntr + 3]);
instr_pntr += 4;
break; break;
case EI_RETI: case EI_RETI:
// NOTE: This is needed for systems using multiple interrupt sources, it triggers the next interrupt // NOTE: This is needed for systems using multiple interrupt sources, it triggers the next interrupt
@ -562,31 +605,40 @@ namespace MSXHawk
IFF1 = IFF2; IFF1 = IFF2;
break; break;
case OUT: case OUT:
OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); OUT_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case OUT_INC: case OUT_INC:
OUT_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); OUT_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case IN: case IN:
IN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); IN_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case IN_INC: case IN_INC:
IN_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); IN_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case IN_A_N_INC: case IN_A_N_INC:
IN_A_N_INC_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); IN_A_N_INC_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
break; break;
case NEG: case NEG:
NEG_8_Func(cur_instr[instr_pntr++]); NEG_8_Func(cur_instr[instr_pntr]);
instr_pntr += 1;
break; break;
case INT_MODE: case INT_MODE:
interruptMode = cur_instr[instr_pntr++]; interruptMode = cur_instr[instr_pntr];
instr_pntr += 1;
break; break;
case RRD: case RRD:
RRD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); RRD_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case RLD: case RLD:
RLD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); RLD_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1]);
instr_pntr += 2;
break; break;
case SET_FL_LD_R: case SET_FL_LD_R:
DEC16_Func(C, B); DEC16_Func(C, B);
@ -666,7 +718,8 @@ namespace MSXHawk
Regs[W] = 0; Regs[W] = 0;
break; break;
case REP_OP_I: case REP_OP_I:
Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); Write_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
Ztemp4 = cur_instr[instr_pntr++]; Ztemp4 = cur_instr[instr_pntr++];
if (Ztemp4 == DEC16) if (Ztemp4 == DEC16)
@ -722,7 +775,8 @@ namespace MSXHawk
} }
break; break;
case REP_OP_O: case REP_OP_O:
OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); OUT_Func(cur_instr[instr_pntr], cur_instr[instr_pntr + 1], cur_instr[instr_pntr + 2]);
instr_pntr += 3;
Ztemp4 = cur_instr[instr_pntr++]; Ztemp4 = cur_instr[instr_pntr++];
if (Ztemp4 == DEC16) if (Ztemp4 == DEC16)
@ -4449,56 +4503,63 @@ namespace MSXHawk
#pragma region Disassemble #pragma region Disassemble
// disassemblies will also return strings of the same length
const char* TraceHeader = "Z80A: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)"; const char* TraceHeader = "Z80A: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)";
const char* NMI_event = "====NMI===="; const char* NMI_event = " ====NMI==== ";
const char* IRQ_event = "====IRQ===="; const char* IRQ_event = " ====IRQ==== ";
const char* No_Reg = "Q"; const char* No_Reg = " ";
const char* Reg_template = "AF:AAFF BC:BBCC DE:DDEE HL:HHLL Ix:IxIx Iy:IyIy SP:SPSP Cy:FEDCBA9876543210 CNP3H5ZSE";
const char* Disasm_template = "PCPC: AA BB CC DD Di Di, XXXXX ";
char replacer[32] = {};
char* val_char_1 = nullptr;
char* val_char_2 = nullptr;
int temp_reg;
void (*TraceCallback)(int); void (*TraceCallback)(int);
string CPURegisterState() string CPURegisterState()
{ {
string reg_state = " "; val_char_1 = replacer;
char* val_char = replacer;
int temp_reg = (Regs[A] << 8) + Regs[F]; string reg_state = "AF:";
sprintf_s(val_char, 5, "%04X", temp_reg); temp_reg = (Regs[A] << 8) + Regs[F];
reg_state.append(val_char, 4); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(" "); reg_state.append(val_char_1, 4);
reg_state.append(" BC:");
temp_reg = (Regs[B] << 8) + Regs[C]; temp_reg = (Regs[B] << 8) + Regs[C];
sprintf_s(val_char, 5, "%04X", temp_reg); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(val_char, 4); reg_state.append(val_char_1, 4);
reg_state.append(" ");
reg_state.append(" DE:");
temp_reg = (Regs[D] << 8) + Regs[E]; temp_reg = (Regs[D] << 8) + Regs[E];
sprintf_s(val_char, 5, "%04X", temp_reg); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(val_char, 4); reg_state.append(val_char_1, 4);
reg_state.append(" ");
reg_state.append(" HL:");
temp_reg = (Regs[H] << 8) + Regs[L]; temp_reg = (Regs[H] << 8) + Regs[L];
sprintf_s(val_char, 5, "%04X", temp_reg); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(val_char, 4); reg_state.append(val_char_1, 4);
reg_state.append(" ");
reg_state.append(" Ix:");
temp_reg = (Regs[Ixh] << 8) + Regs[Ixl]; temp_reg = (Regs[Ixh] << 8) + Regs[Ixl];
sprintf_s(val_char, 5, "%04X", temp_reg); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(val_char, 4); reg_state.append(val_char_1, 4);
reg_state.append(" ");
reg_state.append(" Iy:");
temp_reg = (Regs[Iyh] << 8) + Regs[Iyl]; temp_reg = (Regs[Iyh] << 8) + Regs[Iyl];
sprintf_s(val_char, 5, "%04X", temp_reg); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(val_char, 4); reg_state.append(val_char_1, 4);
reg_state.append(" ");
reg_state.append(" SP:");
temp_reg = (Regs[SPh] << 8) + Regs[SPl]; temp_reg = (Regs[SPh] << 8) + Regs[SPl];
sprintf_s(val_char, 5, "%04X", temp_reg); sprintf_s(val_char_1, 5, "%04X", temp_reg);
reg_state.append(val_char, 4); reg_state.append(val_char_1, 4);
reg_state.append(" ");
reg_state.append(" Cy:");
int tot_long = sprintf_s(val_char, 32, "%16u", TotalExecutedCycles); reg_state.append(val_char_1, sprintf_s(val_char_1, 32, "%16u", TotalExecutedCycles));
reg_state.append(val_char, tot_long);
reg_state.append(" "); reg_state.append(" ");
reg_state.append(FlagCget() ? "C" : "c"); reg_state.append(FlagCget() ? "C" : "c");
@ -4523,7 +4584,14 @@ namespace MSXHawk
string disasm = Disassemble(RegPCget(), bytes_read_ptr); string disasm = Disassemble(RegPCget(), bytes_read_ptr);
string byte_code = ""; string byte_code = "";
for (uint32_t i = 0; i < bytes_read; i++) val_char_1 = replacer;
sprintf_s(val_char_1, 5, "%04X", RegPCget() & 0xFFFF);
byte_code.append(val_char_1, 4);
byte_code.append(": ");
uint32_t i = 0;
for (i = 0; i < bytes_read; i++)
{ {
bank_num = bank_offset = (RegPCget() + i) & 0xFFFF; bank_num = bank_offset = (RegPCget() + i) & 0xFFFF;
bank_offset &= low_mask; bank_offset &= low_mask;
@ -4534,15 +4602,20 @@ namespace MSXHawk
string val1(val_char_1, 2); string val1(val_char_1, 2);
byte_code.append(val1); byte_code.append(val1);
if (i < (bytes_read - 1)) byte_code.append(" ");
{
byte_code.append(" ");
}
} }
while (i < 4)
{
byte_code.append(" ");
i++;
}
byte_code.append(" ");
byte_code.append(disasm); byte_code.append(disasm);
while (byte_code.length() < 32) while (byte_code.length() < 48)
{ {
byte_code.append(" "); byte_code.append(" ");
} }
@ -4565,7 +4638,7 @@ namespace MSXHawk
bank_num = (bank_num >> bank_shift) & high_mask; bank_num = (bank_num >> bank_shift) & high_mask;
addr++; addr++;
char* val_char_1 = replacer; val_char_1 = replacer;
sprintf_s(val_char_1, 5, "%02X", MemoryMap[bank_num][bank_offset]); sprintf_s(val_char_1, 5, "%02X", MemoryMap[bank_num][bank_offset]);
string val1(val_char_1, 2); string val1(val_char_1, 2);
@ -4574,7 +4647,7 @@ namespace MSXHawk
bank_num = (bank_num >> bank_shift)& high_mask; bank_num = (bank_num >> bank_shift)& high_mask;
addr++; addr++;
char* val_char_2 = replacer; val_char_2 = replacer;
sprintf_s(val_char_2, 5, "%02X", MemoryMap[bank_num][bank_offset]); sprintf_s(val_char_2, 5, "%02X", MemoryMap[bank_num][bank_offset]);
string val2(val_char_2, 2); string val2(val_char_2, 2);
@ -4592,7 +4665,7 @@ namespace MSXHawk
bank_num = (bank_num >> bank_shift)& high_mask; bank_num = (bank_num >> bank_shift)& high_mask;
addr++; addr++;
char* val_char_1 = replacer; val_char_1 = replacer;
sprintf_s(val_char_1, 5, "%02X", MemoryMap[bank_num][bank_offset]); sprintf_s(val_char_1, 5, "%02X", MemoryMap[bank_num][bank_offset]);
string val1(val_char_1, 2); string val1(val_char_1, 2);
@ -4609,7 +4682,7 @@ namespace MSXHawk
bank_num = (bank_num >> bank_shift)& high_mask; bank_num = (bank_num >> bank_shift)& high_mask;
addr++; addr++;
char* val_char_1 = replacer; val_char_1 = replacer;
sprintf_s(val_char_1, 5, "%u", MemoryMap[bank_num][bank_offset]); sprintf_s(val_char_1, 5, "%u", MemoryMap[bank_num][bank_offset]);
string val1(val_char_1, 2); string val1(val_char_1, 2);
@ -4627,7 +4700,7 @@ namespace MSXHawk
int8_t temp = (int8_t)MemoryMap[bank_num][bank_offset]; int8_t temp = (int8_t)MemoryMap[bank_num][bank_offset];
char* val_char_1 = replacer; val_char_1 = replacer;
sprintf_s(val_char_1, 5, "%d", temp); sprintf_s(val_char_1, 5, "%d", temp);
string val1(val_char_1, 3); string val1(val_char_1, 3);