fix some embarrassing bugs in new snes interop. maybe biz will be more stable now.
This commit is contained in:
parent
16d67e6805
commit
f108673449
|
@ -27,8 +27,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
|
|
||||||
CommStruct* comm;
|
CommStruct* comm;
|
||||||
MessageApi Message;
|
MessageApi Message;
|
||||||
BufferApi CopyBuffer; //TODO: consider making private and wrapping
|
BufferApi _copyBuffer; //TODO: consider making private and wrapping
|
||||||
BufferApi SetBuffer; //TODO: consider making private and wrapping
|
BufferApi _setBuffer; //TODO: consider making private and wrapping
|
||||||
|
|
||||||
public LibsnesApi(string dllPath)
|
public LibsnesApi(string dllPath)
|
||||||
{
|
{
|
||||||
|
@ -36,8 +36,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
instanceDll = new InstanceDll(dllPath);
|
instanceDll = new InstanceDll(dllPath);
|
||||||
var dllinit = (DllInit)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("DllInit"), typeof(DllInit));
|
var dllinit = (DllInit)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("DllInit"), typeof(DllInit));
|
||||||
Message = (MessageApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("Message"), typeof(MessageApi));
|
Message = (MessageApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("Message"), typeof(MessageApi));
|
||||||
CopyBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("CopyBuffer"), typeof(BufferApi));
|
_copyBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("CopyBuffer"), typeof(BufferApi));
|
||||||
SetBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("SetBuffer"), typeof(BufferApi));
|
_setBuffer = (BufferApi)Marshal.GetDelegateForFunctionPointer(instanceDll.GetProcAddress("SetBuffer"), typeof(BufferApi));
|
||||||
|
|
||||||
comm = (CommStruct*)dllinit().ToPointer();
|
comm = (CommStruct*)dllinit().ToPointer();
|
||||||
}
|
}
|
||||||
|
@ -52,33 +52,50 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
DeallocatedMemoryBlocks.Clear();
|
DeallocatedMemoryBlocks.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyString(string str)
|
/// <summary>
|
||||||
|
/// Copy an ascii string into libretro. It keeps the copy.
|
||||||
|
/// </summary>
|
||||||
|
public void CopyAscii(int id, string str)
|
||||||
{
|
{
|
||||||
fixed (char* cp = str)
|
fixed (byte* cp = System.Text.Encoding.ASCII.GetBytes(str+"\0"))
|
||||||
CopyBuffer(0, cp, str.Length + 1);
|
_copyBuffer(id, cp, str.Length + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CopyBytes(byte[] bytes)
|
/// <summary>
|
||||||
|
/// Copy a buffer into libretro. It keeps the copy.
|
||||||
|
/// </summary>
|
||||||
|
public void CopyBytes(int id, byte[] bytes)
|
||||||
{
|
{
|
||||||
fixed (byte* bp = bytes)
|
fixed (byte* bp = bytes)
|
||||||
CopyBuffer(0, bp, bytes.Length);
|
_copyBuffer(id, bp, bytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAscii(string str)
|
/// <summary>
|
||||||
|
/// Locks a buffer and sets it into libretro. You must pass a delegate to be executed while that buffer is locked.
|
||||||
|
/// This is meant to be used for avoiding a memcpy for large roms (which the core is then just going to memcpy again on its own)
|
||||||
|
/// The memcpy has to happen at some point (libretro semantics specify [not literally, the docs dont say] that the core should finish using the buffer before its init returns)
|
||||||
|
/// but this limits it to once.
|
||||||
|
/// Moreover, this keeps the c++ side from having to free strings when they're no longer used (and memory management is trickier there, so we try to avoid it)
|
||||||
|
/// </summary>
|
||||||
|
public void SetBytes(int id, byte[] bytes, Action andThen)
|
||||||
{
|
{
|
||||||
fixed (char* cp = str)
|
fixed (byte* bp = bytes)
|
||||||
SetBuffer(0, cp, str.Length + 1);
|
{
|
||||||
|
_setBuffer(id, bp, bytes.Length);
|
||||||
|
andThen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetBytes(byte[] bytes)
|
/// <summary>
|
||||||
|
/// see SetBytes
|
||||||
|
/// </summary>
|
||||||
|
public void SetAscii(int id, string str, Action andThen)
|
||||||
{
|
{
|
||||||
fixed (byte* bp = bytes)
|
fixed (byte* cp = System.Text.Encoding.ASCII.GetBytes(str+"\0"))
|
||||||
SetBuffer(0, bp, bytes.Length);
|
{
|
||||||
}
|
_setBuffer(id, cp, str.Length + 1);
|
||||||
public void SetBytes2(byte[] bytes)
|
andThen();
|
||||||
{
|
}
|
||||||
fixed (byte* bp = bytes)
|
|
||||||
SetBuffer(1, bp, bytes.Length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action<uint> ReadHook, ExecHook;
|
public Action<uint> ReadHook, ExecHook;
|
||||||
|
@ -127,7 +144,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
public delegate void snes_trace_t(string msg);
|
public delegate void snes_trace_t(string msg);
|
||||||
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct CPURegs
|
public struct CPURegs
|
||||||
{
|
{
|
||||||
public uint pc;
|
public uint pc;
|
||||||
|
@ -137,7 +153,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
public byte sp, dp, db, mdr;
|
public byte sp, dp, db, mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct LayerEnables
|
public struct LayerEnables
|
||||||
{
|
{
|
||||||
byte _BG1_Prio0, _BG1_Prio1;
|
byte _BG1_Prio0, _BG1_Prio1;
|
||||||
|
@ -161,7 +176,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
public bool Obj_Prio3 { get { return _Obj_Prio3 != 0; } set { _Obj_Prio3 = (byte)(value ? 1 : 0); } }
|
public bool Obj_Prio3 { get { return _Obj_Prio3 != 0; } set { _Obj_Prio3 = (byte)(value ? 1 : 0); } }
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
struct CommStruct
|
struct CommStruct
|
||||||
{
|
{
|
||||||
//the cmd being executed
|
//the cmd being executed
|
||||||
|
@ -185,8 +199,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
public fixed int inports[2];
|
public fixed int inports[2];
|
||||||
|
|
||||||
//this should always be used in pairs
|
//this should always be used in pairs
|
||||||
public void* buf0, buf1;
|
public fixed uint buf[3]; //ACTUALLY A POINTER but can't marshal it :(
|
||||||
public int buf_size0, buf_size1;
|
public fixed int buf_size[3];
|
||||||
|
|
||||||
//bleck. this is a long so that it can be a 32/64bit pointer
|
//bleck. this is a long so that it can be a 32/64bit pointer
|
||||||
public fixed long cdl_ptr[4];
|
public fixed long cdl_ptr[4];
|
||||||
|
|
|
@ -8,8 +8,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
{
|
{
|
||||||
public bool CMD_serialize(IntPtr data, int size)
|
public bool CMD_serialize(IntPtr data, int size)
|
||||||
{
|
{
|
||||||
comm->buf0 = data.ToPointer();
|
comm->buf[0] = (uint)data.ToInt32();
|
||||||
comm->buf_size0 = size;
|
comm->buf_size[0] = size;
|
||||||
Message(eMessage.eMessage_CMD_serialize);
|
Message(eMessage.eMessage_CMD_serialize);
|
||||||
WaitForCMD();
|
WaitForCMD();
|
||||||
bool ret = comm->GetBool();
|
bool ret = comm->GetBool();
|
||||||
|
@ -29,8 +29,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
|
|
||||||
public bool CMD_unserialize(IntPtr data, int size)
|
public bool CMD_unserialize(IntPtr data, int size)
|
||||||
{
|
{
|
||||||
comm->buf0 = data.ToPointer();
|
comm->buf[0] = (uint)data.ToInt32();
|
||||||
comm->buf_size0 = size;
|
comm->buf_size[0] = size;
|
||||||
Message(eMessage.eMessage_CMD_unserialize);
|
Message(eMessage.eMessage_CMD_unserialize);
|
||||||
WaitForCMD();
|
WaitForCMD();
|
||||||
bool ret = comm->GetBool();
|
bool ret = comm->GetBool();
|
||||||
|
@ -61,28 +61,28 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
|
|
||||||
public bool CMD_load_cartridge_super_game_boy(string rom_xml, byte[] rom_data, uint rom_size, byte[] dmg_data)
|
public bool CMD_load_cartridge_super_game_boy(string rom_xml, byte[] rom_data, uint rom_size, byte[] dmg_data)
|
||||||
{
|
{
|
||||||
fixed (char* xmlcp = rom_xml)
|
SetAscii(0, rom_xml, () =>
|
||||||
{
|
SetBytes(1, rom_data, () =>
|
||||||
comm->str = (sbyte*)xmlcp;
|
SetBytes(2, dmg_data, () =>
|
||||||
SetBytes(rom_data);
|
{
|
||||||
SetBytes2(dmg_data);
|
Message(eMessage.eMessage_CMD_load_cartridge_sgb);
|
||||||
Message(eMessage.eMessage_CMD_load_cartridge_sgb);
|
WaitForCMD();
|
||||||
WaitForCMD();
|
})
|
||||||
return comm->GetBool();
|
)
|
||||||
}
|
);
|
||||||
|
return comm->GetBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CMD_load_cartridge_normal(byte[] rom_xml, byte[] rom_data)
|
public bool CMD_load_cartridge_normal(byte[] rom_xml, byte[] rom_data)
|
||||||
{
|
{
|
||||||
string xml = rom_xml==null?null:System.Text.Encoding.ASCII.GetString(rom_xml);
|
string xml = rom_xml==null?null:System.Text.Encoding.ASCII.GetString(rom_xml);
|
||||||
fixed (char* xmlcp = xml)
|
SetAscii(0, xml??"", () =>
|
||||||
{
|
SetBytes(1, rom_data, () => {
|
||||||
comm->str = (sbyte*)xmlcp;
|
Message(eMessage.eMessage_CMD_load_cartridge_normal);
|
||||||
SetBytes(rom_data);
|
WaitForCMD();
|
||||||
Message(eMessage.eMessage_CMD_load_cartridge_normal);
|
})
|
||||||
WaitForCMD();
|
);
|
||||||
return comm->GetBool();
|
return comm->GetBool();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CMD_term()
|
public void CMD_term()
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
string ret = hint;
|
string ret = hint;
|
||||||
if (pathRequest != null)
|
if (pathRequest != null)
|
||||||
hint = pathRequest(slot, hint);
|
hint = pathRequest(slot, hint);
|
||||||
SetAscii(hint);
|
CopyAscii(0, hint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eMessage.eMessage_SIG_trace_callback:
|
case eMessage.eMessage_SIG_trace_callback:
|
||||||
|
@ -109,7 +109,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
||||||
|
|
||||||
comm->ptr = smb.Ptr;
|
comm->ptr = smb.Ptr;
|
||||||
SharedMemoryBlocks[smb.Name] = smb;
|
SharedMemoryBlocks[smb.Name] = smb;
|
||||||
CopyString(smb.BlockName);
|
CopyAscii(0, smb.BlockName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eMessage.eMessage_SIG_freeSharedMemory:
|
case eMessage.eMessage_SIG_freeSharedMemory:
|
||||||
|
|
|
@ -150,8 +150,8 @@ struct CommStruct
|
||||||
SNES::Input::Device inports[2];
|
SNES::Input::Device inports[2];
|
||||||
|
|
||||||
//always used in pairs
|
//always used in pairs
|
||||||
void* buf[2];
|
void* buf[3];
|
||||||
int32 buf_size[2];
|
int32 buf_size[3];
|
||||||
|
|
||||||
int64 cdl_ptr[4];
|
int64 cdl_ptr[4];
|
||||||
int32 cdl_size[4];
|
int32 cdl_size[4];
|
||||||
|
@ -167,11 +167,7 @@ struct CommStruct
|
||||||
|
|
||||||
//private stuff
|
//private stuff
|
||||||
void* privbuf[2]; //TODO remember to tidy this..
|
void* privbuf[2]; //TODO remember to tidy this..
|
||||||
void SetString(const char* str)
|
|
||||||
{
|
|
||||||
if (privbuf[0]) free(privbuf[0]);
|
|
||||||
buf[0] = privbuf[0] = strdup(str);
|
|
||||||
}
|
|
||||||
void CopyBuffer(int id, void* ptr, int32 size)
|
void CopyBuffer(int id, void* ptr, int32 size)
|
||||||
{
|
{
|
||||||
if (privbuf[id]) free(privbuf[id]);
|
if (privbuf[id]) free(privbuf[id]);
|
||||||
|
@ -182,13 +178,12 @@ struct CommStruct
|
||||||
|
|
||||||
void SetBuffer(int id, void* ptr, int32 size)
|
void SetBuffer(int id, void* ptr, int32 size)
|
||||||
{
|
{
|
||||||
|
if (privbuf[id]) free(privbuf[id]);
|
||||||
|
privbuf[id] = nullptr;
|
||||||
buf[id] = ptr;
|
buf[id] = ptr;
|
||||||
buf_size[id] = size;
|
buf_size[id] = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct {
|
|
||||||
} strings;
|
|
||||||
|
|
||||||
|
|
||||||
} comm;
|
} comm;
|
||||||
|
|
||||||
|
@ -202,7 +197,8 @@ uint16_t audiobuffer[AUDIOBUFFER_SIZE];
|
||||||
int audiobuffer_idx = 0;
|
int audiobuffer_idx = 0;
|
||||||
Action CMD_cb;
|
Action CMD_cb;
|
||||||
|
|
||||||
void BREAK(eMessage msg) {
|
void BREAK(eMessage msg)
|
||||||
|
{
|
||||||
comm.status = eStatus_BRK;
|
comm.status = eStatus_BRK;
|
||||||
comm.reason = msg;
|
comm.reason = msg;
|
||||||
co_emu_suspended = co_active();
|
co_emu_suspended = co_active();
|
||||||
|
@ -273,7 +269,7 @@ const char* snes_path_request(int slot, const char* hint)
|
||||||
comm.slot = slot;
|
comm.slot = slot;
|
||||||
comm.str= (char *)hint;
|
comm.str= (char *)hint;
|
||||||
BREAK(eMessage_SIG_path_request);
|
BREAK(eMessage_SIG_path_request);
|
||||||
return (const char*)comm.buf;
|
return (const char*)comm.buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void snes_scanlineStart(int line)
|
void snes_scanlineStart(int line)
|
||||||
|
@ -358,7 +354,9 @@ static void Analyze()
|
||||||
|
|
||||||
void CMD_LoadCartridgeNormal()
|
void CMD_LoadCartridgeNormal()
|
||||||
{
|
{
|
||||||
bool ret = snes_load_cartridge_normal(comm.str, (const uint8_t*)comm.buf[0], comm.buf_size[0]);
|
const char* xml = (const char*)comm.buf[0];
|
||||||
|
if(!xml[0]) xml = nullptr;
|
||||||
|
bool ret = snes_load_cartridge_normal(xml, (const uint8_t*)comm.buf[1], comm.buf_size[1]);
|
||||||
comm.value = ret?1:0;
|
comm.value = ret?1:0;
|
||||||
|
|
||||||
if(ret)
|
if(ret)
|
||||||
|
@ -367,7 +365,7 @@ void CMD_LoadCartridgeNormal()
|
||||||
|
|
||||||
void CMD_LoadCartridgeSGB()
|
void CMD_LoadCartridgeSGB()
|
||||||
{
|
{
|
||||||
bool ret = snes_load_cartridge_super_game_boy(comm.str, (const u8*)comm.buf[0], comm.buf_size[0], nullptr, (const u8*)comm.buf[1], comm.buf_size[1]);
|
bool ret = snes_load_cartridge_super_game_boy((const char*)comm.buf[0], (const u8*)comm.buf[1], comm.buf_size[1], nullptr, (const u8*)comm.buf[2], comm.buf_size[2]);
|
||||||
comm.value = ret ? 1 : 0;
|
comm.value = ret ? 1 : 0;
|
||||||
|
|
||||||
if(ret)
|
if(ret)
|
||||||
|
@ -382,7 +380,7 @@ void CMD_init()
|
||||||
SNES::input.connect(SNES::Controller::Port2, comm.inports[1]);
|
SNES::input.connect(SNES::Controller::Port2, comm.inports[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMD_serialize()
|
void CMD_Serialize()
|
||||||
{
|
{
|
||||||
int size = comm.buf_size[0];
|
int size = comm.buf_size[0];
|
||||||
char* buf = (char*)comm.buf[0];
|
char* buf = (char*)comm.buf[0];
|
||||||
|
@ -390,7 +388,7 @@ void CMD_serialize()
|
||||||
comm.value = ret ? 1 : 0;
|
comm.value = ret ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMD_unserialize()
|
void CMD_Unserialize()
|
||||||
{
|
{
|
||||||
int size = comm.buf_size[0];
|
int size = comm.buf_size[0];
|
||||||
char* buf = (char*)comm.buf[0];
|
char* buf = (char*)comm.buf[0];
|
||||||
|
@ -398,7 +396,7 @@ void CMD_unserialize()
|
||||||
comm.value = ret ? 1 : 0;
|
comm.value = ret ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void snes_run()
|
static void CMD_Run()
|
||||||
{
|
{
|
||||||
do_SIG_audio_flush();
|
do_SIG_audio_flush();
|
||||||
|
|
||||||
|
@ -523,9 +521,9 @@ const Action kHandlers_CMD[] = {
|
||||||
CMD_init,
|
CMD_init,
|
||||||
snes_power,
|
snes_power,
|
||||||
snes_reset,
|
snes_reset,
|
||||||
snes_run,
|
CMD_Run,
|
||||||
CMD_serialize,
|
CMD_Serialize,
|
||||||
CMD_unserialize,
|
CMD_Unserialize,
|
||||||
CMD_LoadCartridgeNormal,
|
CMD_LoadCartridgeNormal,
|
||||||
CMD_LoadCartridgeSGB,
|
CMD_LoadCartridgeSGB,
|
||||||
snes_term,
|
snes_term,
|
||||||
|
@ -580,6 +578,8 @@ BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVO
|
||||||
|
|
||||||
extern "C" dllexport void* __cdecl DllInit()
|
extern "C" dllexport void* __cdecl DllInit()
|
||||||
{
|
{
|
||||||
|
memset(&comm,0,sizeof(comm));
|
||||||
|
|
||||||
//make a coroutine thread to run the emulation in. we'll switch back to this cothread when communicating with the frontend
|
//make a coroutine thread to run the emulation in. we'll switch back to this cothread when communicating with the frontend
|
||||||
co_control = co_active();
|
co_control = co_active();
|
||||||
co_emu = co_create(65536 * sizeof(void*), new_emuthread);
|
co_emu = co_create(65536 * sizeof(void*), new_emuthread);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue