From 2d96724b28de69b6517a730219feae58d19dbc88 Mon Sep 17 00:00:00 2001 From: Sour Date: Thu, 27 Mar 2025 21:30:38 +0900 Subject: [PATCH] Debugger: SNES - Added new "break on..." options Invalid vram/oam/cgram access, controller read while auto-read is running --- Core/Debugger/DebugTypes.h | 3 +++ Core/Debugger/Debugger.cpp | 2 ++ Core/SNES/InternalRegisters.cpp | 4 ++-- Core/SNES/InternalRegisters.h | 2 ++ Core/SNES/SnesControlManager.cpp | 3 +++ Core/SNES/SnesPpu.cpp | 14 +++++++++++--- Core/Shared/SettingTypes.h | 2 ++ UI/Config/Debugger/DebugConfig.cs | 4 ++++ UI/Config/Debugger/SnesDebuggerConfig.cs | 10 +++------- UI/Debugger/Views/DebuggerOptionsView.axaml | 9 +++++++++ UI/Interop/DebugApi.cs | 6 +++++- UI/Localization/resources.en.xml | 5 +++++ 12 files changed, 51 insertions(+), 13 deletions(-) diff --git a/Core/Debugger/DebugTypes.h b/Core/Debugger/DebugTypes.h index 7b922910..6e2aae07 100644 --- a/Core/Debugger/DebugTypes.h +++ b/Core/Debugger/DebugTypes.h @@ -343,6 +343,9 @@ enum class BreakSource GbaNopLoad, GbaUnalignedMemoryAccess, + SnesInvalidPpuAccess, + SnesReadDuringAutoJoy, + BreakOnUndefinedOpCode }; diff --git a/Core/Debugger/Debugger.cpp b/Core/Debugger/Debugger.cpp index bab28da0..d7584f8a 100644 --- a/Core/Debugger/Debugger.cpp +++ b/Core/Debugger/Debugger.cpp @@ -805,6 +805,8 @@ bool Debugger::IsBreakOptionEnabled(BreakSource src) case BreakSource::PceBreakOnInvalidVramAddress: return cfg.PceBreakOnInvalidVramAddress; case BreakSource::GbaInvalidOpCode: return cfg.GbaBreakOnInvalidOpCode; case BreakSource::GbaUnalignedMemoryAccess: return cfg.GbaBreakOnUnalignedMemAccess; + case BreakSource::SnesInvalidPpuAccess: return cfg.SnesBreakOnInvalidPpuAccess; + case BreakSource::SnesReadDuringAutoJoy: return cfg.SnesBreakOnReadDuringAutoJoy; } return true; } diff --git a/Core/SNES/InternalRegisters.cpp b/Core/SNES/InternalRegisters.cpp index bdc80c4a..4310d8c5 100644 --- a/Core/SNES/InternalRegisters.cpp +++ b/Core/SNES/InternalRegisters.cpp @@ -17,6 +17,7 @@ InternalRegisters::InternalRegisters() void InternalRegisters::Initialize(SnesConsole* console) { + _emu = console->GetEmulator(); _cpu = console->GetCpu(); _aluMulDiv.Initialize(_cpu); _console = console; @@ -160,8 +161,7 @@ uint8_t InternalRegisters::ReadControllerData(uint8_t port, bool getMsb) } if(_autoReadActive) { - //TODO add a break option for this? - _console->GetEmulator()->DebugLog("[Input] Read input during auto-read - results may be invalid."); + _emu->BreakIfDebugging(CpuType::Snes, BreakSource::SnesReadDuringAutoJoy); } return value; diff --git a/Core/SNES/InternalRegisters.h b/Core/SNES/InternalRegisters.h index d8fed135..b713a16a 100644 --- a/Core/SNES/InternalRegisters.h +++ b/Core/SNES/InternalRegisters.h @@ -14,6 +14,7 @@ class SnesControlManager; class InternalRegisters final : public ISerializable { private: + Emulator* _emu = nullptr; SnesConsole* _console = nullptr; SnesCpu* _cpu = nullptr; SnesPpu* _ppu = nullptr; @@ -62,6 +63,7 @@ public: bool IsVerticalIrqEnabled() { return _state.EnableVerticalIrq; } bool IsHorizontalIrqEnabled() { return _state.EnableHorizontalIrq; } bool IsNmiEnabled() { return _state.EnableNmi; } + bool IsAutoReadActive() { return _autoReadActive; } bool IsFastRomEnabled() { return _state.EnableFastRom; } uint16_t GetHorizontalTimer() { return _state.HorizontalTimer; } uint16_t GetVerticalTimer() { return _state.VerticalTimer; } diff --git a/Core/SNES/SnesControlManager.cpp b/Core/SNES/SnesControlManager.cpp index 40ab2086..6a3a89dc 100644 --- a/Core/SNES/SnesControlManager.cpp +++ b/Core/SNES/SnesControlManager.cpp @@ -88,6 +88,9 @@ void SnesControlManager::UpdateControlDevices() uint8_t SnesControlManager::Read(uint16_t addr, bool forAutoRead) { if(!forAutoRead) { + if(_console->GetInternalRegisters()->IsAutoReadActive()) { + _emu->BreakIfDebugging(CpuType::Snes, BreakSource::SnesReadDuringAutoJoy); + } _console->GetInternalRegisters()->ProcessAutoJoypad(); SetInputReadFlag(); } diff --git a/Core/SNES/SnesPpu.cpp b/Core/SNES/SnesPpu.cpp index 208dbe02..3c724521 100644 --- a/Core/SNES/SnesPpu.cpp +++ b/Core/SNES/SnesPpu.cpp @@ -6,7 +6,6 @@ #include "SNES/Spc.h" #include "SNES/InternalRegisters.h" #include "SNES/SnesControlManager.h" -#include "SNES/InternalRegisters.h" #include "SNES/SnesDmaController.h" #include "SNES/Debugger/SnesPpuTools.h" #include "Debugger/Debugger.h" @@ -1624,12 +1623,20 @@ bool SnesPpu::IsDoubleWidth() bool SnesPpu::CanAccessCgram() { - return _scanline >= _nmiScanline || _scanline == 0 || _state.ForcedBlank || _memoryManager->GetHClock() < 88 || _memoryManager->GetHClock() >= 1096; + bool allowAccess = _scanline >= _nmiScanline || _scanline == 0 || _state.ForcedBlank || _memoryManager->GetHClock() < 88 || _memoryManager->GetHClock() >= 1096; + if(!allowAccess) { + _emu->BreakIfDebugging(CpuType::Snes, BreakSource::SnesInvalidPpuAccess); + } + return allowAccess; } bool SnesPpu::CanAccessVram() { - return _scanline >= _nmiScanline || _state.ForcedBlank; + bool allowAccess = _scanline >= _nmiScanline || _state.ForcedBlank; + if(!allowAccess) { + _emu->BreakIfDebugging(CpuType::Snes, BreakSource::SnesInvalidPpuAccess); + } + return allowAccess; } void SnesPpu::SetLocationLatchRequest(uint16_t x, uint16_t y) @@ -1672,6 +1679,7 @@ uint16_t SnesPpu::GetOamAddress() if(_state.ForcedBlank || _scanline >= _vblankStartScanline) { return _state.InternalOamAddress; } else { + _emu->BreakIfDebugging(CpuType::Snes, BreakSource::SnesInvalidPpuAccess); if(_memoryManager->GetHClock() <= 255 * 4) { return _oamEvaluationIndex << 2; } else { diff --git a/Core/Shared/SettingTypes.h b/Core/Shared/SettingTypes.h index d5166740..5f546b25 100644 --- a/Core/Shared/SettingTypes.h +++ b/Core/Shared/SettingTypes.h @@ -800,6 +800,8 @@ struct DebugConfig bool SnesBreakOnCop = false; bool SnesBreakOnWdm = false; bool SnesBreakOnStp = false; + bool SnesBreakOnInvalidPpuAccess = false; + bool SnesBreakOnReadDuringAutoJoy = false; bool SnesUseAltSpcOpNames = false; bool SnesIgnoreDspReadWrites = false; diff --git a/UI/Config/Debugger/DebugConfig.cs b/UI/Config/Debugger/DebugConfig.cs index b7e317cc..b2c1d351 100644 --- a/UI/Config/Debugger/DebugConfig.cs +++ b/UI/Config/Debugger/DebugConfig.cs @@ -61,6 +61,8 @@ namespace Mesen.Config SnesBreakOnCop = Debugger.Snes.BreakOnCop, SnesBreakOnWdm = Debugger.Snes.BreakOnWdm, SnesBreakOnStp = Debugger.Snes.BreakOnStp, + SnesBreakOnInvalidPpuAccess = Debugger.Snes.BreakOnInvalidPpuAccess, + SnesBreakOnReadDuringAutoJoy = Debugger.Snes.BreakOnReadDuringAutoJoy, SnesUseAltSpcOpNames = Debugger.Snes.UseAltSpcOpNames, SnesIgnoreDspReadWrites = Debugger.Snes.IgnoreDspReadWrites, @@ -127,6 +129,8 @@ namespace Mesen.Config [MarshalAs(UnmanagedType.I1)] public bool SnesBreakOnCop; [MarshalAs(UnmanagedType.I1)] public bool SnesBreakOnWdm; [MarshalAs(UnmanagedType.I1)] public bool SnesBreakOnStp; + [MarshalAs(UnmanagedType.I1)] public bool SnesBreakOnInvalidPpuAccess; + [MarshalAs(UnmanagedType.I1)] public bool SnesBreakOnReadDuringAutoJoy; [MarshalAs(UnmanagedType.I1)] public bool SnesUseAltSpcOpNames; [MarshalAs(UnmanagedType.I1)] public bool SnesIgnoreDspReadWrites; diff --git a/UI/Config/Debugger/SnesDebuggerConfig.cs b/UI/Config/Debugger/SnesDebuggerConfig.cs index 692bffc5..e04e1222 100644 --- a/UI/Config/Debugger/SnesDebuggerConfig.cs +++ b/UI/Config/Debugger/SnesDebuggerConfig.cs @@ -1,10 +1,4 @@ -using Avalonia; -using Avalonia.Media; -using Mesen.Debugger; -using Mesen.Interop; -using ReactiveUI.Fody.Helpers; -using System.Reactive.Linq; -using System.Reactive; +using ReactiveUI.Fody.Helpers; using Mesen.ViewModels; namespace Mesen.Config @@ -15,6 +9,8 @@ namespace Mesen.Config [Reactive] public bool BreakOnCop { get; set; } = false; [Reactive] public bool BreakOnWdm { get; set; } = false; [Reactive] public bool BreakOnStp { get; set; } = false; + [Reactive] public bool BreakOnInvalidPpuAccess { get; set; } = false; + [Reactive] public bool BreakOnReadDuringAutoJoy { get; set; } = false; [Reactive] public bool UseAltSpcOpNames { get; set; } = false; [Reactive] public bool IgnoreDspReadWrites { get; set; } = true; diff --git a/UI/Debugger/Views/DebuggerOptionsView.axaml b/UI/Debugger/Views/DebuggerOptionsView.axaml index caec69e4..a09b9115 100644 --- a/UI/Debugger/Views/DebuggerOptionsView.axaml +++ b/UI/Debugger/Views/DebuggerOptionsView.axaml @@ -91,6 +91,15 @@ IsChecked="{Binding Config.Snes.BreakOnStp}" Content="{l:Translate chkBreakOnStp}" /> + + + COP WDM STP + Invalid PPU memory access + Controller read during auto-read Uninitialized memory read Debugger opened Power/reset @@ -2965,6 +2967,9 @@ E Invalid instruction Unaligned memory access + Controller read during auto-read + Invalid PPU memory access + Undefined OP