psx - rework disassembler and add trace logger
This commit is contained in:
parent
f8b0262742
commit
877e2dde81
|
@ -17,6 +17,7 @@ using System.IO;
|
|||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common;
|
||||
|
||||
|
@ -77,6 +78,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
static Octoshock CurrOctoshockCore;
|
||||
|
||||
IntPtr psx;
|
||||
TraceBuffer tracer = new TraceBuffer();
|
||||
|
||||
bool disposed = false;
|
||||
public void Dispose()
|
||||
|
@ -459,7 +461,15 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
};
|
||||
OctoshockDll.shock_SetRenderOptions(psx, ref ropts);
|
||||
|
||||
//prep tracer
|
||||
if (tracer.Enabled)
|
||||
OctoshockDll.shock_SetTraceCallback(psx, IntPtr.Zero, ShockTraceCallback);
|
||||
else
|
||||
OctoshockDll.shock_SetTraceCallback(psx, IntPtr.Zero, null);
|
||||
|
||||
//------------------------
|
||||
OctoshockDll.shock_Step(psx, OctoshockDll.eShockStep.Frame);
|
||||
//------------------------
|
||||
|
||||
//what happens to sound in this case?
|
||||
if (render == false) return;
|
||||
|
@ -932,8 +942,13 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
OctoshockDll.shock_SetRegister_CPU(psx, index, (uint)value);
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public ITracer Tracer { get { throw new NotImplementedException(); } }
|
||||
public ITracer Tracer { get { return tracer; } }
|
||||
|
||||
public int ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis)
|
||||
{
|
||||
Tracer.Put(dis);
|
||||
return OctoshockDll.SHOCK_OK;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public IMemoryCallbackSystem MemoryCallbacks { get { throw new NotImplementedException(); } }
|
||||
|
|
|
@ -83,6 +83,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
public const int SHOCK_ERROR = -1;
|
||||
public const int SHOCK_NOCANDO = -2;
|
||||
public const int SHOCK_INVALID_ADDRESS = -3;
|
||||
public const int SHOCK_OVERFLOW = -4;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ShockDiscInfo
|
||||
|
@ -150,12 +151,18 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
public TextStateFPtrs ff;
|
||||
};
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate int ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate int ShockDisc_ReadTOC(IntPtr opaque, ShockTOC* read_target, ShockTOCTrack* tracks101);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate int ShockDisc_ReadLBA(IntPtr opaque, int lba, void* dst);
|
||||
|
||||
[DllImport(dd, CallingConvention = cc)]
|
||||
public static extern int shock_Util_DisassembleMIPS(uint PC, uint instr, IntPtr outbuf, int buflen);
|
||||
|
||||
[DllImport(dd, CallingConvention = cc)]
|
||||
public static extern int shock_CreateDisc(out IntPtr outDisc, IntPtr Opaque, int lbaCount, ShockDisc_ReadTOC ReadTOC, ShockDisc_ReadLBA ReadLBA2448, bool suppliesDeinterleavedSubcode);
|
||||
|
||||
|
@ -165,6 +172,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
[DllImport(dd, CallingConvention = cc)]
|
||||
public static extern int shock_AnalyzeDisc(IntPtr disc, out ShockDiscInfo info);
|
||||
|
||||
|
||||
|
||||
[DllImport(dd, CallingConvention = cc)]
|
||||
public static extern int shock_Create(out IntPtr psx, eRegion region, void* firmware512k);
|
||||
|
||||
|
@ -230,5 +239,8 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
|
||||
[DllImport(dd, CallingConvention = cc)]
|
||||
public static extern int shock_SetRegister_CPU(IntPtr psx, int index, uint value);
|
||||
|
||||
[DllImport(dd, CallingConvention = cc)]
|
||||
public static extern int shock_SetTraceCallback(IntPtr psx, IntPtr opaque, ShockTraceCallback callback);
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -19,6 +19,10 @@
|
|||
#include "cpu.h"
|
||||
#include "gte.h"
|
||||
|
||||
//not very organized, is it
|
||||
void* g_ShockTraceCallbackOpaque = NULL;
|
||||
ShockCallback_Trace g_ShockTraceCallback = NULL;
|
||||
|
||||
/* TODO
|
||||
Make sure load delays are correct.
|
||||
|
||||
|
@ -595,6 +599,15 @@ pscpu_timestamp_t PS_CPU::RunReal(pscpu_timestamp_t timestamp_in)
|
|||
#define JTYPE uint32_t target = instr & ((1 << 26) - 1); /*printf(" target=(%08x) ", target);*/
|
||||
#define RTYPE uint32_t rs MDFN_NOWARN_UNUSED = (instr >> 21) & 0x1F; uint32_t rt MDFN_NOWARN_UNUSED = (instr >> 16) & 0x1F; uint32_t rd MDFN_NOWARN_UNUSED = (instr >> 11) & 0x1F; uint32_t shamt MDFN_NOWARN_UNUSED = (instr >> 6) & 0x1F; /*printf(" rs=%02x(%08x), rt=%02x(%08x), rd=%02x(%08x) ", rs, GPR[rs], rt, GPR[rt], rd, GPR[rd]);*/
|
||||
|
||||
{
|
||||
if(g_ShockTraceCallback)
|
||||
{
|
||||
char tmp[100];
|
||||
shock_Util_DisassembleMIPS(PC, instr, tmp, 100);
|
||||
g_ShockTraceCallback(g_ShockTraceCallbackOpaque, PC, instr, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
#include "cpu_bigswitch.inc"
|
||||
#else
|
||||
|
|
|
@ -1,32 +1,114 @@
|
|||
/* Mednafen - Multi-system Emulator
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "psx.h"
|
||||
|
||||
#define trio_snprintf snprintf
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
//NOTE - this class was hand-crafted for octoshock. it wasn't tested very well, but its a little more tricksy than i'd like
|
||||
class BufferAppender
|
||||
{
|
||||
public:
|
||||
BufferAppender(void* _buf, size_t _buflen)
|
||||
: buf((char*)_buf)
|
||||
, buflen(_buflen)
|
||||
, ofs(0)
|
||||
, overflow(false)
|
||||
{
|
||||
}
|
||||
|
||||
void append(const char* str)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
char c = *str++;
|
||||
if(c == 0) break;
|
||||
append(1,c);
|
||||
}
|
||||
}
|
||||
|
||||
void append(size_t n, char c)
|
||||
{
|
||||
size_t remain = buflen-ofs;
|
||||
if(remain==0) return;
|
||||
size_t todo = n;
|
||||
if(todo > remain)
|
||||
todo = remain;
|
||||
for(size_t i=0; i<todo; i++)
|
||||
buf[ofs++] = c;
|
||||
terminate();
|
||||
}
|
||||
|
||||
void format(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
int remain = buflen-ofs;
|
||||
if(remain>0)
|
||||
{
|
||||
int done = vsnprintf(buf,remain,fmt,ap);
|
||||
va_end(ap);
|
||||
if(done>=0)
|
||||
{
|
||||
ofs += done;
|
||||
}
|
||||
}
|
||||
//make sure we stay null terminated, because msvc _snprintf is a piece of shit and can fill our buffer completely, among other flaws
|
||||
terminate();
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return ofs;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
ofs = 0;
|
||||
overflow = false;
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
printf(buf);
|
||||
}
|
||||
|
||||
bool isOverflow() const { return overflow; }
|
||||
|
||||
private:
|
||||
char* buf;
|
||||
size_t buflen;
|
||||
size_t ofs;
|
||||
bool overflow;
|
||||
|
||||
void terminate()
|
||||
{
|
||||
if(ofs<buflen)
|
||||
buf[ofs] = 0;
|
||||
else
|
||||
{
|
||||
buf[ofs-1] = 0;
|
||||
overflow = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct OpEntry
|
||||
{
|
||||
|
@ -212,9 +294,11 @@ static OpEntry ops[] =
|
|||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
std::string DisassembleMIPS(uint32 PC, uint32 instr)
|
||||
EW_EXPORT s32 shock_Util_DisassembleMIPS(u32 PC, u32 instr, void* outbuf, s32 buflen)
|
||||
{
|
||||
std::string ret = "UNKNOWN";
|
||||
BufferAppender ret(outbuf,buflen);
|
||||
ret.append("UNKNOWN");
|
||||
|
||||
unsigned int rs = (instr >> 21) & 0x1F;
|
||||
unsigned int rt = (instr >> 16) & 0x1F;
|
||||
unsigned int rd = (instr >> 11) & 0x1F;
|
||||
|
@ -277,23 +361,27 @@ std::string DisassembleMIPS(uint32 PC, uint32 instr)
|
|||
char s_c[16];
|
||||
char s_C[16];
|
||||
|
||||
trio_snprintf(s_a, sizeof(s_a), "%d", shamt);
|
||||
//---------------------
|
||||
//TODO - this section only as needed (mask in opcode?)
|
||||
snprintf(s_a, sizeof(s_a), "%d", shamt);
|
||||
|
||||
if(immediate < 0)
|
||||
trio_snprintf(s_i, sizeof(s_i), "%d", immediate);
|
||||
snprintf(s_i, sizeof(s_i), "%d", immediate);
|
||||
else
|
||||
trio_snprintf(s_i, sizeof(s_i), "0x%04x", (uint32)immediate);
|
||||
snprintf(s_i, sizeof(s_i), "0x%04x", (uint32)immediate);
|
||||
|
||||
trio_snprintf(s_z, sizeof(s_z), "0x%04x", immediate_ze);
|
||||
snprintf(s_z, sizeof(s_z), "0x%04x", immediate_ze);
|
||||
|
||||
trio_snprintf(s_p, sizeof(s_p), "0x%08x", PC + 4 + (immediate << 2));
|
||||
snprintf(s_p, sizeof(s_p), "0x%08x", PC + 4 + (immediate << 2));
|
||||
|
||||
trio_snprintf(s_P, sizeof(s_P), "0x%08x", ((PC + 4) & 0xF0000000) | (jt << 2));
|
||||
snprintf(s_P, sizeof(s_P), "0x%08x", ((PC + 4) & 0xF0000000) | (jt << 2));
|
||||
|
||||
trio_snprintf(s_c, sizeof(s_c), "CPR%d", rd);
|
||||
trio_snprintf(s_C, sizeof(s_C), "CCR%d", rd);
|
||||
snprintf(s_c, sizeof(s_c), "CPR%d", rd);
|
||||
snprintf(s_C, sizeof(s_C), "CCR%d", rd);
|
||||
//----------------------
|
||||
|
||||
ret = std::string(op->mnemonic);
|
||||
ret.clear();
|
||||
ret.append(op->mnemonic);
|
||||
ret.append(10 - ret.size(), ' ');
|
||||
|
||||
for(unsigned int i = 0; i < strlen(op->format); i++)
|
||||
|
@ -309,27 +397,27 @@ std::string DisassembleMIPS(uint32 PC, uint32 instr)
|
|||
if(!strncmp(&op->format[i], "#sf#", 4))
|
||||
{
|
||||
i += 3;
|
||||
trio_snprintf(as, 16, "sf=%d", (int)(bool)(instr & (1 << 19)));
|
||||
snprintf(as, 16, "sf=%d", (int)(bool)(instr & (1 << 19)));
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#mx#", 4))
|
||||
{
|
||||
i += 3;
|
||||
trio_snprintf(as, 16, "mx=%d", (instr >> 17) & 0x3);
|
||||
snprintf(as, 16, "mx=%d", (instr >> 17) & 0x3);
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#v#", 3))
|
||||
{
|
||||
i += 2;
|
||||
trio_snprintf(as, 16, "v=%d", (instr >> 15) & 0x3);
|
||||
snprintf(as, 16, "v=%d", (instr >> 15) & 0x3);
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#cv#", 4))
|
||||
{
|
||||
i += 3;
|
||||
trio_snprintf(as, 16, "cv=%d", (instr >> 13) & 0x3);
|
||||
snprintf(as, 16, "cv=%d", (instr >> 13) & 0x3);
|
||||
}
|
||||
else if(!strncmp(&op->format[i], "#lm#", 4))
|
||||
{
|
||||
i += 3;
|
||||
trio_snprintf(as, 16, "lm=%d", (int)(bool)(instr & (1 << 10)));
|
||||
snprintf(as, 16, "lm=%d", (int)(bool)(instr & (1 << 10)));
|
||||
}
|
||||
ret.append(as);
|
||||
}
|
||||
|
@ -338,7 +426,7 @@ std::string DisassembleMIPS(uint32 PC, uint32 instr)
|
|||
{
|
||||
char s_F[16];
|
||||
|
||||
trio_snprintf(s_F, 16, "0x%07x", instr & 0x1FFFFFF);
|
||||
snprintf(s_F, 16, "0x%07x", instr & 0x1FFFFFF);
|
||||
ret.append(s_F);
|
||||
}
|
||||
break;
|
||||
|
@ -409,8 +497,9 @@ std::string DisassembleMIPS(uint32 PC, uint32 instr)
|
|||
op++;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
if(ret.isOverflow())
|
||||
return SHOCK_OVERFLOW;
|
||||
else return SHOCK_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include "emuware/emuware.h"
|
||||
#include <string>
|
||||
|
||||
namespace MDFN_IEN_PSX
|
||||
{
|
||||
|
||||
std::string DisassembleMIPS(uint32 PC, uint32 instr);
|
||||
|
||||
}
|
||||
EW_EXPORT s32 shock_Util_DisassembleMIPS(u32 PC, u32 instr, void* outbuf, s32 buflen);
|
||||
|
|
|
@ -2511,3 +2511,15 @@ EW_EXPORT s32 shock_SetRenderOptions(void* pxs, ShockRenderOptions* opts)
|
|||
s_ShockConfig.opts = *opts;
|
||||
return SHOCK_OK;
|
||||
}
|
||||
|
||||
extern void* g_ShockTraceCallbackOpaque;
|
||||
extern ShockCallback_Trace g_ShockTraceCallback;
|
||||
|
||||
//Sets the callback to be used for CPU tracing
|
||||
EW_EXPORT s32 shock_SetTraceCallback(void* psx, void* opaque, ShockCallback_Trace callback)
|
||||
{
|
||||
g_ShockTraceCallbackOpaque = opaque;
|
||||
g_ShockTraceCallback = callback;
|
||||
|
||||
return SHOCK_OK;
|
||||
}
|
|
@ -186,6 +186,7 @@ enum eShockMemcardTransaction
|
|||
#define SHOCK_ERROR -1
|
||||
#define SHOCK_NOCANDO -2
|
||||
#define SHOCK_INVALID_ADDRESS -3
|
||||
#define SHOCK_OVERFLOW -4
|
||||
|
||||
struct ShockTOCTrack
|
||||
{
|
||||
|
@ -216,6 +217,9 @@ struct ShockRegisters_CPU
|
|||
typedef s32 (*ShockDisc_ReadTOC)(void* opaque, ShockTOC *read_target, ShockTOCTrack tracks[100 + 1]);
|
||||
typedef s32 (*ShockDisc_ReadLBA)(void* opaque, s32 lba, void* dst);
|
||||
|
||||
//The callback to be issued for traces
|
||||
typedef s32 (*ShockCallback_Trace)(void* opaque, u32 PC, u32 inst, const char* msg);
|
||||
|
||||
class ShockDiscRef
|
||||
{
|
||||
public:
|
||||
|
@ -361,3 +365,6 @@ EW_EXPORT s32 shock_GetRegisters_CPU(void* psx, ShockRegisters_CPU* buffer);
|
|||
|
||||
//Sets a CPU register. Rather than have an enum for the registers, lets just use the index (not offset) within the struct
|
||||
EW_EXPORT s32 shock_SetRegister_CPU(void* psx, s32 index, u32 value);
|
||||
|
||||
//Sets the callback to be used for CPU tracing
|
||||
EW_EXPORT s32 shock_SetTraceCallback(void* psx, void* opaque, ShockCallback_Trace callback);
|
||||
|
|
Loading…
Reference in New Issue