From 0ad79c2cc2f8ae5d9097f3e7fc879361de37d67b Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Wed, 1 Dec 2021 20:55:35 -0800 Subject: [PATCH] [GambatteLink] proper memory callback scopes for each player --- .../Nintendo/Gameboy/Gambatte.IDebuggable.cs | 181 +++++++++--------- .../Consoles/Nintendo/Gameboy/GambatteLink.cs | 17 +- 2 files changed, 106 insertions(+), 92 deletions(-) diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs index 07972d68ac..d686d9290c 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/Gambatte.IDebuggable.cs @@ -45,9 +45,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy public long TotalExecutedCycles => Math.Max((long)_cycleCount, (long)callbackCycleCount); - private const string systemBusScope = "System Bus"; - - private MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { systemBusScope, "ROM", "VRAM", "SRAM", "WRAM", "OAM", "HRAM" }); + private MemoryCallbackSystem _memorycallbacks = new MemoryCallbackSystem(new[] { "System Bus", "ROM", "VRAM", "SRAM", "WRAM", "OAM", "HRAM" }); public IMemoryCallbackSystem MemoryCallbacks => _memorycallbacks; private LibGambatte.MemoryCallback _readcb; @@ -57,100 +55,103 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy /// /// for use in dual core /// - internal void ConnectMemoryCallbackSystem(MemoryCallbackSystem mcs) + internal void ConnectMemoryCallbackSystem(MemoryCallbackSystem mcs, int which) { _memorycallbacks = mcs; + _readcb = CreateCallback(MemoryCallbackFlags.AccessRead, () => MemoryCallbacks.HasReads, $"P{which + 1} "); + _writecb = CreateCallback(MemoryCallbackFlags.AccessWrite, () => MemoryCallbacks.HasWrites, $"P{which + 1} "); + _execcb = CreateCallback(MemoryCallbackFlags.AccessExecute, () => MemoryCallbacks.HasExecutes, $"P{which + 1} "); _memorycallbacks.ActiveChanged += SetMemoryCallbacks; } + private LibGambatte.MemoryCallback CreateCallback(MemoryCallbackFlags flags, Func getHasCBOfType, string which = "") + { + var rawFlags = (uint)flags; + return (address, cycleOffset) => + { + callbackCycleCount = _cycleCount + cycleOffset; + if (getHasCBOfType()) + { + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "System Bus"); + if (address < 0x4000u) // always rom bank 0 for most mbcs (todo: edge mbcs where this doesn't apply) + { + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "ROM"); + } + else if (address < 0x8000u) // rom bank x + { + var bank = LibGambatte.gambatte_getrombank(GambatteState); // this will return 1 in case there is no mbc (0 is valid for some mbcs too) + address += (uint)(bank * 0x4000); + address -= 0x4000u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "ROM"); + } + else if (address < 0xA000u) // vram (may be banked on CGB in CGB enhanced mode) + { + if (IsCGBMode() && !IsCGBDMGMode()) + { + var bank = LibGambatte.gambatte_cpuread(GambatteState, 0xFF4F) & 1; + address += (uint)(bank * 0x2000); + } + address -= 0x8000u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "VRAM"); + } + else if (address < 0xC000u) // sram (may be banked) + { + var bank = LibGambatte.gambatte_getsrambank(GambatteState); // this will return 0 in case there is only one bank + address += (uint)(bank * 0x2000); + address -= 0xA000u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "SRAM"); + } + else if (address < 0xD000u) // wram bank 0 + { + address -= 0xC000u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "WRAM"); + } + else if (address < 0xE000u) // wram bank x (always one for dmg/cgb in dmg mode) + { + if (IsCGBMode() && !IsCGBDMGMode()) + { + var bank = Math.Max(LibGambatte.gambatte_cpuread(GambatteState, 0xFF70) & 7, 1); + address += (uint)(bank * 0x1000); + } + address -= 0xD000u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "WRAM"); + } + else if (address < 0xFE00u) // echo ram + { + // do we do something here? + } + else if (address < 0xFEA0u) // oam + { + address -= 0xFE00u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "OAM"); + } + else if (address < 0xFF00u) // "extra" oam + { + // do we do something here? + } + else if (address < 0xFF80u) // mmio + { + // do we do something here? + } + else if (address < 0xFFFF) // hram + { + address -= 0xFF80u; + MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, which + "HRAM"); + } + else if (address == 0xFFFF) // ie reg + { + // do we do something here? + } + else + { + throw new InvalidOperationException("Core accessed invalid address???"); + } + } + }; + } + private void InitMemoryCallbacks() { - LibGambatte.MemoryCallback CreateCallback(MemoryCallbackFlags flags, Func getHasCBOfType) - { - var rawFlags = (uint)flags; - return (address, cycleOffset) => - { - callbackCycleCount = _cycleCount + cycleOffset; - if (getHasCBOfType()) - { - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, systemBusScope); - if (address < 0x4000u) // always rom bank 0 for most mbcs (todo: edge mbcs where this doesn't apply) - { - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "ROM"); - } - else if (address < 0x8000u) // rom bank x - { - var bank = LibGambatte.gambatte_getrombank(GambatteState); // this will return 1 in case there is no mbc (0 is valid for some mbcs too) - address += (uint)(bank * 0x4000); - address -= 0x4000u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "ROM"); - } - else if (address < 0xA000u) // vram (may be banked on CGB in CGB enhanced mode) - { - if (IsCGBMode() && !IsCGBDMGMode()) - { - var bank = LibGambatte.gambatte_cpuread(GambatteState, 0xFF4F) & 1; - address += (uint)(bank * 0x2000); - } - address -= 0x8000u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "VRAM"); - } - else if (address < 0xC000u) // sram (may be banked) - { - var bank = LibGambatte.gambatte_getsrambank(GambatteState); // this will return 0 in case there is only one bank - address += (uint)(bank * 0x2000); - address -= 0xA000u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "SRAM"); - } - else if (address < 0xD000u) // wram bank 0 - { - address -= 0xC000u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "WRAM"); - } - else if (address < 0xE000u) // wram bank x (always one for dmg/cgb in dmg mode) - { - if (IsCGBMode() && !IsCGBDMGMode()) - { - var bank = Math.Max(LibGambatte.gambatte_cpuread(GambatteState, 0xFF70) & 7, 1); - address += (uint)(bank * 0x1000); - } - address -= 0xD000u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "WRAM"); - } - else if (address < 0xFE00u) // echo ram - { - // do we do something here? - } - else if (address < 0xFEA0u) // oam - { - address -= 0xFE00u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "OAM"); - } - else if (address < 0xFF00u) // "extra" oam - { - // do we do something here? - } - else if (address < 0xFF80u) // mmio - { - // do we do something here? - } - else if (address < 0xFFFF) // hram - { - address -= 0xFF80u; - MemoryCallbacks.CallMemoryCallbacks(address, 0, rawFlags, "HRAM"); - } - else if (address == 0xFFFF) // ie reg - { - // do we do something here? - } - else - { - throw new InvalidOperationException("Core accessed invalid address???"); - } - } - }; - } - _readcb = CreateCallback(MemoryCallbackFlags.AccessRead, () => MemoryCallbacks.HasReads); _writecb = CreateCallback(MemoryCallbackFlags.AccessWrite, () => MemoryCallbacks.HasWrites); _execcb = CreateCallback(MemoryCallbackFlags.AccessExecute, () => MemoryCallbacks.HasExecutes); diff --git a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs index 5195003b4d..2e6f57528f 100644 --- a/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs +++ b/src/BizHawk.Emulation.Cores/Consoles/Nintendo/Gameboy/GambatteLink.cs @@ -28,13 +28,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy _linkedOverflow = new int[_numCores]; RomDetails = ""; - _memoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus", "ROM", "VRAM", "SRAM", "WRAM", "OAM", "HRAM" }); + + var scopes = new string[_numCores * 7]; + for (int i = 0; i < _numCores; i++) + { + scopes[i * 7 + 0] = $"P{i + 1} System Bus"; + scopes[i * 7 + 1] = $"P{i + 1} ROM"; + scopes[i * 7 + 2] = $"P{i + 1} VRAM"; + scopes[i * 7 + 3] = $"P{i + 1} SRAM"; + scopes[i * 7 + 4] = $"P{i + 1} WRAM"; + scopes[i * 7 + 5] = $"P{i + 1} OAM"; + scopes[i * 7 + 6] = $"P{i + 1} HRAM"; + } + + _memoryCallbacks = new MemoryCallbackSystem(scopes); for (int i = 0; i < _numCores; i++) { _linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested); _linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks); - _linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks); + _linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks, i); _linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(false, false)); _linkedBlips[i] = new BlipBuffer(1024); _linkedBlips[i].SetRates(2097152 * 2, 44100);