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:
Moritz Bender 2021-11-29 17:59:47 +01:00 committed by GitHub
parent 47c8d4f6e8
commit cc38f4bcba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 2 deletions

Binary file not shown.

View File

@ -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;

View File

@ -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);

View File

@ -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");
}
}
}
}

View File

@ -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;

View File

@ -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));

View File

@ -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) {

View File

@ -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();

View File

@ -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;

View File

@ -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;