Debugger: Added Register Viewer tool

This commit is contained in:
Sour 2019-10-10 23:54:38 -04:00
parent f2be04343a
commit af175616cd
38 changed files with 2329 additions and 829 deletions

View file

@ -1,11 +1,16 @@
#include "stdafx.h"
#include "AluMulDiv.h"
#include "Cpu.h"
#include "InternalRegisterTypes.h"
#include "../Utilities/Serializer.h"
void AluMulDiv::Initialize(Cpu* cpu)
{
_cpu = cpu;
_state = {};
_state.MultOperand1 = 0xFF;
_state.Dividend = 0xFFFF;
}
void AluMulDiv::Run(bool isRead)
@ -27,22 +32,22 @@ void AluMulDiv::Run(bool isRead)
if(_multCounter > 0) {
_multCounter--;
if(_divResult & 0x01) {
_multOrRemainderResult += _shift;
if(_state.DivResult & 0x01) {
_state.MultOrRemainderResult += _shift;
}
_shift <<= 1;
_divResult >>= 1;
_state.DivResult >>= 1;
}
if(_divCounter > 0) {
_divCounter--;
_shift >>= 1;
_divResult <<= 1;
_state.DivResult <<= 1;
if(_multOrRemainderResult >= _shift) {
_multOrRemainderResult -= _shift;
_divResult |= 1;
if(_state.MultOrRemainderResult >= _shift) {
_state.MultOrRemainderResult -= _shift;
_state.DivResult |= 1;
}
}
}
@ -56,11 +61,11 @@ uint8_t AluMulDiv::Read(uint16_t addr)
Run(true);
switch(addr) {
case 0x4214: return (uint8_t)_divResult;
case 0x4215: return (uint8_t)(_divResult >> 8);
case 0x4214: return (uint8_t)_state.DivResult;
case 0x4215: return (uint8_t)(_state.DivResult >> 8);
case 0x4216: return (uint8_t)_multOrRemainderResult;
case 0x4217: return (uint8_t)(_multOrRemainderResult >> 8);
case 0x4216: return (uint8_t)_state.MultOrRemainderResult;
case 0x4217: return (uint8_t)(_state.MultOrRemainderResult >> 8);
}
throw std::runtime_error("ALU: invalid address");
@ -71,27 +76,27 @@ void AluMulDiv::Write(uint16_t addr, uint8_t value)
Run(false);
switch(addr) {
case 0x4202: _multOperand1 = value; break;
case 0x4202: _state.MultOperand1 = value; break;
case 0x4203:
_multOrRemainderResult = 0;
_state.MultOrRemainderResult = 0;
if(!_divCounter && !_multCounter) {
_multCounter = 8;
_multOperand2 = value;
_divResult = (value << 8) | _multOperand1;
_state.MultOperand2 = value;
_state.DivResult = (value << 8) | _state.MultOperand1;
_shift = value;
}
break;
case 0x4204: _dividend = (_dividend & 0xFF00) | value; break;
case 0x4205: _dividend = (_dividend & 0xFF) | (value << 8); break;
case 0x4204: _state.Dividend = (_state.Dividend & 0xFF00) | value; break;
case 0x4205: _state.Dividend = (_state.Dividend & 0xFF) | (value << 8); break;
case 0x4206:
_multOrRemainderResult = _dividend;
_state.MultOrRemainderResult = _state.Dividend;
if(!_divCounter && !_multCounter) {
_divCounter = 16;
_divisor = value;
_state.Divisor = value;
_shift = (value << 16);
}
break;
@ -100,10 +105,15 @@ void AluMulDiv::Write(uint16_t addr, uint8_t value)
}
}
AluState AluMulDiv::GetState()
{
return _state;
}
void AluMulDiv::Serialize(Serializer &s)
{
s.Stream(
_multOperand1, _multOperand2, _multOrRemainderResult, _dividend, _divisor, _divResult,
_state.MultOperand1, _state.MultOperand2, _state.MultOrRemainderResult, _state.Dividend, _state.Divisor, _state.DivResult,
_divCounter, _multCounter, _shift, _prevCpuCycle
);
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "stdafx.h"
#include "InternalRegisterTypes.h"
#include "../Utilities/ISerializable.h"
class Cpu;
@ -11,13 +12,7 @@ private:
uint64_t _prevCpuCycle = 0;
uint8_t _multOperand1 = 0xFF;
uint8_t _multOperand2 = 0;
uint16_t _multOrRemainderResult = 0;
uint16_t _dividend = 0xFFFF;
uint8_t _divisor = 0;
uint16_t _divResult = 0;
AluState _state;
uint32_t _shift = 0;
uint8_t _multCounter = 0;
@ -31,5 +26,7 @@ public:
uint8_t Read(uint16_t addr);
void Write(uint16_t addr, uint8_t value);
AluState GetState();
void Serialize(Serializer &s) override;
};

View file

@ -56,12 +56,14 @@
<ClInclude Include="Cx4DisUtils.h" />
<ClInclude Include="Cx4Types.h" />
<ClInclude Include="DebugUtilities.h" />
<ClInclude Include="DmaControllerTypes.h" />
<ClInclude Include="Gsu.h" />
<ClInclude Include="GsuDebugger.h" />
<ClInclude Include="GsuDisUtils.h" />
<ClInclude Include="GsuRamHandler.h" />
<ClInclude Include="GsuRomHandler.h" />
<ClInclude Include="GsuTypes.h" />
<ClInclude Include="InternalRegisterTypes.h" />
<ClInclude Include="MemoryMappings.h" />
<ClInclude Include="BaseRenderer.h" />
<ClInclude Include="BaseSoundManager.h" />

View file

@ -401,6 +401,12 @@
<ClInclude Include="SuperScope.h">
<Filter>SNES\Input</Filter>
</ClInclude>
<ClInclude Include="InternalRegisterTypes.h">
<Filter>SNES</Filter>
</ClInclude>
<ClInclude Include="DmaControllerTypes.h">
<Filter>SNES</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />

View file

@ -6,6 +6,8 @@
#include "NecDspTypes.h"
#include "GsuTypes.h"
#include "Cx4Types.h"
#include "InternalRegisterTypes.h"
#include "DmaControllerTypes.h"
struct DebugState
{
@ -17,6 +19,10 @@ struct DebugState
CpuState Sa1;
GsuState Gsu;
Cx4State Cx4;
DmaChannelConfig DmaChannels[8];
InternalRegisterState InternalRegs;
AluState Alu;
};
enum class SnesMemoryType

View file

@ -34,6 +34,8 @@
#include "ScriptManager.h"
#include "CallstackManager.h"
#include "ExpressionEvaluator.h"
#include "InternalRegisters.h"
#include "AluMulDiv.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/FolderUtilities.h"
@ -46,6 +48,8 @@ Debugger::Debugger(shared_ptr<Console> console)
_cart = console->GetCartridge();
_settings = console->GetSettings();
_memoryManager = console->GetMemoryManager();
_dmaController = console->GetDmaController();
_internalRegs = console->GetInternalRegisters();
_labelManager.reset(new LabelManager(this));
_watchExpEval[(int)CpuType::Cpu].reset(new ExpressionEvaluator(this, CpuType::Cpu));
@ -396,6 +400,13 @@ void Debugger::GetState(DebugState &state, bool partialPpuState)
state.Cpu = _cpu->GetState();
_ppu->GetState(state.Ppu, partialPpuState);
state.Spc = _spc->GetState();
for(int i = 0; i < 8; i++) {
state.DmaChannels[i] = _dmaController->GetChannelConfig(i);
}
state.InternalRegs = _internalRegs->GetState();
state.Alu = _internalRegs->GetAluState();
if(_cart->GetDsp()) {
state.Dsp = _cart->GetDsp()->GetState();
}

View file

@ -11,6 +11,8 @@ class Ppu;
class Spc;
class BaseCartridge;
class MemoryManager;
class InternalRegisters;
class DmaController;
class EmuSettings;
class TraceLogger;
@ -41,6 +43,8 @@ private:
shared_ptr<Spc> _spc;
shared_ptr<MemoryManager> _memoryManager;
shared_ptr<BaseCartridge> _cart;
shared_ptr<InternalRegisters> _internalRegs;
shared_ptr<DmaController> _dmaController;
shared_ptr<EmuSettings> _settings;
unique_ptr<SpcDebugger> _spcDebugger;

View file

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "DmaController.h"
#include "DmaControllerTypes.h"
#include "MemoryManager.h"
#include "MessageManager.h"
#include "../Utilities/Serializer.h"
@ -240,7 +241,7 @@ bool DmaController::ProcessHdmaChannels()
//1. If DoTransfer is false, skip to step 3.
if(ch.DoTransfer) {
//2. For the number of bytes (1, 2, or 4) required for this Transfer Mode...
_activeChannel = i;
_activeChannel = DmaController::HdmaChannelFlag | i;
RunHdmaTransfer(ch);
}
}

View file

@ -1,38 +1,16 @@
#pragma once
#include "stdafx.h"
#include "CpuTypes.h"
#include "DmaControllerTypes.h"
#include "../Utilities/ISerializable.h"
class MemoryManager;
struct DmaChannelConfig
{
bool DmaActive;
bool InvertDirection;
bool Decrement;
bool FixedTransfer;
bool HdmaIndirectAddressing;
uint8_t TransferMode;
uint16_t SrcAddress;
uint8_t SrcBank;
uint16_t TransferSize;
uint8_t DestAddress;
uint16_t HdmaTableAddress;
uint8_t HdmaBank;
uint8_t HdmaLineCounterAndRepeat;
bool DoTransfer;
bool HdmaFinished;
bool UnusedFlag;
};
class DmaController final : public ISerializable
{
private:
static constexpr uint8_t HdmaChannelFlag = 0x80;
bool _needToProcess = false;
bool _hdmaPending = false;
bool _hdmaInitPending = false;

27
Core/DmaControllerTypes.h Normal file
View file

@ -0,0 +1,27 @@
#pragma once
#include "stdafx.h"
struct DmaChannelConfig
{
bool DmaActive;
bool InvertDirection;
bool Decrement;
bool FixedTransfer;
bool HdmaIndirectAddressing;
uint8_t TransferMode;
uint16_t SrcAddress;
uint8_t SrcBank;
uint16_t TransferSize;
uint8_t DestAddress;
uint16_t HdmaTableAddress;
uint8_t HdmaBank;
uint8_t HdmaLineCounterAndRepeat;
bool DoTransfer;
bool HdmaFinished;
bool UnusedFlag;
};

View file

@ -148,7 +148,7 @@ void EventManager::DrawEvent(DebugEventInfo &evt, bool drawBackground, uint32_t
for(int i = iMin; i <= iMax; i++) {
for(int j = jMin; j <= jMax; j++) {
int32_t pos = (y + i) * 340 * 2 + x + j;
if(pos < 0 || pos >= 340 * 2 * _scanlineCount * 2) {
if(pos < 0 || pos >= 340 * 2 * (int)_scanlineCount * 2) {
continue;
}
buffer[pos] = color;
@ -190,7 +190,7 @@ void EventManager::GetDisplayBuffer(uint32_t *buffer, EventViewerDisplayOptions
auto lock = _lock.AcquireSafe();
_sentEvents.clear();
for(int i = 0; i < 340 * 2 * _scanlineCount * 2; i++) {
for(int i = 0; i < 340 * 2 * (int)_scanlineCount * 2; i++) {
buffer[i] = 0xFF555555;
}

View file

@ -0,0 +1,29 @@
#pragma once
#include "stdafx.h"
struct AluState
{
uint8_t MultOperand1;
uint8_t MultOperand2;
uint16_t MultOrRemainderResult;
uint16_t Dividend;
uint8_t Divisor;
uint16_t DivResult;
};
struct InternalRegisterState
{
bool EnableAutoJoypadRead;
bool EnableFastRom;
bool EnableNmi;
bool EnableHorizontalIrq;
bool EnableVerticalIrq;
uint16_t HorizontalTimer;
uint16_t VerticalTimer;
uint8_t IoPortOutput;
uint16_t ControllerData[4];
};

View file

@ -6,6 +6,7 @@
#include "ControlManager.h"
#include "MemoryManager.h"
#include "MessageManager.h"
#include "InternalRegisterTypes.h"
#include "../Utilities/Serializer.h"
#include "../Utilities/HexUtilities.h"
@ -22,17 +23,18 @@ void InternalRegisters::Initialize(Console* console)
Reset();
//Power on values
_horizontalTimer = 0x1FF;
_verticalTimer = 0x1FF;
_ioPortOutput = 0xFF;
_state = {};
_state.HorizontalTimer = 0x1FF;
_state.VerticalTimer = 0x1FF;
_state.IoPortOutput = 0xFF;
}
void InternalRegisters::Reset()
{
_enableAutoJoypadRead = false;
_enableNmi = false;
_enableHorizontalIrq = false;
_enableVerticalIrq = false;
_state.EnableAutoJoypadRead = false;
_state.EnableNmi = false;
_state.EnableHorizontalIrq = false;
_state.EnableVerticalIrq = false;
_nmiFlag = false;
_irqLevel = false;
_needIrq = false;
@ -40,7 +42,7 @@ void InternalRegisters::Reset()
void InternalRegisters::ProcessAutoJoypadRead()
{
if(!_enableAutoJoypadRead) {
if(!_state.EnableAutoJoypadRead) {
return;
}
@ -50,28 +52,28 @@ void InternalRegisters::ProcessAutoJoypadRead()
controlManager->Write(0x4016, 0);
for(int i = 0; i < 4; i++) {
_controllerData[i] = 0;
_state.ControllerData[i] = 0;
}
for(int i = 0; i < 16; i++) {
uint8_t port1 = controlManager->Read(0x4016);
uint8_t port2 = controlManager->Read(0x4017);
_controllerData[0] <<= 1;
_controllerData[1] <<= 1;
_controllerData[2] <<= 1;
_controllerData[3] <<= 1;
_state.ControllerData[0] <<= 1;
_state.ControllerData[1] <<= 1;
_state.ControllerData[2] <<= 1;
_state.ControllerData[3] <<= 1;
_controllerData[0] |= (port1 & 0x01);
_controllerData[1] |= (port2 & 0x01);
_controllerData[2] |= (port1 & 0x02) >> 1;
_controllerData[3] |= (port2 & 0x02) >> 1;
_state.ControllerData[0] |= (port1 & 0x01);
_state.ControllerData[1] |= (port2 & 0x01);
_state.ControllerData[2] |= (port1 & 0x02) >> 1;
_state.ControllerData[3] |= (port2 & 0x02) >> 1;
}
}
uint8_t InternalRegisters::GetIoPortOutput()
{
return _ioPortOutput;
return _state.IoPortOutput;
}
void InternalRegisters::SetNmiFlag(bool nmiFlag)
@ -79,6 +81,15 @@ void InternalRegisters::SetNmiFlag(bool nmiFlag)
_nmiFlag = nmiFlag;
}
uint8_t InternalRegisters::Peek(uint16_t addr)
{
switch(addr) {
case 0x4210: return (_nmiFlag ? 0x80 : 0) | 0x02;
case 0x4211: return (_console->GetCpu()->CheckIrqSource(IrqSource::Ppu) ? 0x80 : 0);
default: return Read(addr);
}
}
uint8_t InternalRegisters::Read(uint16_t addr)
{
switch(addr) {
@ -105,7 +116,7 @@ uint8_t InternalRegisters::Read(uint16_t addr)
return (
(scanline >= nmiScanline ? 0x80 : 0) |
((hClock >= 1*4 && hClock <= 274*4) ? 0 : 0x40) |
((_enableAutoJoypadRead && scanline >= nmiScanline && scanline <= nmiScanline + 2) ? 0x01 : 0) | //Auto joypad read in progress
((_state.EnableAutoJoypadRead && scanline >= nmiScanline && scanline <= nmiScanline + 2) ? 0x01 : 0) | //Auto joypad read in progress
(_memoryManager->GetOpenBus() & 0x3E)
);
}
@ -120,14 +131,14 @@ uint8_t InternalRegisters::Read(uint16_t addr)
case 0x4217:
return _aluMulDiv.Read(addr);
case 0x4218: return (uint8_t)_controllerData[0];
case 0x4219: return (uint8_t)(_controllerData[0] >> 8);
case 0x421A: return (uint8_t)_controllerData[1];
case 0x421B: return (uint8_t)(_controllerData[1] >> 8);
case 0x421C: return (uint8_t)_controllerData[2];
case 0x421D: return (uint8_t)(_controllerData[2] >> 8);
case 0x421E: return (uint8_t)_controllerData[3];
case 0x421F: return (uint8_t)(_controllerData[3] >> 8);
case 0x4218: return (uint8_t)_state.ControllerData[0];
case 0x4219: return (uint8_t)(_state.ControllerData[0] >> 8);
case 0x421A: return (uint8_t)_state.ControllerData[1];
case 0x421B: return (uint8_t)(_state.ControllerData[1] >> 8);
case 0x421C: return (uint8_t)_state.ControllerData[2];
case 0x421D: return (uint8_t)(_state.ControllerData[2] >> 8);
case 0x421E: return (uint8_t)_state.ControllerData[3];
case 0x421F: return (uint8_t)(_state.ControllerData[3] >> 8);
default:
LogDebug("[Debug] Unimplemented register read: " + HexUtilities::ToHex(addr));
@ -139,33 +150,33 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value)
{
switch(addr) {
case 0x4200:
if((value & 0x30) == 0x20 && !_enableVerticalIrq && _ppu->GetRealScanline() == _verticalTimer) {
if((value & 0x30) == 0x20 && !_state.EnableVerticalIrq && _ppu->GetRealScanline() == _state.VerticalTimer) {
//When enabling vertical irqs, if the current scanline matches the target scanline, set the irq flag right away
_console->GetCpu()->SetIrqSource(IrqSource::Ppu);
}
if((value & 0x80) && !_enableNmi && _nmiFlag) {
if((value & 0x80) && !_state.EnableNmi && _nmiFlag) {
_console->GetCpu()->SetNmiFlag();
}
_enableNmi = (value & 0x80) != 0;
_enableVerticalIrq = (value & 0x20) != 0;
_enableHorizontalIrq = (value & 0x10) != 0;
_state.EnableNmi = (value & 0x80) != 0;
_state.EnableVerticalIrq = (value & 0x20) != 0;
_state.EnableHorizontalIrq = (value & 0x10) != 0;
if(!_enableHorizontalIrq && !_enableVerticalIrq) {
if(!_state.EnableHorizontalIrq && !_state.EnableVerticalIrq) {
//TODO VERIFY
_console->GetCpu()->ClearIrqSource(IrqSource::Ppu);
}
_enableAutoJoypadRead = (value & 0x01) != 0;
_state.EnableAutoJoypadRead = (value & 0x01) != 0;
break;
case 0x4201:
//TODO WRIO - Programmable I/O port (out-port)
if((_ioPortOutput & 0x80) && !(value & 0x80)) {
if((_state.IoPortOutput & 0x80) && !(value & 0x80)) {
_ppu->LatchLocationValues();
}
_ioPortOutput = value;
_state.IoPortOutput = value;
break;
case 0x4202:
@ -176,13 +187,13 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value)
_aluMulDiv.Write(addr, value);
break;
case 0x4207: _horizontalTimer = (_horizontalTimer & 0x100) | value; break;
case 0x4208: _horizontalTimer = (_horizontalTimer & 0xFF) | ((value & 0x01) << 8); break;
case 0x4207: _state.HorizontalTimer = (_state.HorizontalTimer & 0x100) | value; break;
case 0x4208: _state.HorizontalTimer = (_state.HorizontalTimer & 0xFF) | ((value & 0x01) << 8); break;
case 0x4209: _verticalTimer = (_verticalTimer & 0x100) | value; break;
case 0x420A: _verticalTimer = (_verticalTimer & 0xFF) | ((value & 0x01) << 8); break;
case 0x4209: _state.VerticalTimer = (_state.VerticalTimer & 0x100) | value; break;
case 0x420A: _state.VerticalTimer = (_state.VerticalTimer & 0xFF) | ((value & 0x01) << 8); break;
case 0x420D: _enableFastRom = (value & 0x01) != 0; break;
case 0x420D: _state.EnableFastRom = (value & 0x01) != 0; break;
default:
LogDebug("[Debug] Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value));
@ -190,12 +201,22 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value)
}
}
InternalRegisterState InternalRegisters::GetState()
{
return _state;
}
AluState InternalRegisters::GetAluState()
{
return _aluMulDiv.GetState();
}
void InternalRegisters::Serialize(Serializer &s)
{
s.Stream(
_enableFastRom, _nmiFlag, _enableNmi, _enableHorizontalIrq, _enableVerticalIrq, _horizontalTimer,
_verticalTimer, _ioPortOutput, _controllerData[0], _controllerData[1], _controllerData[2], _controllerData[3],
_irqLevel, _needIrq, _enableAutoJoypadRead
_state.EnableFastRom, _nmiFlag, _state.EnableNmi, _state.EnableHorizontalIrq, _state.EnableVerticalIrq, _state.HorizontalTimer,
_state.VerticalTimer, _state.IoPortOutput, _state.ControllerData[0], _state.ControllerData[1], _state.ControllerData[2], _state.ControllerData[3],
_irqLevel, _needIrq, _state.EnableAutoJoypadRead
);
s.Stream(&_aluMulDiv);

View file

@ -4,6 +4,7 @@
#include "Console.h"
#include "Cpu.h"
#include "Ppu.h"
#include "InternalRegisterTypes.h"
#include "../Utilities/ISerializable.h"
class MemoryManager;
@ -17,23 +18,11 @@ private:
AluMulDiv _aluMulDiv;
bool _enableAutoJoypadRead = false;
bool _enableFastRom = false;
InternalRegisterState _state;
bool _nmiFlag = false;
bool _enableNmi = false;
bool _enableHorizontalIrq = false;
bool _enableVerticalIrq = false;
uint16_t _horizontalTimer = 0x1FF;
uint16_t _verticalTimer = 0x1FF;
bool _irqLevel = false;
bool _needIrq = false;
uint8_t _ioPortOutput = 0;
uint16_t _controllerData[4] = {};
public:
InternalRegisters();
void Initialize(Console* console);
@ -47,16 +36,20 @@ public:
uint8_t GetIoPortOutput();
void SetNmiFlag(bool nmiFlag);
bool IsVerticalIrqEnabled() { return _enableVerticalIrq; }
bool IsHorizontalIrqEnabled() { return _enableHorizontalIrq; }
bool IsNmiEnabled() { return _enableNmi; }
bool IsFastRomEnabled() { return _enableFastRom; }
uint16_t GetHorizontalTimer() { return _horizontalTimer; }
uint16_t GetVerticalTimer() { return _verticalTimer; }
bool IsVerticalIrqEnabled() { return _state.EnableVerticalIrq; }
bool IsHorizontalIrqEnabled() { return _state.EnableHorizontalIrq; }
bool IsNmiEnabled() { return _state.EnableNmi; }
bool IsFastRomEnabled() { return _state.EnableFastRom; }
uint16_t GetHorizontalTimer() { return _state.HorizontalTimer; }
uint16_t GetVerticalTimer() { return _state.VerticalTimer; }
uint8_t Peek(uint16_t addr);
uint8_t Read(uint16_t addr);
void Write(uint16_t addr, uint8_t value);
InternalRegisterState GetState();
AluState GetAluState();
void Serialize(Serializer &s) override;
};
@ -68,9 +61,9 @@ void InternalRegisters::ProcessIrqCounters()
}
bool irqLevel = (
(_enableHorizontalIrq || _enableVerticalIrq) &&
(!_enableHorizontalIrq || (_horizontalTimer <= 339 && (_ppu->GetCycle() == _horizontalTimer) && (_ppu->GetLastScanline() != _ppu->GetRealScanline() || _horizontalTimer < 339))) &&
(!_enableVerticalIrq || _ppu->GetRealScanline() == _verticalTimer)
(_state.EnableHorizontalIrq || _state.EnableVerticalIrq) &&
(!_state.EnableHorizontalIrq || (_state.HorizontalTimer <= 339 && (_ppu->GetCycle() == _state.HorizontalTimer) && (_ppu->GetLastScanline() != _ppu->GetRealScanline() || _state.HorizontalTimer < 339))) &&
(!_state.EnableVerticalIrq || _ppu->GetRealScanline() == _state.VerticalTimer)
);
if(!_irqLevel && irqLevel) {

File diff suppressed because it is too large Load diff

View file

@ -48,9 +48,6 @@ private:
uint8_t _spriteTileCount = 0;
bool _hasSpritePriority[4] = {};
bool _forcedVblank = false;
uint8_t _screenBrightness = 0;
uint16_t _scanline = 0;
uint32_t _frameCount = 0;
@ -63,37 +60,14 @@ private:
uint8_t _oddFrame = 0;
PpuState _state;
uint16_t _drawStartX = 0;
uint16_t _drawEndX = 0;
uint8_t _bgMode = 0;
bool _mode1Bg3Priority = false;
uint8_t _mainScreenLayers = 0;
uint8_t _subScreenLayers = 0;
LayerConfig _layerConfig[4] = {};
WindowConfig _window[2] = {};
WindowMaskLogic _maskLogic[6] = {};
bool _windowMaskMain[5] = {};
bool _windowMaskSub[5] = {};
Mode7Config _mode7 = {};
uint16_t *_vram = nullptr;
uint16_t _vramAddress = 0;
uint8_t _vramIncrementValue = 0;
uint8_t _vramAddressRemapping = 0;
bool _vramAddrIncrementOnSecondReg = 0;
uint16_t _vramReadBuffer = 0;
uint8_t _ppu1OpenBus = 0;
uint8_t _ppu2OpenBus = 0;
uint8_t _cgramAddress = 0;
uint8_t _cgramWriteBuffer = 0;
bool _cgramAddressLatch = false;
uint16_t _cgram[Ppu::CgRamSize >> 1] = {};
uint8_t _oamRam[Ppu::SpriteRamSize] = {};
uint16_t *_outputBuffers[2] = {};
uint16_t *_currentBuffer = nullptr;
@ -109,17 +83,7 @@ private:
uint16_t _subScreenBuffer[256] = {};
uint32_t _mosaicColor[4] = {};
uint8_t _mosaicSize = 0;
uint8_t _mosaicEnabled = 0;
uint16_t _mosaicScanlineCounter = 0;
uint8_t _oamMode = 0;
uint16_t _oamBaseAddress = 0;
uint16_t _oamAddressOffset = 0;
uint8_t _oamRam[Ppu::SpriteRamSize] = {};
uint16_t _oamRamAddress = 0;
bool _enableOamPriority = false;
uint16_t _internalOamAddress = 0;
uint8_t _oamWriteBuffer = 0;
@ -127,20 +91,6 @@ private:
bool _timeOver = false;
bool _rangeOver = false;
bool _hiResMode = false;
bool _screenInterlace = false;
bool _objInterlace = false;
bool _overscanMode = false;
bool _directColorMode = false;
ColorWindowMode _colorMathClipMode = ColorWindowMode::Never;
ColorWindowMode _colorMathPreventMode = ColorWindowMode::Never;
bool _colorMathAddSubscreen = false;
uint8_t _colorMathEnabled = 0;
bool _colorMathSubstractMode = false;
bool _colorMathHalveResult = false;
uint16_t _fixedColor = 0;
uint8_t _hvScrollLatchValue = 0;
uint8_t _hScrollLatchValue = 0;

View file

@ -1,6 +1,22 @@
#pragma once
#include "stdafx.h"
enum class WindowMaskLogic
{
Or = 0,
And = 1,
Xor = 2,
Xnor = 3
};
enum class ColorWindowMode
{
Never = 0,
OutsideWindow = 1,
InsideWindow = 2,
Always = 3
};
struct SpriteInfo
{
int16_t X;
@ -73,35 +89,12 @@ struct Mode7Config
bool FillWithTile0;
bool HorizontalMirroring;
bool VerticalMirroring;
bool ExtBgEnabled;
//Holds the scroll values at the start of a scanline for the entire scanline
int16_t HScrollLatch;
int16_t VScrollLatch;
};
struct PpuState
{
uint16_t Cycle;
uint16_t Scanline;
uint16_t HClock;
uint32_t FrameCount;
bool OverscanMode;
uint8_t BgMode;
bool DirectColorMode;
bool HiResMode;
bool ScreenInterlace;
Mode7Config Mode7;
LayerConfig Layers[4];
uint8_t OamMode;
uint16_t OamBaseAddress;
uint16_t OamAddressOffset;
bool EnableOamPriority;
bool ObjInterlace;
};
struct WindowConfig
{
bool ActiveLayers[6];
@ -128,21 +121,69 @@ struct WindowConfig
}
};
enum class WindowMaskLogic
struct PpuState
{
Or = 0,
And = 1,
Xor = 2,
Xnor = 3
uint16_t Cycle;
uint16_t Scanline;
uint16_t HClock;
uint32_t FrameCount;
bool ForcedVblank;
uint8_t ScreenBrightness;
Mode7Config Mode7;
uint8_t BgMode;
bool Mode1Bg3Priority;
uint8_t MainScreenLayers;
uint8_t SubScreenLayers;
LayerConfig Layers[4];
WindowConfig Window[2];
WindowMaskLogic MaskLogic[6];
bool WindowMaskMain[5];
bool WindowMaskSub[5];
uint16_t VramAddress;
uint8_t VramIncrementValue;
uint8_t VramAddressRemapping;
bool VramAddrIncrementOnSecondReg;
uint16_t VramReadBuffer;
uint8_t Ppu1OpenBus;
uint8_t Ppu2OpenBus;
uint8_t CgramAddress;
uint8_t CgramWriteBuffer;
bool CgramAddressLatch;
uint8_t MosaicSize = 0;
uint8_t MosaicEnabled = 0;
uint16_t OamRamAddress = 0;
uint8_t OamMode;
uint16_t OamBaseAddress;
uint16_t OamAddressOffset;
bool EnableOamPriority;
bool ExtBgEnabled = false;
bool HiResMode = false;
bool ScreenInterlace = false;
bool ObjInterlace = false;
bool OverscanMode = false;
bool DirectColorMode = false;
ColorWindowMode ColorMathClipMode = ColorWindowMode::Never;
ColorWindowMode ColorMathPreventMode = ColorWindowMode::Never;
bool ColorMathAddSubscreen = false;
uint8_t ColorMathEnabled = 0;
bool ColorMathSubstractMode = false;
bool ColorMathHalveResult = false;
uint16_t FixedColor = 0;
};
enum class ColorWindowMode
{
Never = 0,
OutsideWindow = 1,
InsideWindow = 2,
Always = 3
};
enum PixelFlags
{

View file

@ -35,8 +35,14 @@ public:
uint8_t Peek(uint32_t addr) override
{
//Avoid side effects for now
return 0;
if(addr == 0x4016 || addr == 0x4017) {
//Avoid side effects for now
return 0;
} else if(addr >= 0x4300) {
return _dmaController->Read(addr);
} else {
return _regs->Peek(addr);
}
}
void PeekBlock(uint8_t *output) override

View file

@ -236,12 +236,14 @@ void Spc::Write(uint16_t addr, uint8_t value, MemoryOperationType type)
if(!CheckFlag(SpcFlags::DirectPage)) {
_state.InternalSpeed = (value >> 6) & 0x03;
_state.ExternalSpeed = (value >> 4) & 0x03;
_state.TimersEnabled = (value & 0x09) == 0x08;
_state.TimersEnabled = (value & 0x08) != 0;
_state.TimersDisabled = (value & 0x01) != 0;
_state.WriteEnabled = value & 0x02;
_state.Timer0.SetGlobalEnabled(_state.TimersEnabled);
_state.Timer1.SetGlobalEnabled(_state.TimersEnabled);
_state.Timer2.SetGlobalEnabled(_state.TimersEnabled);
bool timersEnabled = _state.TimersEnabled && !_state.TimersDisabled;
_state.Timer0.SetGlobalEnabled(timersEnabled);
_state.Timer1.SetGlobalEnabled(timersEnabled);
_state.Timer2.SetGlobalEnabled(timersEnabled);
}
break;
@ -409,7 +411,7 @@ void Spc::Serialize(Serializer &s)
_dsp->set_output(_soundBuffer, Spc::SampleBufferSize >> 1);
}
s.Stream(_operandA, _operandB, _tmp1, _tmp2, _tmp3, _opCode, _opStep, _opSubStep, _enabled);
s.Stream(_operandA, _operandB, _tmp1, _tmp2, _tmp3, _opCode, _opStep, _opSubStep, _enabled, _state.TimersDisabled);
}
uint8_t Spc::GetOpCode()

View file

@ -18,6 +18,7 @@ struct SpcState
uint8_t InternalSpeed;
uint8_t ExternalSpeed;
bool TimersEnabled;
bool TimersDisabled;
CpuStopState StopState;
uint8_t DspReg;

View file

@ -89,7 +89,7 @@ extern "C"
DllExport void __stdcall GetDebugEvents(DebugEventInfo *infoArray, uint32_t &maxEventCount, bool getPreviousFrameData) { GetDebugger()->GetEventManager()->GetEvents(infoArray, maxEventCount, getPreviousFrameData); }
DllExport uint32_t __stdcall GetDebugEventCount(bool getPreviousFrameData) { return GetDebugger()->GetEventManager()->GetEventCount(getPreviousFrameData); }
DllExport void __stdcall GetEventViewerOutput(uint32_t *buffer, EventViewerDisplayOptions options) { GetDebugger()->GetEventManager()->GetDisplayBuffer(buffer, options); }
DllExport DebugEventInfo __stdcall GetEventViewerEvent(uint16_t scanline, uint16_t cycle, EventViewerDisplayOptions options) { return GetDebugger()->GetEventManager()->GetEvent(scanline, cycle, options); }
DllExport void __stdcall GetEventViewerEvent(DebugEventInfo *evtInfo, uint16_t scanline, uint16_t cycle, EventViewerDisplayOptions options) { *evtInfo = GetDebugger()->GetEventManager()->GetEvent(scanline, cycle, options); }
DllExport uint32_t __stdcall TakeEventSnapshot(EventViewerDisplayOptions options) { return GetDebugger()->GetEventManager()->TakeEventSnapshot(options); }
DllExport int32_t __stdcall LoadScript(char* name, char* content, int32_t scriptId) { return GetDebugger()->GetScriptManager()->LoadScript(name, content, scriptId); }

View file

@ -23,6 +23,7 @@ namespace Mesen.GUI.Config
public DebuggerInfo Debugger = new DebuggerInfo();
public TilemapViewerConfig TilemapViewer = new TilemapViewerConfig();
public TileViewerConfig TileViewer = new TileViewerConfig();
public RegisterViewerConfig RegisterViewer = new RegisterViewerConfig();
public SpriteViewerConfig SpriteViewer = new SpriteViewerConfig();
public DbgIntegrationConfig DbgIntegration = new DbgIntegrationConfig();
public ScriptWindowConfig ScriptWindow = new ScriptWindowConfig();

View file

@ -69,8 +69,6 @@ namespace Mesen.GUI.Config
[ShortcutName("Open APU Viewer")]
public XmlKeys OpenApuViewer = Keys.Control | Keys.U;
[ShortcutName("Open Assembler")]
public XmlKeys OpenAssembler = Keys.Control | Keys.K;
[ShortcutName("Open Debugger")]
public XmlKeys OpenDebugger = Keys.Control | Keys.D;
[ShortcutName("Open SPC Debugger")]
@ -89,6 +87,8 @@ namespace Mesen.GUI.Config
public XmlKeys OpenScriptWindow = Keys.Control | Keys.N;
[ShortcutName("Open Trace Logger")]
public XmlKeys OpenTraceLogger = Keys.Control | Keys.J;
[ShortcutName("Open Register Viewer")]
public XmlKeys OpenRegisterViewer = Keys.Control | Keys.K;
[ShortcutName("Open Text Hooker")]
public XmlKeys OpenTextHooker = Keys.Control | Keys.H;
[ShortcutName("Open Watch Window")]

View file

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Mesen.GUI.Debugger;
using Mesen.GUI.Controls;
using Mesen.GUI.Utilities;
namespace Mesen.GUI.Config
{
public class RegisterViewerConfig
{
public Size WindowSize = new Size(0, 0);
public Point WindowLocation;
public bool AutoRefresh = true;
public int RefreshScanline = 240;
public int RefreshCycle = 0;
public RegisterViewerConfig()
{
}
}
}

View file

@ -38,6 +38,7 @@ namespace Mesen.GUI.Debugger
case DebugWindow.SpriteViewer: frm = new frmSpriteViewer(); frm.Icon = Properties.Resources.PerfTracker; break;
case DebugWindow.EventViewer: frm = new frmEventViewer(); frm.Icon = Properties.Resources.NesEventViewer; break;
case DebugWindow.ScriptWindow: frm = new frmScript(); frm.Icon = Properties.Resources.Script; break;
case DebugWindow.RegisterViewer: frm = new frmRegisterViewer(); frm.Icon = Properties.Resources.RegisterIcon; break;
}
if(_openedWindows.Count == 0) {
@ -164,6 +165,7 @@ namespace Mesen.GUI.Debugger
PaletteViewer,
SpriteViewer,
EventViewer,
ScriptWindow
ScriptWindow,
RegisterViewer
}
}

View file

@ -18,6 +18,8 @@ namespace Mesen.GUI.Debugger
{
public partial class ctrlEventViewerPpuView : BaseControl
{
private const int HdmaChannelFlag = 0x80;
private int _baseWidth = 340 * 2;
private EntityBinder _entityBinder = new EntityBinder();
@ -215,7 +217,8 @@ namespace Mesen.GUI.Debugger
}
EventViewerDisplayOptions options = ConfigManager.Config.Debug.EventViewer.GetInteropOptions();
DebugEventInfo evt = DebugApi.GetEventViewerEvent((UInt16)pos.Y, (UInt16)pos.X, options);
DebugEventInfo evt = new DebugEventInfo();
DebugApi.GetEventViewerEvent(ref evt, (UInt16)pos.Y, (UInt16)pos.X, options);
if(evt.ProgramCounter == 0xFFFFFFFF) {
ResetTooltip();
UpdateOverlay(e.Location);
@ -245,12 +248,14 @@ namespace Mesen.GUI.Debugger
if(isDma) {
bool indirectHdma = false;
values["Channel"] = evt.DmaChannel.ToString();
if(evt.DmaChannelInfo.InterruptedByHdma != 0) {
indirectHdma = evt.DmaChannelInfo.HdmaIndirectAddressing != 0;
values["Channel"] = (evt.DmaChannel & 0x07).ToString();
if((evt.DmaChannel & ctrlEventViewerPpuView.HdmaChannelFlag) != 0) {
indirectHdma = evt.DmaChannelInfo.HdmaIndirectAddressing;
values["Channel"] += indirectHdma ? " (Indirect HDMA)" : " (HDMA)";
values["Line Counter"] = "$" + evt.DmaChannelInfo.HdmaLineCounterAndRepeat.ToString("X2");
}
values["Mode"] = evt.DmaChannelInfo.TransferMode.ToString();
int aBusAddress;
@ -260,7 +265,7 @@ namespace Mesen.GUI.Debugger
aBusAddress = (evt.DmaChannelInfo.SrcBank << 16) | evt.DmaChannelInfo.SrcAddress;
}
if(evt.DmaChannelInfo.InvertDirection == 0) {
if(!evt.DmaChannelInfo.InvertDirection) {
values["Transfer"] = "$" + aBusAddress.ToString("X4") + " -> $" + evt.DmaChannelInfo.DestAddress.ToString("X2");
} else {
values["Transfer"] = "$" + aBusAddress.ToString("X4") + " <- $" + evt.DmaChannelInfo.DestAddress.ToString("X2");

View file

@ -0,0 +1,97 @@
namespace Mesen.GUI.Debugger
{
partial class ctrlPropertyList
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.lstProperties = new Mesen.GUI.Controls.DoubleBufferedListView();
this.colAddress = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colValue = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.colValueHex = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.SuspendLayout();
//
// lstProperties
//
this.lstProperties.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colAddress,
this.colName,
this.colValue,
this.colValueHex});
this.lstProperties.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstProperties.FullRowSelect = true;
this.lstProperties.GridLines = true;
this.lstProperties.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
this.lstProperties.HideSelection = false;
this.lstProperties.Location = new System.Drawing.Point(0, 0);
this.lstProperties.Name = "lstProperties";
this.lstProperties.Size = new System.Drawing.Size(424, 292);
this.lstProperties.TabIndex = 1;
this.lstProperties.UseCompatibleStateImageBehavior = false;
this.lstProperties.View = System.Windows.Forms.View.Details;
this.lstProperties.VirtualMode = true;
this.lstProperties.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.lstProperties_RetrieveVirtualItem);
//
// colAddress
//
this.colAddress.Text = "Address";
this.colAddress.Width = 125;
//
// colName
//
this.colName.Text = "Name";
this.colName.Width = 114;
//
// colValue
//
this.colValue.Text = "Value";
this.colValue.Width = 79;
//
// colValueHex
//
this.colValueHex.Text = "Value (Hex)";
this.colValueHex.Width = 90;
//
// ctrlPropertyList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.lstProperties);
this.Name = "ctrlPropertyList";
this.Size = new System.Drawing.Size(424, 292);
this.ResumeLayout(false);
}
#endregion
private GUI.Controls.DoubleBufferedListView lstProperties;
private System.Windows.Forms.ColumnHeader colName;
private System.Windows.Forms.ColumnHeader colValue;
private System.Windows.Forms.ColumnHeader colAddress;
private System.Windows.Forms.ColumnHeader colValueHex;
}
}

View file

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Mesen.GUI.Debugger
{
public partial class ctrlPropertyList : UserControl
{
private List<RegEntry> _values = new List<RegEntry>();
public ctrlPropertyList()
{
InitializeComponent();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
colAddress.Width = this.ClientSize.Width / 5 - 5;
colName.Width = (int)(this.ClientSize.Width / 2.6 - 5);
colValue.Width = this.ClientSize.Width / 5 - 5;
colValueHex.Width = this.ClientSize.Width / 5 - 5;
}
public void UpdateState(List<RegEntry> values)
{
lstProperties.BeginUpdate();
_values = values;
lstProperties.VirtualListSize = _values.Count;
lstProperties.EndUpdate();
}
private void lstProperties_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
string val = _values[e.ItemIndex].GetValue();
e.Item = new ListViewItem(new string[] {
(val == null ? "" : " ") + _values[e.ItemIndex].Reg,
_values[e.ItemIndex].Name,
val,
_values[e.ItemIndex].GetHexValue()
});
if(val == null) {
e.Item.BackColor = SystemColors.MenuBar;
}
}
}
public class RegEntry
{
public string Reg;
public string Name;
private object _value;
private Format _format;
public RegEntry(string reg, string name, object value, Format format = Format.None)
{
this.Reg = reg;
this.Name = name;
this._value = value;
this._format = format;
}
public string GetValue()
{
if(_value is string) {
return _value as string;
} else if(_value is bool) {
return (bool)_value ? "☑ true" : "☐ false";
} else if(_value is IFormattable) {
return _value.ToString();
} else if(_value == null) {
return null;
}
throw new Exception("Unsupported type");
}
public string GetHexValue()
{
if(_value == null) {
return "";
}
switch(_format) {
default: return "";
case Format.X8: return "$" + ((IFormattable)_value).ToString("X2", null);
case Format.X16: return "$" + ((IFormattable)_value).ToString("X4", null);
case Format.X24: return "$" + ((IFormattable)_value).ToString("X6", null);
}
}
public enum Format
{
None,
D,
X8,
X16,
X24
}
}
}

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,252 @@
namespace Mesen.GUI.Debugger
{
partial class frmRegisterViewer
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.ctrlScanlineCycleSelect = new Mesen.GUI.Debugger.Controls.ctrlScanlineCycleSelect();
this.ctrlMesenMenuStrip1 = new Mesen.GUI.Controls.ctrlMesenMenuStrip();
this.mnuFile = new System.Windows.Forms.ToolStripMenuItem();
this.mnuClose = new System.Windows.Forms.ToolStripMenuItem();
this.mnuView = new System.Windows.Forms.ToolStripMenuItem();
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.tabMain = new System.Windows.Forms.TabControl();
this.tpgCpu = new System.Windows.Forms.TabPage();
this.ctrlPropertyCpu = new Mesen.GUI.Debugger.ctrlPropertyList();
this.tpgDma = new System.Windows.Forms.TabPage();
this.ctrlPropertyDma = new Mesen.GUI.Debugger.ctrlPropertyList();
this.tpgPpu = new System.Windows.Forms.TabPage();
this.ctrlPropertyPpu = new Mesen.GUI.Debugger.ctrlPropertyList();
this.tpgSpc = new System.Windows.Forms.TabPage();
this.ctrlPropertySpc = new Mesen.GUI.Debugger.ctrlPropertyList();
this.ctrlMesenMenuStrip1.SuspendLayout();
this.tabMain.SuspendLayout();
this.tpgCpu.SuspendLayout();
this.tpgDma.SuspendLayout();
this.tpgPpu.SuspendLayout();
this.tpgSpc.SuspendLayout();
this.SuspendLayout();
//
// ctrlScanlineCycleSelect
//
this.ctrlScanlineCycleSelect.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ctrlScanlineCycleSelect.Location = new System.Drawing.Point(0, 411);
this.ctrlScanlineCycleSelect.Name = "ctrlScanlineCycleSelect";
this.ctrlScanlineCycleSelect.Size = new System.Drawing.Size(384, 28);
this.ctrlScanlineCycleSelect.TabIndex = 5;
//
// ctrlMesenMenuStrip1
//
this.ctrlMesenMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuFile,
this.mnuView});
this.ctrlMesenMenuStrip1.Location = new System.Drawing.Point(0, 0);
this.ctrlMesenMenuStrip1.Name = "ctrlMesenMenuStrip1";
this.ctrlMesenMenuStrip1.Size = new System.Drawing.Size(384, 24);
this.ctrlMesenMenuStrip1.TabIndex = 9;
this.ctrlMesenMenuStrip1.Text = "ctrlMesenMenuStrip1";
//
// mnuFile
//
this.mnuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuClose});
this.mnuFile.Name = "mnuFile";
this.mnuFile.Size = new System.Drawing.Size(37, 20);
this.mnuFile.Text = "File";
//
// mnuClose
//
this.mnuClose.Image = global::Mesen.GUI.Properties.Resources.Exit;
this.mnuClose.Name = "mnuClose";
this.mnuClose.Size = new System.Drawing.Size(103, 22);
this.mnuClose.Text = "Close";
this.mnuClose.Click += new System.EventHandler(this.mnuClose_Click);
//
// mnuView
//
this.mnuView.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.mnuAutoRefresh,
this.toolStripMenuItem2,
this.mnuRefresh});
this.mnuView.Name = "mnuView";
this.mnuView.Size = new System.Drawing.Size(44, 20);
this.mnuView.Text = "View";
//
// mnuAutoRefresh
//
this.mnuAutoRefresh.Checked = true;
this.mnuAutoRefresh.CheckOnClick = true;
this.mnuAutoRefresh.CheckState = System.Windows.Forms.CheckState.Checked;
this.mnuAutoRefresh.Name = "mnuAutoRefresh";
this.mnuAutoRefresh.Size = new System.Drawing.Size(141, 22);
this.mnuAutoRefresh.Text = "Auto-refresh";
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(138, 6);
//
// mnuRefresh
//
this.mnuRefresh.Image = global::Mesen.GUI.Properties.Resources.Refresh;
this.mnuRefresh.Name = "mnuRefresh";
this.mnuRefresh.Size = new System.Drawing.Size(141, 22);
this.mnuRefresh.Text = "Refresh";
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// tabMain
//
this.tabMain.Controls.Add(this.tpgCpu);
this.tabMain.Controls.Add(this.tpgDma);
this.tabMain.Controls.Add(this.tpgPpu);
this.tabMain.Controls.Add(this.tpgSpc);
this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabMain.Location = new System.Drawing.Point(0, 24);
this.tabMain.Name = "tabMain";
this.tabMain.SelectedIndex = 0;
this.tabMain.Size = new System.Drawing.Size(384, 387);
this.tabMain.TabIndex = 10;
this.tabMain.SelectedIndexChanged += new System.EventHandler(this.tabMain_SelectedIndexChanged);
//
// tpgCpu
//
this.tpgCpu.Controls.Add(this.ctrlPropertyCpu);
this.tpgCpu.Location = new System.Drawing.Point(4, 22);
this.tpgCpu.Name = "tpgCpu";
this.tpgCpu.Size = new System.Drawing.Size(376, 361);
this.tpgCpu.TabIndex = 0;
this.tpgCpu.Text = "CPU";
this.tpgCpu.UseVisualStyleBackColor = true;
//
// ctrlPropertyCpu
//
this.ctrlPropertyCpu.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlPropertyCpu.Location = new System.Drawing.Point(0, 0);
this.ctrlPropertyCpu.Name = "ctrlPropertyCpu";
this.ctrlPropertyCpu.Size = new System.Drawing.Size(376, 361);
this.ctrlPropertyCpu.TabIndex = 0;
//
// tpgDma
//
this.tpgDma.Controls.Add(this.ctrlPropertyDma);
this.tpgDma.Location = new System.Drawing.Point(4, 22);
this.tpgDma.Name = "tpgDma";
this.tpgDma.Size = new System.Drawing.Size(526, 461);
this.tpgDma.TabIndex = 2;
this.tpgDma.Text = "DMA";
this.tpgDma.UseVisualStyleBackColor = true;
//
// ctrlPropertyDma
//
this.ctrlPropertyDma.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlPropertyDma.Location = new System.Drawing.Point(0, 0);
this.ctrlPropertyDma.Name = "ctrlPropertyDma";
this.ctrlPropertyDma.Size = new System.Drawing.Size(526, 461);
this.ctrlPropertyDma.TabIndex = 1;
//
// tpgPpu
//
this.tpgPpu.Controls.Add(this.ctrlPropertyPpu);
this.tpgPpu.Location = new System.Drawing.Point(4, 22);
this.tpgPpu.Name = "tpgPpu";
this.tpgPpu.Size = new System.Drawing.Size(526, 461);
this.tpgPpu.TabIndex = 1;
this.tpgPpu.Text = "PPU";
this.tpgPpu.UseVisualStyleBackColor = true;
//
// ctrlPropertyPpu
//
this.ctrlPropertyPpu.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlPropertyPpu.Location = new System.Drawing.Point(0, 0);
this.ctrlPropertyPpu.Name = "ctrlPropertyPpu";
this.ctrlPropertyPpu.Size = new System.Drawing.Size(526, 461);
this.ctrlPropertyPpu.TabIndex = 2;
//
// tpgSpc
//
this.tpgSpc.Controls.Add(this.ctrlPropertySpc);
this.tpgSpc.Location = new System.Drawing.Point(4, 22);
this.tpgSpc.Name = "tpgSpc";
this.tpgSpc.Size = new System.Drawing.Size(526, 461);
this.tpgSpc.TabIndex = 5;
this.tpgSpc.Text = "SPC";
this.tpgSpc.UseVisualStyleBackColor = true;
//
// ctrlPropertySpc
//
this.ctrlPropertySpc.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlPropertySpc.Location = new System.Drawing.Point(0, 0);
this.ctrlPropertySpc.Name = "ctrlPropertySpc";
this.ctrlPropertySpc.Size = new System.Drawing.Size(526, 461);
this.ctrlPropertySpc.TabIndex = 2;
//
// frmRegisterViewer
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(384, 439);
this.Controls.Add(this.tabMain);
this.Controls.Add(this.ctrlScanlineCycleSelect);
this.Controls.Add(this.ctrlMesenMenuStrip1);
this.Name = "frmRegisterViewer";
this.Text = "Register Viewer";
this.Controls.SetChildIndex(this.ctrlMesenMenuStrip1, 0);
this.Controls.SetChildIndex(this.ctrlScanlineCycleSelect, 0);
this.Controls.SetChildIndex(this.tabMain, 0);
this.ctrlMesenMenuStrip1.ResumeLayout(false);
this.ctrlMesenMenuStrip1.PerformLayout();
this.tabMain.ResumeLayout(false);
this.tpgCpu.ResumeLayout(false);
this.tpgDma.ResumeLayout(false);
this.tpgPpu.ResumeLayout(false);
this.tpgSpc.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Controls.ctrlScanlineCycleSelect ctrlScanlineCycleSelect;
private GUI.Controls.ctrlMesenMenuStrip ctrlMesenMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem mnuFile;
private System.Windows.Forms.ToolStripMenuItem mnuClose;
private System.Windows.Forms.ToolStripMenuItem mnuView;
private System.Windows.Forms.ToolStripMenuItem mnuAutoRefresh;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2;
private System.Windows.Forms.ToolStripMenuItem mnuRefresh;
private System.Windows.Forms.TabControl tabMain;
private System.Windows.Forms.TabPage tpgCpu;
private System.Windows.Forms.TabPage tpgPpu;
private System.Windows.Forms.TabPage tpgDma;
private System.Windows.Forms.TabPage tpgSpc;
private ctrlPropertyList ctrlPropertyCpu;
private ctrlPropertyList ctrlPropertyDma;
private ctrlPropertyList ctrlPropertyPpu;
private ctrlPropertyList ctrlPropertySpc;
}
}

View file

@ -0,0 +1,436 @@
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
using Mesen.GUI.Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Mesen.GUI.Debugger.RegEntry;
namespace Mesen.GUI.Debugger
{
public partial class frmRegisterViewer : BaseForm, IRefresh
{
private NotificationListener _notifListener;
private WindowRefreshManager _refreshManager;
private DebugState _state;
private byte _reg4210;
private byte _reg4211;
private byte _reg4212;
public ctrlScanlineCycleSelect ScanlineCycleSelect { get { return this.ctrlScanlineCycleSelect; } }
public frmRegisterViewer()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs evt)
{
base.OnLoad(evt);
if(DesignMode) {
return;
}
_notifListener = new NotificationListener();
_notifListener.OnNotification += OnNotificationReceived;
InitShortcuts();
RegisterViewerConfig config = ConfigManager.Config.Debug.RegisterViewer;
RestoreLocation(config.WindowLocation, config.WindowSize);
mnuAutoRefresh.Checked = config.AutoRefresh;
ctrlScanlineCycleSelect.Initialize(config.RefreshScanline, config.RefreshCycle);
_refreshManager = new WindowRefreshManager(this);
_refreshManager.AutoRefresh = config.AutoRefresh;
_refreshManager.AutoRefreshSpeed = RefreshSpeed.High;
RefreshData();
RefreshViewer();
mnuAutoRefresh.CheckedChanged += mnuAutoRefresh_CheckedChanged;
}
private void InitShortcuts()
{
mnuRefresh.InitShortcut(this, nameof(DebuggerShortcutsConfig.Refresh));
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
_notifListener?.Dispose();
_refreshManager?.Dispose();
RegisterViewerConfig config = ConfigManager.Config.Debug.RegisterViewer;
config.WindowSize = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Size : this.Size;
config.WindowLocation = this.WindowState != FormWindowState.Normal ? this.RestoreBounds.Location : this.Location;
config.AutoRefresh = mnuAutoRefresh.Checked;
config.RefreshScanline = ctrlScanlineCycleSelect.Scanline;
config.RefreshCycle = ctrlScanlineCycleSelect.Cycle;
ConfigManager.ApplyChanges();
base.OnFormClosed(e);
}
private void OnNotificationReceived(NotificationEventArgs e)
{
switch(e.NotificationType) {
case ConsoleNotificationType.CodeBreak:
RefreshData();
this.BeginInvoke((Action)(() => {
this.RefreshViewer();
}));
break;
}
}
public void RefreshData()
{
_state = DebugApi.GetState();
_reg4210 = DebugApi.GetMemoryValue(SnesMemoryType.CpuMemory, 0x4210);
_reg4211 = DebugApi.GetMemoryValue(SnesMemoryType.CpuMemory, 0x4211);
_reg4212 = DebugApi.GetMemoryValue(SnesMemoryType.CpuMemory, 0x4212);
}
public void RefreshViewer()
{
if(tabMain.SelectedTab == tpgCpu) {
InternalRegisterState regs = _state.InternalRegs;
AluState alu = _state.Alu;
ctrlPropertyCpu.UpdateState(new List<RegEntry>() {
new RegEntry("$4200 - $4201", "IRQ/NMI/Autopoll Enabled", null),
new RegEntry("$4200.7", "NMI Enabled", regs.EnableNmi),
new RegEntry("$4200.5", "H IRQ Enabled", regs.EnableHorizontalIrq),
new RegEntry("$4200.4", "V IRQ Enabled", regs.EnableVerticalIrq),
new RegEntry("$4200.1", "Auto Joypad Poll", regs.EnableAutoJoypadRead),
new RegEntry("$4201", "IO Port", regs.IoPortOutput, Format.X8),
new RegEntry("$4202 - $4206", "Mult/Div Registers (Input)", null),
new RegEntry("$4202", "Multiplicand", alu.MultOperand1, Format.X8),
new RegEntry("$4203", "Multiplier", alu.MultOperand2, Format.X8),
new RegEntry("$4204/5", "Dividend", alu.Dividend, Format.X16),
new RegEntry("$4206", "Divisor", alu.Divisor, Format.X8),
new RegEntry("$4207 - $420A", "H/V IRQ Timers", null),
new RegEntry("$4207/8", "H Timer", regs.HorizontalTimer, Format.X16),
new RegEntry("$4209/A", "V Timer", regs.VerticalTimer, Format.X16),
new RegEntry("$4207 - $420A", "Misc. Flags", null),
new RegEntry("$420D", "FastROM Enabled", regs.EnableFastRom),
new RegEntry("$4210", "NMI Flag", (_reg4210 & 0x80) != 0),
new RegEntry("$4211", "IRQ Flag", (_reg4211 & 0x80) != 0),
new RegEntry("$4212.x", "V-Blank Flag", (_reg4212 & 0x80) != 0),
new RegEntry("$4212.x", "H-Blank Flag", (_reg4212 & 0x40) != 0),
new RegEntry("$4212.x", "Auto Joypad Read", (_reg4212 & 0x01) != 0),
new RegEntry("$4214 - $4217", "Mult/Div Registers (Result)", null),
new RegEntry("$4214/5", "Quotient", alu.DivResult, Format.X16),
new RegEntry("$4216/7", "Product / Remainder", alu.MultOrRemainderResult, Format.X16),
new RegEntry("$4218 - $421F", "Input Data", null),
new RegEntry("$4218/9", "P1 Data", regs.ControllerData[0], Format.X16),
new RegEntry("$421A/B", "P2 Data", regs.ControllerData[1], Format.X16),
new RegEntry("$421C/D", "P3 Data", regs.ControllerData[2], Format.X16),
new RegEntry("$421E/F", "P4 Data", regs.ControllerData[3], Format.X16),
});
} else if(tabMain.SelectedTab == tpgDma) {
List<RegEntry> entries = new List<RegEntry>();
//TODO
/*for(int i = 0; i < 8; i++) {
entries.Add(new RegEntry("$420C." + i.ToString(), "HDMA Channel " + i.ToString() + " Enabled", _state.DmaChannels[i].DmaActive));
}*/
for(int i = 0; i < 8; i++) {
DmaChannelConfig ch = _state.DmaChannels[i];
entries.Add(new RegEntry("DMA Channel " + i.ToString(), "", null));
entries.Add(new RegEntry("$420B." + i.ToString(), "Channel Enabled", _state.DmaChannels[i].DmaActive));
entries.Add(new RegEntry("$43" + i.ToString() + "0.0-2", "Transfer Mode", ch.TransferMode, Format.D));
entries.Add(new RegEntry("$43" + i.ToString() + "0.3", "Fixed", ch.FixedTransfer));
entries.Add(new RegEntry("$43" + i.ToString() + "0.4", "Decrement", ch.Decrement));
entries.Add(new RegEntry("$43" + i.ToString() + "0.6", "Indirect HDMA", ch.HdmaIndirectAddressing));
entries.Add(new RegEntry("$43" + i.ToString() + "0.7", "Direction", ch.InvertDirection ? "B -> A" : "A -> B"));
entries.Add(new RegEntry("$43" + i.ToString() + "1", "B Bus Address", ch.DestAddress, Format.X8));
entries.Add(new RegEntry("$43" + i.ToString() + "2/3/4", "A Bus Address", ((ch.SrcBank << 16) | ch.SrcAddress), Format.X24));
entries.Add(new RegEntry("$43" + i.ToString() + "5/6", "Size", ch.TransferSize, Format.X16));
entries.Add(new RegEntry("$43" + i.ToString() + "7", "HDMA Bank", ch.HdmaBank, Format.X8));
entries.Add(new RegEntry("$43" + i.ToString() + "8/9", "HDMA Address", ch.HdmaTableAddress, Format.X16));
entries.Add(new RegEntry("$43" + i.ToString() + "A", "HDMA Line Counter", ch.HdmaLineCounterAndRepeat, Format.X8));
}
ctrlPropertyDma.UpdateState(entries);
} else if(tabMain.SelectedTab == tpgSpc) {
SpcState spc = _state.Spc;
ctrlPropertySpc.UpdateState(new List<RegEntry>() {
new RegEntry("$F0", "Test", null),
new RegEntry("$F0.0", "Timers Disabled", spc.TimersDisabled),
new RegEntry("$F0.1", "RAM Write Enabled", spc.WriteEnabled),
new RegEntry("$F0.3", "Timers Enabled", spc.TimersEnabled),
new RegEntry("$F0.4-5", "External Speed", spc.ExternalSpeed, Format.D),
new RegEntry("$F0.6-7", "Internal Speed", spc.InternalSpeed, Format.D),
new RegEntry("$F1", "Control", null),
new RegEntry("$F1.0", "Timer 0 Enabled", spc.Timer0.Enabled),
new RegEntry("$F1.1", "Timer 1 Enabled", spc.Timer1.Enabled),
new RegEntry("$F1.2", "Timer 2 Enabled", spc.Timer2.Enabled),
new RegEntry("$F1.7", "IPL ROM Enabled", spc.RomEnabled),
new RegEntry("$F2", "DSP", null),
new RegEntry("$F2", "DSP Register", spc.DspReg, Format.X8),
new RegEntry("$F4 - $F7", "CPU<->SPC Ports", null),
new RegEntry("$F4", "Port 0 (CPU read)", spc.OutputReg[0], Format.X8),
new RegEntry("$F4", "Port 0 (SPC read)", spc.CpuRegs[0], Format.X8),
new RegEntry("$F5", "Port 1 (CPU read)", spc.OutputReg[1], Format.X8),
new RegEntry("$F5", "Port 1 (SPC read)", spc.CpuRegs[1], Format.X8),
new RegEntry("$F6", "Port 2 (CPU read)", spc.OutputReg[2], Format.X8),
new RegEntry("$F6", "Port 2 (SPC read)", spc.CpuRegs[2], Format.X8),
new RegEntry("$F7", "Port 3 (CPU read)", spc.OutputReg[3], Format.X8),
new RegEntry("$F7", "Port 3 (SPC read)", spc.CpuRegs[3], Format.X8),
new RegEntry("$F8", "RAM Reg 0", spc.RamReg[0], Format.X8),
new RegEntry("$F9", "RAM Reg 1", spc.RamReg[1], Format.X8),
new RegEntry("$FA - $FF", "Timers", null),
new RegEntry("$FA", "Timer 0 Divider", spc.Timer0.Target, Format.X8),
new RegEntry("$FA", "Timer 0 Frequency", GetTimerFrequency(8000, spc.Timer0.Target)),
new RegEntry("$FB", "Timer 1 Divider", spc.Timer1.Target, Format.X8),
new RegEntry("$FA", "Timer 1 Frequency", GetTimerFrequency(8000, spc.Timer1.Target)),
new RegEntry("$FC", "Timer 2 Divider", spc.Timer2.Target, Format.X8),
new RegEntry("$FA", "Timer 2 Frequency", GetTimerFrequency(64000, spc.Timer2.Target)),
new RegEntry("$FD", "Timer 0 Output", spc.Timer0.Output, Format.X8),
new RegEntry("$FE", "Timer 1 Output", spc.Timer1.Output, Format.X8),
new RegEntry("$FF", "Timer 2 Output", spc.Timer2.Output, Format.X8),
});
} else if(tabMain.SelectedTab == tpgPpu) {
PpuState ppu = _state.Ppu;
ctrlPropertyPpu.UpdateState(new List<RegEntry>() {
new RegEntry("$2100", "Brightness", null),
new RegEntry("$2100.0", "Forced Blank", ppu.ForcedVblank),
new RegEntry("$2100.4-7", "Brightness", ppu.ScreenBrightness),
new RegEntry("$2101", "OAM Settings", null),
new RegEntry("$2100.0-2", "OAM Table Address", ppu.OamBaseAddress, Format.X16),
new RegEntry("$2100.3-4", "OAM Second Table Address", (ppu.OamBaseAddress + ppu.OamAddressOffset) & 0x7FFF, Format.X16),
new RegEntry("$2101.5-7", "OAM Size Mode", ppu.OamMode),
new RegEntry("$2102-2103", "OAM Base Address", ppu.OamRamAddress),
new RegEntry("$2103.7", "OAM Priority", ppu.EnableOamPriority),
new RegEntry("$2105", "BG Mode/Size", null),
new RegEntry("$2105.0-2", "BG Mode", ppu.BgMode),
new RegEntry("$2105.3", "Mode 1 BG3 Priority", ppu.Mode1Bg3Priority),
new RegEntry("$2105.4", "BG1 16x16 Tiles", ppu.Layers[0].LargeTiles),
new RegEntry("$2105.5", "BG2 16x16 Tiles", ppu.Layers[1].LargeTiles),
new RegEntry("$2105.6", "BG3 16x16 Tiles", ppu.Layers[2].LargeTiles),
new RegEntry("$2105.7", "BG4 16x16 Tiles", ppu.Layers[3].LargeTiles),
new RegEntry("$2106", "Mosaic", null),
new RegEntry("$2106.0", "BG1 Mosaic Enabled", (ppu.MosaicEnabled & 0x01) != 0),
new RegEntry("$2106.1", "BG2 Mosaic Enabled", (ppu.MosaicEnabled & 0x02) != 0),
new RegEntry("$2106.2", "BG3 Mosaic Enabled", (ppu.MosaicEnabled & 0x04) != 0),
new RegEntry("$2106.3", "BG4 Mosaic Enabled", (ppu.MosaicEnabled & 0x08) != 0),
new RegEntry("$2106.4-7", "Mosaic Size", (ppu.MosaicSize - 1).ToString() + " (" + ppu.MosaicSize.ToString() + "x" + ppu.MosaicSize.ToString() + ")"),
new RegEntry("$2107 - $210A", "Tilemap Addresses/Sizes", null),
new RegEntry("$2107.0-1", "BG1 Size", GetLayerSize(ppu.Layers[0])),
new RegEntry("$2107.2-6", "BG1 Address", ppu.Layers[0].TilemapAddress, Format.X16),
new RegEntry("$2108.0-1", "BG1 Size", GetLayerSize(ppu.Layers[1])),
new RegEntry("$2108.2-6", "BG2 Address", ppu.Layers[1].TilemapAddress, Format.X16),
new RegEntry("$2109.0-1", "BG1 Size", GetLayerSize(ppu.Layers[2])),
new RegEntry("$2109.2-6", "BG3 Address", ppu.Layers[2].TilemapAddress, Format.X16),
new RegEntry("$210A.0-1", "BG1 Size", GetLayerSize(ppu.Layers[3])),
new RegEntry("$210A.2-6", "BG4 Address", ppu.Layers[3].TilemapAddress, Format.X16),
new RegEntry("$210B - $210C", "Tile Addresses", null),
new RegEntry("$210B.0-2", "BG1 Tile Address", ppu.Layers[0].ChrAddress, Format.X16),
new RegEntry("$210B.4-6", "BG2 Tile Address", ppu.Layers[1].ChrAddress, Format.X16),
new RegEntry("$210C.0-2", "BG3 Tile Address", ppu.Layers[2].ChrAddress, Format.X16),
new RegEntry("$210C.4-6", "BG4 Tile Address", ppu.Layers[3].ChrAddress, Format.X16),
new RegEntry("$210D - $2114", "H/V Scroll Offsets", null),
new RegEntry("$210D", "BG1 H Offset", ppu.Layers[0].HScroll, Format.X16),
new RegEntry("$210D", "Mode7 H Offset", ppu.Mode7.HScroll, Format.X16),
new RegEntry("$210E", "BG1 V Offset", ppu.Layers[0].VScroll, Format.X16),
new RegEntry("$210E", "Mode7 V Offset", ppu.Mode7.VScroll, Format.X16),
new RegEntry("$210F", "BG2 H Offset", ppu.Layers[1].HScroll, Format.X16),
new RegEntry("$2110", "BG2 V Offset", ppu.Layers[1].VScroll, Format.X16),
new RegEntry("$2111", "BG3 H Offset", ppu.Layers[2].HScroll, Format.X16),
new RegEntry("$2112", "BG3 V Offset", ppu.Layers[2].VScroll, Format.X16),
new RegEntry("$2113", "BG4 H Offset", ppu.Layers[3].HScroll, Format.X16),
new RegEntry("$2114", "BG4 V Offset", ppu.Layers[3].VScroll, Format.X16),
new RegEntry("$2115 - $2117", "VRAM", null),
new RegEntry("$2115.0-1", "Increment Value", ppu.VramIncrementValue),
new RegEntry("$2115.2-3", "Address Mapping", ppu.VramAddressRemapping),
new RegEntry("$2115.7", "Increment on $2119", ppu.VramAddrIncrementOnSecondReg),
new RegEntry("$2116/7", "VRAM Address", ppu.VramAddress, Format.X16),
new RegEntry("$211A - $2120", "Mode 7", null),
new RegEntry("$211A.0", "Mode 7 - Hor. Mirroring", ppu.Mode7.HorizontalMirroring),
new RegEntry("$211A.1", "Mode 7 - Vert. Mirroring", ppu.Mode7.VerticalMirroring),
new RegEntry("$211A.6", "Mode 7 - Fill w/ Tile 0", ppu.Mode7.FillWithTile0),
new RegEntry("$211A.7", "Mode 7 - Large Tilemap", ppu.Mode7.LargeMap),
new RegEntry("$211B", "Mode 7 - Matrix A", ppu.Mode7.Matrix[0], Format.X16),
new RegEntry("$211C", "Mode 7 - Matrix B", ppu.Mode7.Matrix[1], Format.X16),
new RegEntry("$211D", "Mode 7 - Matrix C", ppu.Mode7.Matrix[2], Format.X16),
new RegEntry("$211E", "Mode 7 - Matrix D", ppu.Mode7.Matrix[3], Format.X16),
new RegEntry("$211F", "Mode 7 - Center X", ppu.Mode7.CenterX, Format.X16),
new RegEntry("$2120", "Mode 7 - Center Y", ppu.Mode7.CenterY, Format.X16),
new RegEntry("$2123 - $212B", "Windows", null),
new RegEntry("", "BG1 Windows", null),
new RegEntry("$2123.0", "BG1 Window 1 Inverted", ppu.Window[0].InvertedLayers[0]),
new RegEntry("$2123.1", "BG1 Window 1 Active", ppu.Window[0].ActiveLayers[0]),
new RegEntry("$2123.2", "BG1 Window 2 Inverted", ppu.Window[1].InvertedLayers[0]),
new RegEntry("$2123.3", "BG1 Window 2 Active", ppu.Window[1].ActiveLayers[0]),
new RegEntry("", "BG2 Windows", null),
new RegEntry("$2123.4", "BG2 Window 1 Inverted", ppu.Window[0].InvertedLayers[1]),
new RegEntry("$2123.5", "BG2 Window 1 Active", ppu.Window[0].ActiveLayers[1]),
new RegEntry("$2123.6", "BG2 Window 2 Inverted", ppu.Window[1].InvertedLayers[1]),
new RegEntry("$2123.7", "BG2 Window 2 Active", ppu.Window[1].ActiveLayers[1]),
new RegEntry("", "BG3 Windows", null),
new RegEntry("$2124.0", "BG3 Window 1 Inverted", ppu.Window[0].InvertedLayers[2]),
new RegEntry("$2124.1", "BG3 Window 1 Active", ppu.Window[0].ActiveLayers[2]),
new RegEntry("$2124.2", "BG3 Window 2 Inverted", ppu.Window[1].InvertedLayers[2]),
new RegEntry("$2124.3", "BG3 Window 2 Active", ppu.Window[1].ActiveLayers[2]),
new RegEntry("", "BG4 Windows", null),
new RegEntry("$2124.4", "BG4 Window 1 Inverted", ppu.Window[0].InvertedLayers[3]),
new RegEntry("$2124.5", "BG4 Window 1 Active", ppu.Window[0].ActiveLayers[3]),
new RegEntry("$2124.6", "BG4 Window 2 Inverted", ppu.Window[1].InvertedLayers[3]),
new RegEntry("$2124.7", "BG4 Window 2 Active", ppu.Window[1].ActiveLayers[3]),
new RegEntry("", "OAM Windows", null),
new RegEntry("$2125.0", "OAM Window 1 Inverted", ppu.Window[0].InvertedLayers[4]),
new RegEntry("$2125.1", "OAM Window 1 Active", ppu.Window[0].ActiveLayers[4]),
new RegEntry("$2125.2", "OAM Window 2 Inverted", ppu.Window[1].InvertedLayers[4]),
new RegEntry("$2125.3", "OAM Window 2 Active", ppu.Window[1].ActiveLayers[4]),
new RegEntry("", "Color Windows", null),
new RegEntry("$2125.4", "Color Window 1 Inverted", ppu.Window[0].InvertedLayers[5]),
new RegEntry("$2125.5", "Color Window 1 Active", ppu.Window[0].ActiveLayers[5]),
new RegEntry("$2125.6", "Color Window 2 Inverted", ppu.Window[1].InvertedLayers[5]),
new RegEntry("$2125.7", "Color Window 2 Active", ppu.Window[1].ActiveLayers[5]),
new RegEntry("", "Window Position", null),
new RegEntry("$2126", "Window 1 Left", ppu.Window[0].Left),
new RegEntry("$2127", "Window 1 Right", ppu.Window[0].Right),
new RegEntry("$2128", "Window 2 Left", ppu.Window[1].Left),
new RegEntry("$2129", "Window 2 Right", ppu.Window[1].Right),
new RegEntry("", "Window Masks", null),
new RegEntry("$212A.0-1", "BG1 Window Mask", ppu.MaskLogic[0].ToString().ToUpper()),
new RegEntry("$212A.2-3", "BG2 Window Mask", ppu.MaskLogic[1].ToString().ToUpper()),
new RegEntry("$212A.4-5", "BG3 Window Mask", ppu.MaskLogic[2].ToString().ToUpper()),
new RegEntry("$212A.6-7", "BG4 Window Mask", ppu.MaskLogic[3].ToString().ToUpper()),
new RegEntry("$212B.6-7", "OAM Window Mask", ppu.MaskLogic[4].ToString().ToUpper()),
new RegEntry("$212B.6-7", "Color Window Mask", ppu.MaskLogic[5].ToString().ToUpper()),
new RegEntry("$212C", "Main Screen Layers", null),
new RegEntry("$212C.0", "BG1 Enabled", (ppu.MainScreenLayers & 0x01) != 0),
new RegEntry("$212C.1", "BG2 Enabled", (ppu.MainScreenLayers & 0x02) != 0),
new RegEntry("$212C.2", "BG3 Enabled", (ppu.MainScreenLayers & 0x04) != 0),
new RegEntry("$212C.3", "BG4 Enabled", (ppu.MainScreenLayers & 0x08) != 0),
new RegEntry("$212C.4", "OAM Enabled", (ppu.MainScreenLayers & 0x10) != 0),
new RegEntry("$212D", "Sub Screen Layers", null),
new RegEntry("$212D.0", "BG1 Enabled", (ppu.SubScreenLayers & 0x01) != 0),
new RegEntry("$212D.1", "BG2 Enabled", (ppu.SubScreenLayers & 0x02) != 0),
new RegEntry("$212D.2", "BG3 Enabled", (ppu.SubScreenLayers & 0x04) != 0),
new RegEntry("$212D.3", "BG4 Enabled", (ppu.SubScreenLayers & 0x08) != 0),
new RegEntry("$212D.4", "OAM Enabled", (ppu.SubScreenLayers & 0x10) != 0),
new RegEntry("$212E", "Main Screen Windows", null),
new RegEntry("$212E.0", "BG1 Mainscreen Window Enabled", ppu.WindowMaskMain[0]),
new RegEntry("$212E.1", "BG2 Mainscreen Window Enabled", ppu.WindowMaskMain[1]),
new RegEntry("$212E.2", "BG3 Mainscreen Window Enabled", ppu.WindowMaskMain[2]),
new RegEntry("$212E.3", "BG4 Mainscreen Window Enabled", ppu.WindowMaskMain[3]),
new RegEntry("$212E.4", "OAM Mainscreen Window Enabled", ppu.WindowMaskMain[4]),
new RegEntry("$212F", "Sub Screen Windows", null),
new RegEntry("$212F.0", "BG1 Subscreen Window Enabled", ppu.WindowMaskSub[0]),
new RegEntry("$212F.1", "BG2 Subscreen Window Enabled", ppu.WindowMaskSub[1]),
new RegEntry("$212F.2", "BG3 Subscreen Window Enabled", ppu.WindowMaskSub[2]),
new RegEntry("$212F.3", "BG4 Subscreen Window Enabled", ppu.WindowMaskSub[3]),
new RegEntry("$212F.4", "OAM Subscreen Window Enabled", ppu.WindowMaskSub[4]),
new RegEntry("$2130 - $2131", "Color Math", null),
new RegEntry("$2130.0", "Direct Color Mode", ppu.DirectColorMode),
new RegEntry("$2130.1", "CM - Add Subscreen", ppu.ColorMathAddSubscreen),
new RegEntry("$2130.4-5", "CM - Prevent Mode", ppu.ColorMathPreventMode.ToString()),
new RegEntry("$2130.6-7", "CM - Clip Mode", ppu.ColorMathClipMode.ToString()),
new RegEntry("$2131.0", "CM - BG1 Enabled", (ppu.ColorMathEnabled & 0x01) != 0),
new RegEntry("$2131.1", "CM - BG2 Enabled", (ppu.ColorMathEnabled & 0x02) != 0),
new RegEntry("$2131.2", "CM - BG3 Enabled", (ppu.ColorMathEnabled & 0x04) != 0),
new RegEntry("$2131.3", "CM - BG4 Enabled", (ppu.ColorMathEnabled & 0x08) != 0),
new RegEntry("$2131.4", "CM - OAM Enabled", (ppu.ColorMathEnabled & 0x10) != 0),
new RegEntry("$2131.5", "CM - Background Enabled", (ppu.ColorMathEnabled & 0x20) != 0),
new RegEntry("$2131.6", "CM - Half Mode", ppu.ColorMathHalveResult),
new RegEntry("$2131.7", "CM - Substract Mode", ppu.ColorMathSubstractMode),
new RegEntry("$2132 - $2133", "Misc.", null),
new RegEntry("$2132", "Fixed Color - BGR", ppu.FixedColor, Format.X16),
new RegEntry("$2133.0", "Screen Interlace", ppu.ScreenInterlace),
new RegEntry("$2133.1", "OAM Interlace", ppu.ObjInterlace),
new RegEntry("$2133.2", "Overscan Mode", ppu.OverscanMode),
new RegEntry("$2133.3", "High Resolution Mode", ppu.HiResMode),
new RegEntry("$2133.4", "Ext. BG Enabled", ppu.ExtBgEnabled),
});
}
}
private string GetTimerFrequency(double baseFreq, int divider)
{
return (divider == 0 ? (baseFreq / 256) : (baseFreq / divider)).ToString(".00") + " Hz";
}
private string GetLayerSize(LayerConfig layer)
{
return (layer.DoubleWidth ? "64" : "32") + "x" + (layer.DoubleHeight ? "64" : "32");
}
private void mnuRefresh_Click(object sender, EventArgs e)
{
RefreshData();
RefreshViewer();
}
private void mnuClose_Click(object sender, EventArgs e)
{
Close();
}
private void mnuAutoRefresh_CheckedChanged(object sender, EventArgs e)
{
_refreshManager.AutoRefresh = mnuAutoRefresh.Checked;
}
private void tabMain_SelectedIndexChanged(object sender, EventArgs e)
{
RefreshViewer();
}
}
}

View file

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="ctrlMesenMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>107, 17</value>
</metadata>
</root>

View file

@ -47,6 +47,7 @@ namespace Mesen.GUI.Debugger
GetMember(nameof(DebuggerShortcutsConfig.OpenDebugger)),
GetMember(nameof(DebuggerShortcutsConfig.OpenEventViewer)),
GetMember(nameof(DebuggerShortcutsConfig.OpenMemoryTools)),
GetMember(nameof(DebuggerShortcutsConfig.OpenRegisterViewer)),
//GetMember(nameof(DebuggerShortcutsConfig.OpenProfiler)),
GetMember(nameof(DebuggerShortcutsConfig.OpenScriptWindow)),
GetMember(nameof(DebuggerShortcutsConfig.OpenTraceLogger)),

View file

@ -150,6 +150,7 @@
this.pnlRenderer = new System.Windows.Forms.Panel();
this.ctrlRecentGames = new Mesen.GUI.Controls.ctrlRecentGames();
this.mnuBilinearInterpolation = new System.Windows.Forms.ToolStripMenuItem();
this.mnuRegisterViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMain.SuspendLayout();
this.pnlRenderer.SuspendLayout();
this.SuspendLayout();
@ -909,8 +910,9 @@
this.mnuDebugger,
this.mnuEventViewer,
this.mnuMemoryTools,
this.mnuTraceLogger,
this.mnuRegisterViewer,
this.mnuScriptWindow,
this.mnuTraceLogger,
this.toolStripMenuItem12,
this.mnuTilemapViewer,
this.mnuTileViewer,
@ -1095,6 +1097,13 @@
this.mnuBilinearInterpolation.Size = new System.Drawing.Size(231, 22);
this.mnuBilinearInterpolation.Text = "Use Bilinear Interpolation";
//
// mnuRegisterViewer
//
this.mnuRegisterViewer.Image = global::Mesen.GUI.Properties.Resources.RegisterIcon;
this.mnuRegisterViewer.Name = "mnuRegisterViewer";
this.mnuRegisterViewer.Size = new System.Drawing.Size(155, 22);
this.mnuRegisterViewer.Text = "Register Viewer";
//
// frmMain
//
this.AllowDrop = true;
@ -1243,5 +1252,6 @@
private System.Windows.Forms.ToolStripMenuItem mnuStopMovie;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem25;
private System.Windows.Forms.ToolStripMenuItem mnuBilinearInterpolation;
private System.Windows.Forms.ToolStripMenuItem mnuRegisterViewer;
}
}

View file

@ -251,6 +251,7 @@ namespace Mesen.GUI.Forms
mnuPaletteViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenPaletteViewer));
mnuTraceLogger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTraceLogger));
mnuScriptWindow.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenScriptWindow));
mnuRegisterViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenRegisterViewer));
mnuNoneFilter.Click += (s, e) => { _shortcuts.SetVideoFilter(VideoFilterType.None); };
mnuNtscFilter.Click += (s, e) => { _shortcuts.SetVideoFilter(VideoFilterType.NTSC); };
@ -299,6 +300,7 @@ namespace Mesen.GUI.Forms
mnuPaletteViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.PaletteViewer); };
mnuEventViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.EventViewer); };
mnuScriptWindow.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.ScriptWindow); };
mnuRegisterViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.RegisterViewer); };
UpdateDebuggerMenu();
}
@ -316,7 +318,6 @@ namespace Mesen.GUI.Forms
mnuGsuDebugger.Enabled = coprocessor == CoprocessorType.GSU;
mnuGsuDebugger.Visible = coprocessor == CoprocessorType.GSU;
mnuTraceLogger.Enabled = running;
mnuScriptWindow.Enabled = running;
mnuMemoryTools.Enabled = running;
@ -325,6 +326,7 @@ namespace Mesen.GUI.Forms
mnuSpriteViewer.Enabled = running;
mnuPaletteViewer.Enabled = running;
mnuEventViewer.Enabled = running;
mnuRegisterViewer.Enabled = running;
}
private void ResizeRecentGames()

View file

@ -107,7 +107,7 @@ namespace Mesen.GUI
return debugEvents;
}
[DllImport(DllPath)] public static extern DebugEventInfo GetEventViewerEvent(UInt16 scanline, UInt16 cycle, EventViewerDisplayOptions options);
[DllImport(DllPath)] public static extern void GetEventViewerEvent(ref DebugEventInfo evtInfo, UInt16 scanline, UInt16 cycle, EventViewerDisplayOptions options);
[DllImport(DllPath)] public static extern UInt32 TakeEventSnapshot(EventViewerDisplayOptions options);
[DllImport(DllPath, EntryPoint = "GetEventViewerOutput")] private static extern void GetEventViewerOutputWrapper([In, Out]byte[] buffer, EventViewerDisplayOptions options);
@ -243,291 +243,6 @@ namespace Mesen.GUI
public SnesMemoryType Type;
}
public enum CpuStopState : byte
{
Running = 0,
Stopped = 1,
WaitingForIrq = 2
}
[Flags]
public enum ProcFlags : byte
{
Carry = 0x01,
Zero = 0x02,
IrqDisable = 0x04,
Decimal = 0x08,
IndexMode8 = 0x10,
MemoryMode8 = 0x20,
Overflow = 0x40,
Negative = 0x80
}
[Flags]
public enum SpcFlags : byte
{
Carry = 0x01,
Zero = 0x02,
IrqEnable = 0x04,
HalfCarry = 0x08,
Break = 0x10,
DirectPage = 0x20,
Overflow = 0x40,
Negative = 0x80
};
public struct CpuState
{
public UInt64 CycleCount;
public UInt16 A;
public UInt16 X;
public UInt16 Y;
public UInt16 SP;
public UInt16 D;
public UInt16 PC;
public byte K;
public byte DBR;
public ProcFlags PS;
[MarshalAs(UnmanagedType.I1)] public bool EmulationMode;
[MarshalAs(UnmanagedType.I1)] public bool NmiFlag;
[MarshalAs(UnmanagedType.I1)] public bool PrevNmiFlag;
public byte IrqSource;
public byte PrevIrqSource;
public CpuStopState StopState;
};
public struct PpuState
{
public UInt16 Cycle;
public UInt16 Scanline;
public UInt16 HClock;
public UInt32 FrameCount;
[MarshalAs(UnmanagedType.I1)] public bool OverscanMode;
public byte BgMode;
[MarshalAs(UnmanagedType.I1)] public bool DirectColorMode;
[MarshalAs(UnmanagedType.I1)] public bool HiResMode;
[MarshalAs(UnmanagedType.I1)] public bool ScreenInterlace;
public Mode7Config Mode7;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public LayerConfig[] Layers;
public byte OamMode;
public UInt16 OamBaseAddress;
public UInt16 OamAddressOffset;
[MarshalAs(UnmanagedType.I1)] public bool EnableOamPriority;
[MarshalAs(UnmanagedType.I1)] public bool ObjInterlace;
};
public struct LayerConfig
{
public UInt16 TilemapAddress;
public UInt16 ChrAddress;
public UInt16 HScroll;
public UInt16 VScroll;
[MarshalAs(UnmanagedType.I1)] public bool DoubleWidth;
[MarshalAs(UnmanagedType.I1)] public bool DoubleHeight;
[MarshalAs(UnmanagedType.I1)] public bool LargeTiles;
}
public struct Mode7Config
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public Int16[] Matrix;
public Int16 HScroll;
public Int16 VScroll;
public Int16 CenterX;
public Int16 CenterY;
public Byte ValueLatch;
[MarshalAs(UnmanagedType.I1)] public bool LargeMap;
[MarshalAs(UnmanagedType.I1)] public bool FillWithTile0;
[MarshalAs(UnmanagedType.I1)] public bool HorizontalMirroring;
[MarshalAs(UnmanagedType.I1)] public bool VerticalMirroring;
[MarshalAs(UnmanagedType.I1)] public bool ExtBgEnabled;
public Int16 HScrollLatch;
public Int16 VScrollLatch;
}
public struct SpcTimer
{
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
[MarshalAs(UnmanagedType.I1)] public bool TimersEnabled;
public byte Output;
public byte Stage0;
public byte Stage1;
public byte PrevStage1;
public byte Stage2;
public byte Target;
}
public struct SpcState
{
public UInt64 Cycle;
public UInt16 PC;
public byte A;
public byte X;
public byte Y;
public byte SP;
public SpcFlags PS;
[MarshalAs(UnmanagedType.I1)] public bool WriteEnabled;
[MarshalAs(UnmanagedType.I1)] public bool RomEnabled;
public byte InternalSpeed;
public byte ExternalSpeed;
[MarshalAs(UnmanagedType.I1)] public bool TimersEnabled;
public CpuStopState StopState;
public byte DspReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] OutputReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] RamReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] CpuRegs;
public SpcTimer Timer0;
public SpcTimer Timer1;
public SpcTimer Timer2;
};
public struct NecDspAccFlags
{
[MarshalAs(UnmanagedType.I1)] public bool Carry;
[MarshalAs(UnmanagedType.I1)] public bool Zero;
[MarshalAs(UnmanagedType.I1)] public bool Overflow0;
[MarshalAs(UnmanagedType.I1)] public bool Overflow1;
[MarshalAs(UnmanagedType.I1)] public bool Sign0;
[MarshalAs(UnmanagedType.I1)] public bool Sign1;
}
public struct NecDspState
{
public UInt16 A;
public NecDspAccFlags FlagsA;
public UInt16 B;
public NecDspAccFlags FlagsB;
public UInt16 TR;
public UInt16 TRB;
public UInt16 PC;
public UInt16 RP;
public UInt16 DP;
public UInt16 DR;
public UInt16 SR;
public UInt16 K;
public UInt16 L;
public UInt16 M;
public UInt16 N;
public UInt16 SerialOut;
public UInt16 SerialIn;
public byte SP;
}
public struct GsuFlags
{
[MarshalAs(UnmanagedType.I1)] public bool Zero;
[MarshalAs(UnmanagedType.I1)] public bool Carry;
[MarshalAs(UnmanagedType.I1)] public bool Sign;
[MarshalAs(UnmanagedType.I1)] public bool Overflow;
[MarshalAs(UnmanagedType.I1)] public bool Running;
[MarshalAs(UnmanagedType.I1)] public bool RomReadPending;
[MarshalAs(UnmanagedType.I1)] public bool Alt1;
[MarshalAs(UnmanagedType.I1)] public bool Alt2;
[MarshalAs(UnmanagedType.I1)] public bool ImmLow;
[MarshalAs(UnmanagedType.I1)] public bool ImmHigh;
[MarshalAs(UnmanagedType.I1)] public bool Prefix;
[MarshalAs(UnmanagedType.I1)] public bool Irq;
};
public struct GsuPixelCache
{
public byte X;
public byte Y;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Pixels;
public byte ValidBits;
};
public struct GsuState
{
public UInt64 CycleCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public UInt16[] R;
public GsuFlags SFR;
public byte RegisterLatch;
public byte ProgramBank;
public byte RomBank;
public byte RamBank;
[MarshalAs(UnmanagedType.I1)] public bool IrqDisabled;
[MarshalAs(UnmanagedType.I1)] public bool HighSpeedMode;
[MarshalAs(UnmanagedType.I1)] public bool ClockSelect;
[MarshalAs(UnmanagedType.I1)] public bool BackupRamEnabled;
public byte ScreenBase;
public byte ColorGradient;
public byte PlotBpp;
public byte ScreenHeight;
[MarshalAs(UnmanagedType.I1)] public bool GsuRamAccess;
[MarshalAs(UnmanagedType.I1)] public bool GsuRomAccess;
public UInt16 CacheBase;
[MarshalAs(UnmanagedType.I1)] public bool PlotTransparent;
[MarshalAs(UnmanagedType.I1)] public bool PlotDither;
[MarshalAs(UnmanagedType.I1)] public bool ColorHighNibble;
[MarshalAs(UnmanagedType.I1)] public bool ColorFreezeHigh;
[MarshalAs(UnmanagedType.I1)] public bool ObjMode;
public byte ColorReg;
public byte SrcReg;
public byte DestReg;
public byte RomReadBuffer;
public byte RomDelay;
public byte ProgramReadBuffer;
public UInt16 RamWriteAddress;
public byte RamWriteValue;
public byte RamDelay;
public UInt16 RamAddress;
public GsuPixelCache PrimaryCache;
public GsuPixelCache SecondaryCache;
};
public struct DebugState
{
public UInt64 MasterClock;
public CpuState Cpu;
public PpuState Ppu;
public SpcState Spc;
public NecDspState NecDsp;
public CpuState Sa1;
public GsuState Gsu;
}
public enum MemoryOperationType
{
Read = 0,
@ -556,10 +271,13 @@ namespace Mesen.GUI
public struct DmaChannelConfig
{
public byte InvertDirection;
public byte Decrement;
public byte FixedTransfer;
public byte HdmaIndirectAddressing;
[MarshalAs(UnmanagedType.I1)] public bool DmaActive;
[MarshalAs(UnmanagedType.I1)] public bool InvertDirection;
[MarshalAs(UnmanagedType.I1)] public bool Decrement;
[MarshalAs(UnmanagedType.I1)] public bool FixedTransfer;
[MarshalAs(UnmanagedType.I1)] public bool HdmaIndirectAddressing;
public byte TransferMode;
public UInt16 SrcAddress;
@ -571,11 +289,10 @@ namespace Mesen.GUI
public UInt16 HdmaTableAddress;
public byte HdmaBank;
public byte HdmaLineCounterAndRepeat;
public byte DoTransfer;
public byte HdmaFinished;
public byte InterruptedByHdma;
public byte UnusedFlag;
[MarshalAs(UnmanagedType.I1)] public bool DoTransfer;
[MarshalAs(UnmanagedType.I1)] public bool HdmaFinished;
[MarshalAs(UnmanagedType.I1)] public bool UnusedFlag;
}
public struct DebugEventInfo

501
UI/Interop/DebugState.cs Normal file
View file

@ -0,0 +1,501 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Mesen.GUI
{
public enum CpuStopState : byte
{
Running = 0,
Stopped = 1,
WaitingForIrq = 2
}
[Flags]
public enum ProcFlags : byte
{
Carry = 0x01,
Zero = 0x02,
IrqDisable = 0x04,
Decimal = 0x08,
IndexMode8 = 0x10,
MemoryMode8 = 0x20,
Overflow = 0x40,
Negative = 0x80
}
[Flags]
public enum SpcFlags : byte
{
Carry = 0x01,
Zero = 0x02,
IrqEnable = 0x04,
HalfCarry = 0x08,
Break = 0x10,
DirectPage = 0x20,
Overflow = 0x40,
Negative = 0x80
};
public struct CpuState
{
public UInt64 CycleCount;
public UInt16 A;
public UInt16 X;
public UInt16 Y;
public UInt16 SP;
public UInt16 D;
public UInt16 PC;
public byte K;
public byte DBR;
public ProcFlags PS;
[MarshalAs(UnmanagedType.I1)] public bool EmulationMode;
[MarshalAs(UnmanagedType.I1)] public bool NmiFlag;
[MarshalAs(UnmanagedType.I1)] public bool PrevNmiFlag;
public byte IrqSource;
public byte PrevIrqSource;
public CpuStopState StopState;
};
public struct PpuState
{
public UInt16 Cycle;
public UInt16 Scanline;
public UInt16 HClock;
public UInt32 FrameCount;
[MarshalAs(UnmanagedType.I1)] public bool ForcedVblank;
public byte ScreenBrightness;
public Mode7Config Mode7;
public byte BgMode;
[MarshalAs(UnmanagedType.I1)] public bool Mode1Bg3Priority;
public byte MainScreenLayers;
public byte SubScreenLayers;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public LayerConfig[] Layers;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public WindowConfig[] Window;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public WindowMaskLogic[] MaskLogic;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.I1)]
public bool[] WindowMaskMain;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.I1)]
public bool[] WindowMaskSub;
public UInt16 VramAddress;
public byte VramIncrementValue;
public byte VramAddressRemapping;
[MarshalAs(UnmanagedType.I1)] public bool VramAddrIncrementOnSecondReg;
public UInt16 VramReadBuffer;
public byte Ppu1OpenBus;
public byte Ppu2OpenBus;
public byte CgramAddress;
public byte CgramWriteBuffer;
[MarshalAs(UnmanagedType.I1)] public bool CgramAddressLatch;
public byte MosaicSize;
public byte MosaicEnabled;
public UInt16 OamRamAddress;
public byte OamMode;
public UInt16 OamBaseAddress;
public UInt16 OamAddressOffset;
[MarshalAs(UnmanagedType.I1)] public bool EnableOamPriority;
[MarshalAs(UnmanagedType.I1)] public bool ExtBgEnabled;
[MarshalAs(UnmanagedType.I1)] public bool HiResMode;
[MarshalAs(UnmanagedType.I1)] public bool ScreenInterlace;
[MarshalAs(UnmanagedType.I1)] public bool ObjInterlace;
[MarshalAs(UnmanagedType.I1)] public bool OverscanMode;
[MarshalAs(UnmanagedType.I1)] public bool DirectColorMode;
public ColorWindowMode ColorMathClipMode;
public ColorWindowMode ColorMathPreventMode;
[MarshalAs(UnmanagedType.I1)] public bool ColorMathAddSubscreen;
public byte ColorMathEnabled;
[MarshalAs(UnmanagedType.I1)] public bool ColorMathSubstractMode;
[MarshalAs(UnmanagedType.I1)] public bool ColorMathHalveResult;
public UInt16 FixedColor;
};
public struct LayerConfig
{
public UInt16 TilemapAddress;
public UInt16 ChrAddress;
public UInt16 HScroll;
public UInt16 VScroll;
[MarshalAs(UnmanagedType.I1)] public bool DoubleWidth;
[MarshalAs(UnmanagedType.I1)] public bool DoubleHeight;
[MarshalAs(UnmanagedType.I1)] public bool LargeTiles;
}
public struct WindowConfig
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
public bool[] ActiveLayers;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)]
public bool[] InvertedLayers;
public Byte Left;
public Byte Right;
}
public struct Mode7Config
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public Int16[] Matrix;
public Int16 HScroll;
public Int16 VScroll;
public Int16 CenterX;
public Int16 CenterY;
public Byte ValueLatch;
[MarshalAs(UnmanagedType.I1)] public bool LargeMap;
[MarshalAs(UnmanagedType.I1)] public bool FillWithTile0;
[MarshalAs(UnmanagedType.I1)] public bool HorizontalMirroring;
[MarshalAs(UnmanagedType.I1)] public bool VerticalMirroring;
public Int16 HScrollLatch;
public Int16 VScrollLatch;
}
public enum WindowMaskLogic
{
Or = 0,
And = 1,
Xor = 2,
Xnor = 3
}
public enum ColorWindowMode
{
Never = 0,
OutsideWindow = 1,
InsideWindow = 2,
Always = 3
}
public struct SpcTimer
{
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
[MarshalAs(UnmanagedType.I1)] public bool TimersEnabled;
public byte Output;
public byte Stage0;
public byte Stage1;
public byte PrevStage1;
public byte Stage2;
public byte Target;
}
public struct SpcState
{
public UInt64 Cycle;
public UInt16 PC;
public byte A;
public byte X;
public byte Y;
public byte SP;
public SpcFlags PS;
[MarshalAs(UnmanagedType.I1)] public bool WriteEnabled;
[MarshalAs(UnmanagedType.I1)] public bool RomEnabled;
public byte InternalSpeed;
public byte ExternalSpeed;
[MarshalAs(UnmanagedType.I1)] public bool TimersEnabled;
[MarshalAs(UnmanagedType.I1)] public bool TimersDisabled;
public CpuStopState StopState;
public byte DspReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] OutputReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] RamReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] CpuRegs;
public SpcTimer Timer0;
public SpcTimer Timer1;
public SpcTimer Timer2;
};
public struct NecDspAccFlags
{
[MarshalAs(UnmanagedType.I1)] public bool Carry;
[MarshalAs(UnmanagedType.I1)] public bool Zero;
[MarshalAs(UnmanagedType.I1)] public bool Overflow0;
[MarshalAs(UnmanagedType.I1)] public bool Overflow1;
[MarshalAs(UnmanagedType.I1)] public bool Sign0;
[MarshalAs(UnmanagedType.I1)] public bool Sign1;
}
public struct NecDspState
{
public UInt16 A;
public NecDspAccFlags FlagsA;
public UInt16 B;
public NecDspAccFlags FlagsB;
public UInt16 TR;
public UInt16 TRB;
public UInt16 PC;
public UInt16 RP;
public UInt16 DP;
public UInt16 DR;
public UInt16 SR;
public UInt16 K;
public UInt16 L;
public UInt16 M;
public UInt16 N;
public UInt16 SerialOut;
public UInt16 SerialIn;
public byte SP;
}
public struct GsuFlags
{
[MarshalAs(UnmanagedType.I1)] public bool Zero;
[MarshalAs(UnmanagedType.I1)] public bool Carry;
[MarshalAs(UnmanagedType.I1)] public bool Sign;
[MarshalAs(UnmanagedType.I1)] public bool Overflow;
[MarshalAs(UnmanagedType.I1)] public bool Running;
[MarshalAs(UnmanagedType.I1)] public bool RomReadPending;
[MarshalAs(UnmanagedType.I1)] public bool Alt1;
[MarshalAs(UnmanagedType.I1)] public bool Alt2;
[MarshalAs(UnmanagedType.I1)] public bool ImmLow;
[MarshalAs(UnmanagedType.I1)] public bool ImmHigh;
[MarshalAs(UnmanagedType.I1)] public bool Prefix;
[MarshalAs(UnmanagedType.I1)] public bool Irq;
};
public struct GsuPixelCache
{
public byte X;
public byte Y;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Pixels;
public byte ValidBits;
};
public struct GsuState
{
public UInt64 CycleCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public UInt16[] R;
public GsuFlags SFR;
public byte RegisterLatch;
public byte ProgramBank;
public byte RomBank;
public byte RamBank;
[MarshalAs(UnmanagedType.I1)] public bool IrqDisabled;
[MarshalAs(UnmanagedType.I1)] public bool HighSpeedMode;
[MarshalAs(UnmanagedType.I1)] public bool ClockSelect;
[MarshalAs(UnmanagedType.I1)] public bool BackupRamEnabled;
public byte ScreenBase;
public byte ColorGradient;
public byte PlotBpp;
public byte ScreenHeight;
[MarshalAs(UnmanagedType.I1)] public bool GsuRamAccess;
[MarshalAs(UnmanagedType.I1)] public bool GsuRomAccess;
public UInt16 CacheBase;
[MarshalAs(UnmanagedType.I1)] public bool PlotTransparent;
[MarshalAs(UnmanagedType.I1)] public bool PlotDither;
[MarshalAs(UnmanagedType.I1)] public bool ColorHighNibble;
[MarshalAs(UnmanagedType.I1)] public bool ColorFreezeHigh;
[MarshalAs(UnmanagedType.I1)] public bool ObjMode;
public byte ColorReg;
public byte SrcReg;
public byte DestReg;
public byte RomReadBuffer;
public byte RomDelay;
public byte ProgramReadBuffer;
public UInt16 RamWriteAddress;
public byte RamWriteValue;
public byte RamDelay;
public UInt16 RamAddress;
public GsuPixelCache PrimaryCache;
public GsuPixelCache SecondaryCache;
};
public struct Cx4Dma
{
public UInt32 Source;
public UInt32 Dest;
public UInt16 Length;
public UInt32 Pos;
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
};
public struct Cx4Suspend
{
public UInt32 Duration;
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
};
public struct Cx4Cache
{
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
public byte Page;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I1)]
public bool[] Lock;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public UInt32[] Address;
public UInt32 Base;
public UInt16 ProgramBank;
public byte ProgramCounter;
public UInt16 Pos;
};
public struct Cx4Bus
{
[MarshalAs(UnmanagedType.I1)] public bool Enabled;
[MarshalAs(UnmanagedType.I1)] public bool Reading;
[MarshalAs(UnmanagedType.I1)] public bool Writing;
public byte DelayCycles;
public UInt32 Address;
};
public struct Cx4State
{
public UInt64 CycleCount;
public UInt16 PB;
public byte PC;
public UInt32 A;
public UInt16 P;
public byte SP;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public UInt32[] Stack;
public UInt64 Mult;
public UInt32 RomBuffer;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] RamBuffer;
public UInt32 MemoryDataReg;
public UInt32 MemoryAddressReg;
public UInt32 DataPointerReg;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public UInt32[] Regs;
[MarshalAs(UnmanagedType.I1)] public bool Negative;
[MarshalAs(UnmanagedType.I1)] public bool Zero;
[MarshalAs(UnmanagedType.I1)] public bool Carry;
[MarshalAs(UnmanagedType.I1)] public bool Overflow;
[MarshalAs(UnmanagedType.I1)] public bool IrqFlag;
[MarshalAs(UnmanagedType.I1)] public bool Stopped;
[MarshalAs(UnmanagedType.I1)] public bool Locked;
[MarshalAs(UnmanagedType.I1)] public bool IrqDisabled;
[MarshalAs(UnmanagedType.I1)] public bool SingleRom;
public byte RomAccessDelay;
public byte RamAccessDelay;
public Cx4Bus Bus;
public Cx4Dma Dma;
public Cx4Cache Cache;
public Cx4Suspend Suspend;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
public byte[] Vectors;
};
public struct AluState
{
public byte MultOperand1;
public byte MultOperand2;
public UInt16 MultOrRemainderResult;
public UInt16 Dividend;
public byte Divisor;
public UInt16 DivResult;
};
public struct InternalRegisterState
{
[MarshalAs(UnmanagedType.I1)] public bool EnableAutoJoypadRead;
[MarshalAs(UnmanagedType.I1)] public bool EnableFastRom;
[MarshalAs(UnmanagedType.I1)] public bool EnableNmi;
[MarshalAs(UnmanagedType.I1)] public bool EnableHorizontalIrq;
[MarshalAs(UnmanagedType.I1)] public bool EnableVerticalIrq;
public UInt16 HorizontalTimer;
public UInt16 VerticalTimer;
public byte IoPortOutput;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public UInt16[] ControllerData;
};
public struct DebugState
{
public UInt64 MasterClock;
public CpuState Cpu;
public PpuState Ppu;
public SpcState Spc;
public NecDspState NecDsp;
public CpuState Sa1;
public GsuState Gsu;
public Cx4State Cx4;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public DmaChannelConfig[] DmaChannels;
public InternalRegisterState InternalRegs;
public AluState Alu;
}
}

View file

@ -261,6 +261,7 @@
<Compile Include="Debugger\Config\DebuggerInfo.cs" />
<Compile Include="Debugger\Config\ScriptWindowConfig.cs" />
<Compile Include="Debugger\Config\SpriteViewerConfig.cs" />
<Compile Include="Debugger\Config\RegisterViewerConfig.cs" />
<Compile Include="Debugger\Config\TileViewerConfig.cs" />
<Compile Include="Debugger\Config\TilemapViewerConfig.cs" />
<Compile Include="Debugger\Controls\ctrlPanel.cs">
@ -326,6 +327,12 @@
<Compile Include="Debugger\PpuViewer\ctrlImageViewer.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Debugger\PpuViewer\ctrlPropertyList.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\PpuViewer\ctrlPropertyList.Designer.cs">
<DependentUpon>ctrlPropertyList.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\PpuViewer\ctrlSpriteList.cs">
<SubType>UserControl</SubType>
</Compile>
@ -338,6 +345,12 @@
<Compile Include="Debugger\PpuViewer\frmSpriteViewer.Designer.cs">
<DependentUpon>frmSpriteViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\PpuViewer\frmRegisterViewer.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Debugger\PpuViewer\frmRegisterViewer.Designer.cs">
<DependentUpon>frmRegisterViewer.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\PpuViewer\SpriteInfo.cs" />
<Compile Include="Debugger\PpuViewer\WindowRefreshManager.cs" />
<Compile Include="Debugger\Scripts\FastColoredTextBox\AutocompleteItem.cs" />
@ -799,6 +812,7 @@
<Compile Include="Forms\Tools\frmRecordAvi.Designer.cs">
<DependentUpon>frmRecordAvi.cs</DependentUpon>
</Compile>
<Compile Include="Interop\DebugState.cs" />
<Compile Include="Interop\RecordApi.cs" />
<Compile Include="Updates\frmDownloadProgress.cs">
<SubType>Form</SubType>
@ -960,6 +974,9 @@
<EmbeddedResource Include="Debugger\PpuViewer\ctrlImagePanel.resx">
<DependentUpon>ctrlImagePanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\PpuViewer\ctrlPropertyList.resx">
<DependentUpon>ctrlPropertyList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\PpuViewer\ctrlScanlineCycleSelect.resx">
<DependentUpon>ctrlScanlineCycleSelect.cs</DependentUpon>
</EmbeddedResource>
@ -972,6 +989,9 @@
<EmbeddedResource Include="Debugger\PpuViewer\frmSpriteViewer.resx">
<DependentUpon>frmSpriteViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\PpuViewer\frmRegisterViewer.resx">
<DependentUpon>frmRegisterViewer.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\PpuViewer\frmTileViewer.resx">
<DependentUpon>frmTileViewer.cs</DependentUpon>
</EmbeddedResource>