Implement memory callbacks for the new bsnes core (#2797)
* Actually working callbacks now actually work after natt's changes * Set whether memory hooks exist every frame to prevent unnecessary function calls if not
This commit is contained in:
parent
47c8d4f6e8
commit
cc38f4bcba
Binary file not shown.
|
@ -21,6 +21,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
public abstract void snes_set_layer_enables(ref BsnesApi.LayerEnables layerEnables);
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void snes_set_trace_enabled(bool enabled);
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract void snes_set_hooks_enabled(bool readHookEnabled, bool writeHookEnabled, bool executeHookEnabled);
|
||||
|
||||
[BizImport(CallingConvention.Cdecl)]
|
||||
public abstract BsnesApi.SNES_REGION snes_get_region();
|
||||
|
@ -150,6 +152,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
public delegate void snes_audio_sample_t(short left, short right);
|
||||
public delegate string snes_path_request_t(int slot, string hint, bool required);
|
||||
public delegate void snes_trace_t(string disassembly, string register_info);
|
||||
public delegate void snes_read_hook_t(uint address);
|
||||
public delegate void snes_write_hook_t(uint address, byte value);
|
||||
public delegate void snes_exec_hook_t(uint address);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CpuRegisters
|
||||
|
@ -193,7 +198,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
public snes_video_frame_t videoFrameCb;
|
||||
public snes_audio_sample_t audioSampleCb;
|
||||
public snes_path_request_t pathRequestCb;
|
||||
public snes_trace_t snesTraceCb;
|
||||
public snes_trace_t traceCb;
|
||||
public snes_read_hook_t readHookCb;
|
||||
public snes_write_hook_t writeHookCb;
|
||||
public snes_exec_hook_t execHookCb;
|
||||
|
||||
private static List<FieldInfo> FieldsInOrder;
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
};
|
||||
// TODO: I really don't think stuff like this should be set every single frame (only on change)
|
||||
Api.core.snes_set_layer_enables(ref enables);
|
||||
Api.core.snes_set_hooks_enabled(MemoryCallbacks.HasReads, MemoryCallbacks.HasWrites, MemoryCallbacks.HasExecutes);
|
||||
Api.core.snes_set_trace_enabled(_tracer.IsEnabled());
|
||||
Api.core.snes_set_video_enabled(render);
|
||||
Api.core.snes_set_audio_enabled(renderSound);
|
||||
|
|
|
@ -59,7 +59,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
videoFrameCb = snes_video_refresh,
|
||||
audioSampleCb = snes_audio_sample,
|
||||
pathRequestCb = snes_path_request,
|
||||
snesTraceCb = snes_trace
|
||||
traceCb = snes_trace,
|
||||
readHookCb = ReadHook,
|
||||
writeHookCb = WriteHook,
|
||||
execHookCb = ExecHook
|
||||
};
|
||||
|
||||
Api = new BsnesApi(CoreComm.CoreFileProvider.DllPath(), CoreComm, callbacks.AllDelegatesInMemoryOrder());
|
||||
|
@ -383,5 +386,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.BSNES
|
|||
|
||||
private void snes_trace(string disassembly, string registerInfo)
|
||||
=> _tracer.Put(new(disassembly: disassembly, registerInfo: registerInfo));
|
||||
|
||||
private void ReadHook(uint addr)
|
||||
{
|
||||
if (MemoryCallbacks.HasReads)
|
||||
{
|
||||
MemoryCallbacks.CallMemoryCallbacks(addr, 0, (uint) MemoryCallbackFlags.AccessRead, "System Bus");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteHook(uint addr, byte value)
|
||||
{
|
||||
if (MemoryCallbacks.HasWrites)
|
||||
{
|
||||
MemoryCallbacks.CallMemoryCallbacks(addr, value, (uint) MemoryCallbackFlags.AccessWrite, "System Bus");
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecHook(uint addr)
|
||||
{
|
||||
if (MemoryCallbacks.HasExecutes)
|
||||
{
|
||||
MemoryCallbacks.CallMemoryCallbacks(addr, 0, (uint) MemoryCallbackFlags.AccessExecute, "System Bus");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,13 @@ struct Platform {
|
|||
virtual auto getBackdropColor() -> uint16 { return 0; }
|
||||
|
||||
bool traceEnabled = false;
|
||||
bool readHookEnabled = false;
|
||||
bool writeHookEnabled = false;
|
||||
bool executeHookEnabled = false;
|
||||
virtual auto cpuTrace(vector<string>) -> void {}
|
||||
virtual auto readHook(uint address) -> void {}
|
||||
virtual auto writeHook(uint address, uint8 value) -> void {}
|
||||
virtual auto execHook(uint address) -> void {}
|
||||
};
|
||||
|
||||
extern Platform* platform;
|
||||
|
|
|
@ -36,6 +36,8 @@ auto CPU::main() -> void {
|
|||
if(r.wai) return instructionWait();
|
||||
if(r.stp) return instructionStop();
|
||||
if(!status.interruptPending) {
|
||||
if (__builtin_expect(platform->executeHookEnabled, 0))
|
||||
platform->execHook(cpu.r.pc.d);
|
||||
if (platform->traceEnabled) {
|
||||
vector<string> disassembly = disassemble();
|
||||
disassembly[1].append(" V:", hex(cpu.vcounter(), 3), " H:", hex(cpu.hdot(), 3));
|
||||
|
|
|
@ -7,6 +7,9 @@ auto CPU::idle() -> void {
|
|||
}
|
||||
|
||||
auto CPU::read(uint address) -> uint8 {
|
||||
if (__builtin_expect(platform->readHookEnabled, 0))
|
||||
platform->readHook(address);
|
||||
|
||||
if(address & 0x408000) {
|
||||
if(address & 0x800000 && io.fastROM) {
|
||||
status.clockCount = 6;
|
||||
|
@ -46,6 +49,9 @@ auto CPU::read(uint address) -> uint8 {
|
|||
}
|
||||
|
||||
auto CPU::write(uint address, uint8 data) -> void {
|
||||
if (__builtin_expect(platform->writeHookEnabled, 0))
|
||||
platform->writeHook(address, data);
|
||||
|
||||
aluEdge();
|
||||
|
||||
if(address & 0x408000) {
|
||||
|
|
|
@ -267,6 +267,13 @@ EXPORT void snes_set_trace_enabled(bool enabled)
|
|||
platform->traceEnabled = enabled;
|
||||
}
|
||||
|
||||
EXPORT void snes_set_hooks_enabled(bool read_hook_enabled, bool write_hook_enabled, bool execute_hook_enabled)
|
||||
{
|
||||
platform->readHookEnabled = read_hook_enabled;
|
||||
platform->writeHookEnabled = write_hook_enabled;
|
||||
platform->executeHookEnabled = execute_hook_enabled;
|
||||
}
|
||||
|
||||
|
||||
EXPORT int snes_get_region(void) {
|
||||
return Region::PAL();
|
||||
|
|
|
@ -10,6 +10,9 @@ typedef void (*snes_video_frame_t)(const uint16_t* data, int width, int height,
|
|||
typedef void (*snes_audio_sample_t)(int16_t left, int16_t right);
|
||||
typedef char* (*snes_path_request_t)(int slot, const char* hint, int required);
|
||||
typedef void (*snes_trace_t)(const char* disassembly, const char* register_info);
|
||||
typedef void (*snes_read_hook_t)(uint32_t address);
|
||||
typedef void (*snes_write_hook_t)(uint32_t address, uint8_t value);
|
||||
typedef void (*snes_exec_hook_t)(uint32_t address);
|
||||
|
||||
struct SnesCallbacks {
|
||||
snes_input_poll_t snes_input_poll;
|
||||
|
@ -19,6 +22,9 @@ struct SnesCallbacks {
|
|||
snes_audio_sample_t snes_audio_sample;
|
||||
snes_path_request_t snes_path_request;
|
||||
snes_trace_t snes_trace;
|
||||
snes_read_hook_t snes_read_hook;
|
||||
snes_write_hook_t snes_write_hook;
|
||||
snes_exec_hook_t snes_exec_hook;
|
||||
};
|
||||
|
||||
extern SnesCallbacks snesCallbacks;
|
||||
|
|
|
@ -23,6 +23,9 @@ struct Program : Emulator::Platform
|
|||
auto notify(string text) -> void override;
|
||||
auto getBackdropColor() -> uint16 override;
|
||||
auto cpuTrace(vector<string>) -> void override;
|
||||
auto readHook(uint address) -> void override;
|
||||
auto writeHook(uint address, uint8 value) -> void override;
|
||||
auto execHook(uint address) -> void override;
|
||||
|
||||
auto load() -> void;
|
||||
auto loadFile(string location) -> vector<uint8_t>;
|
||||
|
@ -455,6 +458,21 @@ auto Program::cpuTrace(vector<string> parts) -> void
|
|||
snesCallbacks.snes_trace(parts[0], parts[1]);
|
||||
}
|
||||
|
||||
auto Program::readHook(uint address) -> void
|
||||
{
|
||||
snesCallbacks.snes_read_hook(address);
|
||||
}
|
||||
|
||||
auto Program::writeHook(uint address, uint8 value) -> void
|
||||
{
|
||||
snesCallbacks.snes_write_hook(address, value);
|
||||
}
|
||||
|
||||
auto Program::execHook(uint address) -> void
|
||||
{
|
||||
snesCallbacks.snes_exec_hook(address);
|
||||
}
|
||||
|
||||
auto Program::getBackdropColor() -> uint16
|
||||
{
|
||||
return backdropColor;
|
||||
|
|
Loading…
Reference in New Issue