Added GSU (Super FX) support

This commit is contained in:
Sour 2019-07-30 22:34:52 -04:00
parent 468921eabb
commit 33cee67e61
81 changed files with 4174 additions and 214 deletions

View file

@ -10,6 +10,7 @@
#include "EmuSettings.h"
#include "NecDsp.h"
#include "Sa1.h"
#include "Gsu.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/VirtualFile.h"
#include "../Utilities/FolderUtilities.h"
@ -162,6 +163,15 @@ void BaseCartridge::Init()
_coprocessorType = GetCoprocessorType();
if(_coprocessorType != CoprocessorType::None && _cartInfo.ExpansionRamSize > 0 && _cartInfo.ExpansionRamSize <= 7) {
_coprocessorRamSize = _cartInfo.ExpansionRamSize > 0 ? 1024 * (1 << _cartInfo.ExpansionRamSize) : 0;
}
if(_coprocessorType == CoprocessorType::GSU && _coprocessorRamSize == 0) {
//Use a min of 64kb by default for GSU games
_coprocessorRamSize = 0x10000;
}
_saveRamSize = _cartInfo.SramSize > 0 ? 1024 * (1 << _cartInfo.SramSize) : 0;
_saveRam = new uint8_t[_saveRamSize];
_console->GetSettings()->InitializeRam(_saveRam, _saveRamSize);
@ -174,7 +184,7 @@ CoprocessorType BaseCartridge::GetCoprocessorType()
if((_cartInfo.RomType & 0x0F) >= 0x03) {
switch((_cartInfo.RomType & 0xF0) >> 4) {
case 0x00: return GetDspVersion(); break;
case 0x01: return CoprocessorType::GSU1; break; //Or mariochip1/gsu2
case 0x01: return CoprocessorType::GSU; break;
case 0x02: return CoprocessorType::OBC1; break;
case 0x03: return CoprocessorType::SA1; break;
case 0x04: return CoprocessorType::DD1; break;
@ -224,7 +234,9 @@ CoprocessorType BaseCartridge::GetDspVersion()
void BaseCartridge::Reset()
{
_coprocessor->Reset();
if(_coprocessor) {
_coprocessor->Reset();
}
}
RomInfo BaseCartridge::GetRomInfo()
@ -300,7 +312,7 @@ void BaseCartridge::Init(MemoryMappings &mm)
void BaseCartridge::RegisterHandlers(MemoryMappings &mm)
{
if(MapSpecificCarts(mm)) {
if(_coprocessorType == CoprocessorType::GSU || MapSpecificCarts(mm)) {
return;
}
@ -351,6 +363,9 @@ void BaseCartridge::InitCoprocessor()
if(_coprocessorType == CoprocessorType::SA1) {
_coprocessor.reset(new Sa1(_console));
_sa1 = dynamic_cast<Sa1*>(_coprocessor.get());
} else if(_coprocessorType == CoprocessorType::GSU) {
_coprocessor.reset(new Gsu(_console, _coprocessorRamSize));
_gsu = dynamic_cast<Gsu*>(_coprocessor.get());
}
}
@ -459,9 +474,7 @@ void BaseCartridge::DisplayCartInfo()
case CoprocessorType::DSP2: coProcMessage += "DSP2"; break;
case CoprocessorType::DSP3: coProcMessage += "DSP3"; break;
case CoprocessorType::DSP4: coProcMessage += "DSP4"; break;
case CoprocessorType::GSU1: coProcMessage += "Super FX (GSU1)"; break;
case CoprocessorType::GSU2: coProcMessage += "Super FX (GSU2)"; break;
case CoprocessorType::MarioChip: coProcMessage += "Super FX (Mario Chip 1)"; break;
case CoprocessorType::GSU: coProcMessage += "Super FX (GSU1/2)"; break;
case CoprocessorType::OBC1: coProcMessage += "OBC1"; break;
case CoprocessorType::RTC: coProcMessage += "RTC"; break;
case CoprocessorType::SA1: coProcMessage += "SA1"; break;
@ -489,6 +502,9 @@ void BaseCartridge::DisplayCartInfo()
if(_saveRamSize > 0) {
MessageManager::Log("SRAM size: " + std::to_string(_saveRamSize / 1024) + " KB");
}
if(_coprocessorRamSize > 0) {
MessageManager::Log("Coprocessor RAM size: " + std::to_string(_coprocessorRamSize / 1024) + " KB");
}
MessageManager::Log("-----------------------------");
}
@ -502,6 +518,19 @@ Sa1* BaseCartridge::GetSa1()
return _sa1;
}
Gsu* BaseCartridge::GetGsu()
{
return _gsu;
}
void BaseCartridge::RunCoprocessors()
{
//These coprocessors are run at the end of the frame, or as needed
if(_necDsp) {
_necDsp->Run();
}
}
BaseCoprocessor* BaseCartridge::GetCoprocessor()
{
return _coprocessor.get();

View file

@ -10,6 +10,7 @@ class VirtualFile;
class EmuSettings;
class NecDsp;
class Sa1;
class Gsu;
class Console;
class BaseCartridge : public ISerializable
@ -24,6 +25,7 @@ private:
unique_ptr<BaseCoprocessor> _coprocessor;
NecDsp *_necDsp = nullptr;
Sa1 *_sa1 = nullptr;
Gsu *_gsu = nullptr;
CartFlags::CartFlags _flags = CartFlags::CartFlags::None;
CoprocessorType _coprocessorType = CoprocessorType::None;
@ -35,6 +37,7 @@ private:
uint32_t _prgRomSize = 0;
uint32_t _saveRamSize = 0;
uint32_t _coprocessorRamSize = 0;
void LoadBattery();
@ -76,6 +79,10 @@ public:
NecDsp* GetDsp();
Sa1* GetSa1();
Gsu* GetGsu();
void RunCoprocessors();
BaseCoprocessor* GetCoprocessor();
vector<unique_ptr<IMemoryHandler>>& GetPrgRomHandlers();

View file

@ -6,9 +6,9 @@
class BaseCoprocessor : public ISerializable, public IMemoryHandler
{
public:
virtual void Run() = 0;
virtual void Reset() = 0;
virtual void ProcessEndOfFrame() { }
virtual void LoadBattery(string filePath) { }
virtual void SaveBattery(string filePath) { }
};

View file

@ -1,10 +1,11 @@
#include "stdafx.h"
#include "Breakpoint.h"
#include "DebugTypes.h"
#include "DebugUtilities.h"
bool Breakpoint::Matches(uint32_t memoryAddr, AddressInfo &info)
{
if(_memoryType <= SnesMemoryType::Sa1Memory) {
if(_memoryType <= DebugUtilities::GetLastCpuMemoryType()) {
if(_startAddr == -1) {
return true;
} else if(_endAddr == -1) {

View file

@ -3,6 +3,7 @@
#include "DebugTypes.h"
#include "Debugger.h"
#include "Breakpoint.h"
#include "DebugUtilities.h"
#include "ExpressionEvaluator.h"
BreakpointManager::BreakpointManager(Debugger *debugger)
@ -12,7 +13,7 @@ BreakpointManager::BreakpointManager(Debugger *debugger)
void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
{
for(int j = 0; j < (int)CpuType::Sa1 + 1; j++) {
for(int j = 0; j <= (int)DebugUtilities::GetLastCpuType(); j++) {
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
_breakpoints[j][i].clear();
_rpnList[j][i].clear();
@ -22,6 +23,8 @@ void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
_bpExpEval[(int)CpuType::Cpu].reset(new ExpressionEvaluator(_debugger, CpuType::Cpu));
_bpExpEval[(int)CpuType::Spc].reset(new ExpressionEvaluator(_debugger, CpuType::Spc));
_bpExpEval[(int)CpuType::Sa1].reset(new ExpressionEvaluator(_debugger, CpuType::Sa1));
_bpExpEval[(int)CpuType::Gsu].reset(new ExpressionEvaluator(_debugger, CpuType::Gsu));
for(uint32_t j = 0; j < count; j++) {
Breakpoint &bp = breakpoints[j];

View file

@ -2,6 +2,7 @@
#include "stdafx.h"
#include "Breakpoint.h"
#include "DebugTypes.h"
#include "DebugUtilities.h"
class ExpressionEvaluator;
class Debugger;
@ -15,11 +16,11 @@ private:
Debugger *_debugger;
vector<Breakpoint> _breakpoints[(int)CpuType::Sa1 + 1][BreakpointTypeCount];
vector<ExpressionData> _rpnList[(int)CpuType::Sa1 + 1][BreakpointTypeCount];
bool _hasBreakpoint[(int)CpuType::Sa1 + 1][BreakpointTypeCount] = {};
vector<Breakpoint> _breakpoints[(int)DebugUtilities::GetLastCpuType() + 1][BreakpointTypeCount];
vector<ExpressionData> _rpnList[(int)DebugUtilities::GetLastCpuType() + 1][BreakpointTypeCount];
bool _hasBreakpoint[(int)DebugUtilities::GetLastCpuType() + 1][BreakpointTypeCount] = {};
unique_ptr<ExpressionEvaluator> _bpExpEval[(int)CpuType::Sa1 + 1];
unique_ptr<ExpressionEvaluator> _bpExpEval[(int)DebugUtilities::GetLastCpuType() + 1];
BreakpointType GetBreakpointType(MemoryOperationType type);

View file

@ -33,9 +33,7 @@ enum class CoprocessorType
DSP2,
DSP3,
DSP4,
GSU1,
GSU2,
MarioChip,
GSU,
OBC1,
SA1,
DD1,

View file

@ -107,9 +107,11 @@ void Console::Run()
_cpu->Exec();
if(previousFrameCount != _ppu->GetFrameCount()) {
_cart->RunCoprocessors();
if(_cart->GetCoprocessor()) {
_cart->GetCoprocessor()->Run();
_cart->GetCoprocessor()->ProcessEndOfFrame();
}
_rewindManager->ProcessEndOfFrame();
WaitForLock();
@ -169,6 +171,11 @@ void Console::RunSingleFrame()
_cpu->Exec();
}
_cart->RunCoprocessors();
if(_cart->GetCoprocessor()) {
_cart->GetCoprocessor()->ProcessEndOfFrame();
}
_controlManager->UpdateControlDevices();
}
@ -231,7 +238,7 @@ void Console::Reset()
_spc->Reset();
_ppu->Reset();
_cpu->Reset();
//_cart->Reset();
_cart->Reset();
//_controlManager->Reset();
_notificationManager->SendNotification(ConsoleNotificationType::GameReset);
@ -673,9 +680,7 @@ void Console::ProcessPpuCycle()
if(_debugger) {
_debugger->ProcessPpuCycle();
_spc->Run();
if(_cart->GetCoprocessor()) {
_cart->GetCoprocessor()->Run();
}
_cart->RunCoprocessors();
}
}
@ -697,10 +702,12 @@ void Console::ProcessEvent(EventType type)
template void Console::ProcessMemoryRead<CpuType::Cpu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryRead<CpuType::Sa1>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryRead<CpuType::Spc>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryRead<CpuType::Gsu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryWrite<CpuType::Cpu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryWrite<CpuType::Sa1>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryWrite<CpuType::Spc>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessMemoryWrite<CpuType::Gsu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Console::ProcessInterrupt<CpuType::Cpu>(uint32_t originalPc, uint32_t currentPc, bool forNmi);
template void Console::ProcessInterrupt<CpuType::Sa1>(uint32_t originalPc, uint32_t currentPc, bool forNmi);

View file

@ -51,6 +51,12 @@
<ClInclude Include="Cpu.Shared.h" />
<ClInclude Include="CpuDebugger.h" />
<ClInclude Include="DebugUtilities.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="MemoryMappings.h" />
<ClInclude Include="BaseRenderer.h" />
<ClInclude Include="BaseSoundManager.h" />
@ -184,6 +190,10 @@
<ClCompile Include="EmuSettings.cpp" />
<ClCompile Include="EventManager.cpp" />
<ClCompile Include="ExpressionEvaluator.cpp" />
<ClCompile Include="Gsu.cpp" />
<ClCompile Include="Gsu.Instructions.cpp" />
<ClCompile Include="GsuDebugger.cpp" />
<ClCompile Include="GsuDisUtils.cpp" />
<ClCompile Include="InternalRegisters.cpp" />
<ClCompile Include="KeyManager.cpp" />
<ClCompile Include="LabelManager.cpp" />

View file

@ -329,10 +329,30 @@
<ClInclude Include="CpuDebugger.h">
<Filter>Debugger\Debuggers</Filter>
</ClInclude>
<ClInclude Include="Cpu.Instructions.h" />
<ClInclude Include="Cpu.Shared.h">
<Filter>SNES</Filter>
</ClInclude>
<ClInclude Include="GsuTypes.h">
<Filter>SNES\Coprocessors\GSU</Filter>
</ClInclude>
<ClInclude Include="Gsu.h">
<Filter>SNES\Coprocessors\GSU</Filter>
</ClInclude>
<ClInclude Include="GsuDebugger.h">
<Filter>Debugger\Debuggers</Filter>
</ClInclude>
<ClInclude Include="GsuDisUtils.h">
<Filter>Debugger\Disassembler</Filter>
</ClInclude>
<ClInclude Include="Cpu.Instructions.h">
<Filter>SNES</Filter>
</ClInclude>
<ClInclude Include="GsuRomHandler.h">
<Filter>SNES\Coprocessors\GSU</Filter>
</ClInclude>
<ClInclude Include="GsuRamHandler.h">
<Filter>SNES\Coprocessors\GSU</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp" />
@ -537,6 +557,18 @@
<ClCompile Include="CpuDebugger.cpp">
<Filter>Debugger\Debuggers</Filter>
</ClCompile>
<ClCompile Include="Gsu.cpp">
<Filter>SNES\Coprocessors\GSU</Filter>
</ClCompile>
<ClCompile Include="Gsu.Instructions.cpp">
<Filter>SNES\Coprocessors\GSU</Filter>
</ClCompile>
<ClCompile Include="GsuDebugger.cpp">
<Filter>Debugger\Debuggers</Filter>
</ClCompile>
<ClCompile Include="GsuDisUtils.cpp">
<Filter>Debugger\Disassembler</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="SNES">
@ -581,5 +613,8 @@
<Filter Include="Debugger\Debuggers">
<UniqueIdentifier>{799edb31-b81c-4842-a1e5-a81d5b28459a}</UniqueIdentifier>
</Filter>
<Filter Include="SNES\Coprocessors\GSU">
<UniqueIdentifier>{5bda57b5-9204-46f4-85f5-3b550c589a18}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View file

@ -66,7 +66,7 @@ void CpuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType
}
_codeDataLogger->SetFlags(addressInfo.Address, flags);
}
_disassembler->BuildCache(addressInfo, state.PS, _cpuType);
_disassembler->BuildCache(addressInfo, state.PS & (ProcFlags::IndexMode8 | ProcFlags::MemoryMode8), _cpuType);
}
DebugState debugState;

View file

@ -4,6 +4,7 @@
#include "PpuTypes.h"
#include "SpcTypes.h"
#include "NecDspTypes.h"
#include "GsuTypes.h"
struct DebugState
{
@ -13,6 +14,7 @@ struct DebugState
SpcState Spc;
NecDspState Dsp;
CpuState Sa1;
GsuState Gsu;
};
enum class SnesMemoryType
@ -20,6 +22,7 @@ enum class SnesMemoryType
CpuMemory,
SpcMemory,
Sa1Memory,
GsuMemory,
PrgRom,
WorkRam,
SaveRam,
@ -32,6 +35,7 @@ enum class SnesMemoryType
DspDataRom,
DspDataRam,
Sa1InternalRam,
GsuWorkRam,
Register,
};
@ -253,5 +257,5 @@ enum class CpuType : uint8_t
Spc,
NecDsp,
Sa1,
//SuperFx,
Gsu,
};

View file

@ -11,9 +11,20 @@ public:
case CpuType::Cpu: return SnesMemoryType::CpuMemory;
case CpuType::Spc: return SnesMemoryType::SpcMemory;
case CpuType::Sa1: return SnesMemoryType::Sa1Memory;
case CpuType::Gsu: return SnesMemoryType::GsuMemory;
case CpuType::NecDsp: break;
}
throw std::runtime_error("Invalid CPU type");
}
static constexpr SnesMemoryType GetLastCpuMemoryType()
{
return SnesMemoryType::GsuMemory;
}
static constexpr CpuType GetLastCpuType()
{
return CpuType::Gsu;
}
};

View file

@ -6,9 +6,11 @@
#include "Ppu.h"
#include "Spc.h"
#include "Sa1.h"
#include "Gsu.h"
#include "NecDsp.h"
#include "CpuDebugger.h"
#include "SpcDebugger.h"
#include "GsuDebugger.h"
#include "BaseCartridge.h"
#include "MemoryManager.h"
#include "EmuSettings.h"
@ -48,6 +50,7 @@ Debugger::Debugger(shared_ptr<Console> console)
_watchExpEval[(int)CpuType::Cpu].reset(new ExpressionEvaluator(this, CpuType::Cpu));
_watchExpEval[(int)CpuType::Spc].reset(new ExpressionEvaluator(this, CpuType::Spc));
_watchExpEval[(int)CpuType::Sa1].reset(new ExpressionEvaluator(this, CpuType::Sa1));
_watchExpEval[(int)CpuType::Gsu].reset(new ExpressionEvaluator(this, CpuType::Gsu));
_codeDataLogger.reset(new CodeDataLogger(_cart->DebugGetPrgRomSize(), _memoryManager.get()));
_memoryDumper.reset(new MemoryDumper(_ppu, console->GetSpc(), _memoryManager, _cart));
@ -63,6 +66,8 @@ Debugger::Debugger(shared_ptr<Console> console)
_spcDebugger.reset(new SpcDebugger(this));
if(_cart->GetSa1()) {
_sa1Debugger.reset(new CpuDebugger(this, CpuType::Sa1));
} else if(_cart->GetGsu()) {
_gsuDebugger.reset(new GsuDebugger(this));
}
_step.reset(new StepRequest());
@ -106,8 +111,9 @@ void Debugger::ProcessMemoryRead(uint32_t addr, uint8_t value, MemoryOperationTy
{
switch(type) {
case CpuType::Cpu: _cpuDebugger->ProcessRead(addr, value, opType); break;
case CpuType::Sa1: _sa1Debugger->ProcessRead(addr, value, opType); break;
case CpuType::Spc: _spcDebugger->ProcessRead(addr, value, opType); break;
case CpuType::Sa1: _sa1Debugger->ProcessRead(addr, value, opType); break;
case CpuType::Gsu: _gsuDebugger->ProcessRead(addr, value, opType); break;
}
}
@ -116,8 +122,9 @@ void Debugger::ProcessMemoryWrite(uint32_t addr, uint8_t value, MemoryOperationT
{
switch(type) {
case CpuType::Cpu: _cpuDebugger->ProcessWrite(addr, value, opType); break;
case CpuType::Sa1: _sa1Debugger->ProcessWrite(addr, value, opType); break;
case CpuType::Spc: _spcDebugger->ProcessWrite(addr, value, opType); break;
case CpuType::Sa1: _sa1Debugger->ProcessWrite(addr, value, opType); break;
case CpuType::Gsu: _gsuDebugger->ProcessWrite(addr, value, opType); break;
}
}
@ -200,6 +207,8 @@ void Debugger::SleepUntilResume(BreakSource source, MemoryOperationInfo *operati
_disassembler->Disassemble(CpuType::Spc);
if(_cart->GetSa1()) {
_disassembler->Disassemble(CpuType::Sa1);
} else if(_cart->GetGsu()) {
_disassembler->Disassemble(CpuType::Gsu);
}
_executionStopped = true;
@ -283,6 +292,9 @@ void Debugger::Run()
if(_sa1Debugger) {
_sa1Debugger->Run();
}
if(_gsuDebugger) {
_gsuDebugger->Run();
}
_waitForBreakResume = false;
}
@ -295,6 +307,9 @@ void Debugger::Step(CpuType cpuType, int32_t stepCount, StepType type)
if(_sa1Debugger) {
_sa1Debugger->Run();
}
if(_gsuDebugger) {
_gsuDebugger->Run();
}
switch(type) {
case StepType::PpuStep: step.PpuStepCount = stepCount; break;
@ -305,6 +320,7 @@ void Debugger::Step(CpuType cpuType, int32_t stepCount, StepType type)
case CpuType::Cpu: _cpuDebugger->Step(stepCount, type); break;
case CpuType::Spc: _spcDebugger->Step(stepCount, type); break;
case CpuType::Sa1: _sa1Debugger->Step(stepCount, type); break;
case CpuType::Gsu: _gsuDebugger->Step(stepCount, type); break;
case CpuType::NecDsp: throw std::runtime_error("Step(): Unsupported CPU type.");
}
break;
@ -349,6 +365,9 @@ void Debugger::GetState(DebugState &state, bool partialPpuState)
if(_cart->GetSa1()) {
state.Sa1 = _cart->GetSa1()->GetCpuState();
}
if(_cart->GetGsu()) {
state.Gsu = _cart->GetGsu()->GetState();
}
}
AddressInfo Debugger::GetAbsoluteAddress(AddressInfo relAddress)
@ -363,6 +382,8 @@ AddressInfo Debugger::GetAbsoluteAddress(AddressInfo relAddress)
return _spc->GetAbsoluteAddress(relAddress.Address);
} else if(relAddress.Type == SnesMemoryType::Sa1Memory) {
return _cart->GetSa1()->GetMemoryMappings()->GetAbsoluteAddress(relAddress.Address);
} else if(relAddress.Type == SnesMemoryType::GsuMemory) {
return _cart->GetGsu()->GetMemoryMappings()->GetAbsoluteAddress(relAddress.Address);
}
throw std::runtime_error("Unsupported address type");
@ -468,6 +489,8 @@ shared_ptr<CallstackManager> Debugger::GetCallstackManager(CpuType cpuType)
case CpuType::Cpu: return _cpuDebugger->GetCallstackManager();
case CpuType::Spc: return _spcDebugger->GetCallstackManager();
case CpuType::Sa1: return _sa1Debugger->GetCallstackManager();
case CpuType::Gsu:
case CpuType::NecDsp: break;
}
throw std::runtime_error("GetCallstackManager() - Unsupported CPU type");
@ -481,10 +504,12 @@ shared_ptr<Console> Debugger::GetConsole()
template void Debugger::ProcessMemoryRead<CpuType::Cpu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Sa1>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Spc>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryRead<CpuType::Gsu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryWrite<CpuType::Cpu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryWrite<CpuType::Sa1>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryWrite<CpuType::Spc>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessMemoryWrite<CpuType::Gsu>(uint32_t addr, uint8_t value, MemoryOperationType opType);
template void Debugger::ProcessInterrupt<CpuType::Cpu>(uint32_t originalPc, uint32_t currentPc, bool forNmi);
template void Debugger::ProcessInterrupt<CpuType::Sa1>(uint32_t originalPc, uint32_t currentPc, bool forNmi);

View file

@ -26,6 +26,7 @@ class LabelManager;
class ScriptManager;
class SpcDebugger;
class CpuDebugger;
class GsuDebugger;
enum class EventType;
enum class EvalResultType : int32_t;
@ -44,6 +45,7 @@ private:
unique_ptr<SpcDebugger> _spcDebugger;
unique_ptr<CpuDebugger> _cpuDebugger;
unique_ptr<CpuDebugger> _sa1Debugger;
unique_ptr<GsuDebugger> _gsuDebugger;
shared_ptr<ScriptManager> _scriptManager;
shared_ptr<TraceLogger> _traceLogger;
@ -56,7 +58,7 @@ private:
shared_ptr<EventManager> _eventManager;
shared_ptr<LabelManager> _labelManager;
unique_ptr<ExpressionEvaluator> _watchExpEval[(int)CpuType::Sa1 + 1];
unique_ptr<ExpressionEvaluator> _watchExpEval[(int)CpuType::Gsu + 1];
atomic<bool> _executionStopped;
atomic<uint32_t> _breakRequestCount;

View file

@ -6,6 +6,7 @@
#include "Spc.h"
#include "NecDsp.h"
#include "Sa1.h"
#include "Gsu.h"
#include "Debugger.h"
#include "MemoryManager.h"
#include "LabelManager.h"
@ -49,6 +50,9 @@ Disassembler::Disassembler(shared_ptr<Console> console, shared_ptr<CodeDataLogge
_sa1InternalRam = console->GetCartridge()->GetSa1() ? console->GetCartridge()->GetSa1()->DebugGetInternalRam() : nullptr;
_sa1InternalRamSize = console->GetCartridge()->GetSa1() ? console->GetCartridge()->GetSa1()->DebugGetInternalRamSize() : 0;
_gsuWorkRam = console->GetCartridge()->GetGsu() ? console->GetCartridge()->GetGsu()->DebugGetWorkRam() : nullptr;
_gsuWorkRamSize = console->GetCartridge()->GetGsu() ? console->GetCartridge()->GetGsu()->DebugGetWorkRamSize() : 0;
_prgCache = vector<DisassemblyInfo>(_prgRomSize);
_sramCache = vector<DisassemblyInfo>(_sramSize);
_wramCache = vector<DisassemblyInfo>(_wramSize);
@ -56,6 +60,11 @@ Disassembler::Disassembler(shared_ptr<Console> console, shared_ptr<CodeDataLogge
_spcRomCache = vector<DisassemblyInfo>(_spcRomSize);
_necDspRomCache = vector<DisassemblyInfo>(_necDspProgramRomSize);
_sa1InternalRamCache = vector<DisassemblyInfo>(_sa1InternalRamSize);
_gsuWorkRamCache = vector<DisassemblyInfo>(_gsuWorkRamSize);
for(int i = 0; i < (int)DebugUtilities::GetLastCpuType(); i++) {
_needDisassemble[i] = true;
}
}
void Disassembler::GetSource(AddressInfo &info, uint8_t **source, uint32_t &size, vector<DisassemblyInfo> **cache)
@ -103,6 +112,12 @@ void Disassembler::GetSource(AddressInfo &info, uint8_t **source, uint32_t &size
size = _sa1InternalRamSize;
break;
case SnesMemoryType::GsuWorkRam:
*source = _gsuWorkRam;
*cache = &_gsuWorkRamCache;
size = _gsuWorkRamSize;
break;
default:
throw std::runtime_error("Disassembler::GetSource() invalid memory type");
}
@ -114,6 +129,7 @@ vector<DisassemblyResult>& Disassembler::GetDisassemblyList(CpuType type)
case CpuType::Cpu: return _disassembly;
case CpuType::Spc: return _spcDisassembly;
case CpuType::Sa1: return _sa1Disassembly;
case CpuType::Gsu: return _gsuDisassembly;
case CpuType::NecDsp: break;
}
throw std::runtime_error("Disassembly::GetDisassemblyList(): Invalid cpu type");
@ -156,9 +172,10 @@ uint32_t Disassembler::BuildCache(AddressInfo &addrInfo, uint8_t cpuFlags, CpuTy
void Disassembler::SetDisassembleFlag(CpuType type)
{
if(type == CpuType::Cpu || type == CpuType::Sa1) {
if(type == CpuType::Cpu || type == CpuType::Sa1 || type == CpuType::Gsu) {
_needDisassemble[(int)CpuType::Cpu] = true;
_needDisassemble[(int)CpuType::Sa1] = true;
_needDisassemble[(int)CpuType::Gsu] = true;
} else if(type == CpuType::Spc) {
_needDisassemble[(int)CpuType::Spc] = true;
} else {
@ -171,6 +188,7 @@ void Disassembler::ResetPrgCache()
_prgCache = vector<DisassemblyInfo>(_prgRomSize);
_needDisassemble[(int)CpuType::Cpu] = true;
_needDisassemble[(int)CpuType::Sa1] = true;
_needDisassemble[(int)CpuType::Gsu] = true;
}
void Disassembler::InvalidateCache(AddressInfo addrInfo, CpuType type)
@ -208,7 +226,28 @@ void Disassembler::Disassemble(CpuType cpuType)
auto lock = _disassemblyLock.AcquireSafe();
bool isSpc = cpuType == CpuType::Spc;
MemoryMappings *mappings = cpuType == CpuType::Sa1 ? _console->GetCartridge()->GetSa1()->GetMemoryMappings() : _memoryManager->GetMemoryMappings();
MemoryMappings *mappings = nullptr;
switch(cpuType) {
case CpuType::Cpu: mappings = _memoryManager->GetMemoryMappings(); break;
case CpuType::Sa1:
if(!_console->GetCartridge()->GetSa1()) {
return;
}
mappings = _console->GetCartridge()->GetSa1()->GetMemoryMappings();
break;
case CpuType::Gsu:
if(!_console->GetCartridge()->GetGsu()) {
return;
}
mappings = _console->GetCartridge()->GetGsu()->GetMemoryMappings();
break;
case CpuType::Spc: mappings = nullptr; break;
default: throw std::runtime_error("Disassemble(): Invalid cpu type");
}
vector<DisassemblyResult> &results = GetDisassemblyList(cpuType);
int32_t maxAddr = isSpc ? 0xFFFF : 0xFFFFFF;
results.clear();
@ -462,11 +501,12 @@ bool Disassembler::GetLineData(CpuType type, uint32_t lineIndex, CodeLineData &d
vector<DisassemblyInfo> *cache;
GetSource(result.Address, &source, sourceLength, &cache);
DisassemblyInfo disInfo = (*cache)[result.Address.Address];
CpuType lineCpuType = disInfo.IsInitialized() ? disInfo.GetCpuType() : type;
data.Address = result.CpuAddress;
data.AbsoluteAddress = result.Address.Address;
switch(type) {
switch(lineCpuType) {
case CpuType::Cpu:
case CpuType::Sa1: {
CpuState state = _console->GetCpu()->GetState();
@ -511,6 +551,19 @@ bool Disassembler::GetLineData(CpuType type, uint32_t lineIndex, CodeLineData &d
break;
}
case CpuType::Gsu: {
if(!disInfo.IsInitialized()) {
disInfo = DisassemblyInfo(source + result.Address.Address, 0, CpuType::Gsu);
} else {
data.Flags |= LineFlags::VerifiedCode;
}
data.OpSize = disInfo.GetOpSize();
data.EffectiveAddress = -1;
data.ValueSize = 0;
break;
}
case CpuType::NecDsp:
throw std::runtime_error("GetLineData - CPU type not supported");
}

View file

@ -2,6 +2,7 @@
#include "stdafx.h"
#include "DisassemblyInfo.h"
#include "DebugTypes.h"
#include "DebugUtilities.h"
#include "../Utilities/SimpleLock.h"
class MemoryManager;
@ -32,13 +33,15 @@ private:
vector<DisassemblyInfo> _spcRomCache;
vector<DisassemblyInfo> _necDspRomCache;
vector<DisassemblyInfo> _sa1InternalRamCache;
vector<DisassemblyInfo> _gsuWorkRamCache;
SimpleLock _disassemblyLock;
vector<DisassemblyResult> _disassembly;
vector<DisassemblyResult> _spcDisassembly;
vector<DisassemblyResult> _sa1Disassembly;
vector<DisassemblyResult> _gsuDisassembly;
bool _needDisassemble[(int)CpuType::Sa1+1] = { true, true, true, true };
bool _needDisassemble[(int)DebugUtilities::GetLastCpuType()+1];
uint8_t *_prgRom;
uint32_t _prgRomSize;
@ -57,6 +60,9 @@ private:
uint8_t *_sa1InternalRam;
uint32_t _sa1InternalRamSize;
uint8_t *_gsuWorkRam;
uint32_t _gsuWorkRamSize;
void GetSource(AddressInfo &info, uint8_t **source, uint32_t &size, vector<DisassemblyInfo> **cache);
vector<DisassemblyResult>& GetDisassemblyList(CpuType type);
void SetDisassembleFlag(CpuType type);

View file

@ -5,6 +5,7 @@
#include "MemoryDumper.h"
#include "CpuDisUtils.h"
#include "SpcDisUtils.h"
#include "GsuDisUtils.h"
#include "NecDspDisUtils.h"
#include "../Utilities/HexUtilities.h"
#include "../Utilities/FastString.h"
@ -21,7 +22,7 @@ DisassemblyInfo::DisassemblyInfo(uint8_t *opPointer, uint8_t cpuFlags, CpuType t
void DisassemblyInfo::Initialize(uint8_t *opPointer, uint8_t cpuFlags, CpuType type)
{
_cpuType = type;
_flags = cpuFlags & (ProcFlags::MemoryMode8 | ProcFlags::IndexMode8);
_flags = cpuFlags;
_opSize = GetOpSize(opPointer[0], _flags, _cpuType);
memcpy(_byteCode, opPointer, _opSize);
@ -35,7 +36,7 @@ bool DisassemblyInfo::IsInitialized()
bool DisassemblyInfo::IsValid(uint8_t cpuFlags)
{
return _flags == (cpuFlags & (ProcFlags::MemoryMode8 | ProcFlags::IndexMode8));
return _flags == cpuFlags;
}
void DisassemblyInfo::Reset()
@ -53,6 +54,7 @@ void DisassemblyInfo::GetDisassembly(string &out, uint32_t memoryAddr, LabelMana
case CpuType::Spc: SpcDisUtils::GetDisassembly(*this, out, memoryAddr, labelManager); break;
case CpuType::NecDsp: NecDspDisUtils::GetDisassembly(*this, out, memoryAddr, labelManager); break;
case CpuType::Gsu: GsuDisUtils::GetDisassembly(*this, out, memoryAddr, labelManager); break;
}
}
@ -64,11 +66,18 @@ int32_t DisassemblyInfo::GetEffectiveAddress(Console *console, void *cpuState)
return CpuDisUtils::GetEffectiveAddress(*this, console, *(CpuState*)cpuState);
case CpuType::Spc: return SpcDisUtils::GetEffectiveAddress(*this, console, *(SpcState*)cpuState);
case CpuType::Gsu:
case CpuType::NecDsp: return -1;
}
return -1;
}
CpuType DisassemblyInfo::GetCpuType()
{
return _cpuType;
}
uint8_t DisassemblyInfo::GetOpCode()
{
return _byteCode[0];
@ -114,6 +123,17 @@ uint8_t DisassemblyInfo::GetOpSize(uint8_t opCode, uint8_t flags, CpuType type)
return CpuDisUtils::GetOpSize(opCode, flags);
case CpuType::Spc: return SpcDisUtils::GetOpSize(opCode);
case CpuType::Gsu:
if(opCode >= 0x05 && opCode <= 0x0F) {
return 2;
} else if(opCode >= 0xA0 && opCode <= 0xAF) {
return 2;
} else if(opCode >= 0xF0 && opCode <= 0xFF) {
return 3;
}
return 1;
case CpuType::NecDsp: return 4;
}
return 0;
@ -127,6 +147,8 @@ bool DisassemblyInfo::IsJumpToSub(uint8_t opCode, CpuType type)
return opCode == 0x20 || opCode == 0x22 || opCode == 0xFC; //JSR, JSL
case CpuType::Spc: return opCode == 0x3F || opCode == 0x0F; //JSR, BRK
case CpuType::Gsu:
case CpuType::NecDsp: return false;
}
return false;
@ -141,6 +163,8 @@ bool DisassemblyInfo::IsReturnInstruction(uint8_t opCode, CpuType type)
return opCode == 0x60 || opCode == 0x6B || opCode == 0x40;
case CpuType::Spc: return opCode == 0x6F || opCode == 0x7F;
case CpuType::Gsu:
case CpuType::NecDsp: return false;
}
@ -170,6 +194,7 @@ bool DisassemblyInfo::UpdateCpuFlags(uint8_t &cpuFlags)
}
return true;
case CpuType::Gsu:
case CpuType::Spc:
case CpuType::NecDsp: return false;
}

View file

@ -28,6 +28,7 @@ public:
void GetDisassembly(string &out, uint32_t memoryAddr, LabelManager *labelManager);
CpuType GetCpuType();
uint8_t GetOpCode();
uint8_t GetOpSize();
uint8_t GetFlags();

View file

@ -71,60 +71,139 @@ bool ExpressionEvaluator::CheckSpecialTokens(string expression, size_t &pos, str
}
} while(pos < len);
if(token == "a") {
output += std::to_string((int64_t)EvalValues::RegA);
} else if(token == "x") {
output += std::to_string((int64_t)EvalValues::RegX);
} else if(token == "y") {
output += std::to_string((int64_t)EvalValues::RegY);
} else if(token == "ps") {
output += std::to_string((int64_t)EvalValues::RegPS);
} else if(token == "sp") {
output += std::to_string((int64_t)EvalValues::RegSP);
} else if(token == "pc") {
output += std::to_string((int64_t)EvalValues::RegPC);
} else if(token == "oppc") {
output += std::to_string((int64_t)EvalValues::RegOpPC);
} else if(token == "previousoppc") {
output += std::to_string((int64_t)EvalValues::PreviousOpPC);
} else if(token == "frame") {
output += std::to_string((int64_t)EvalValues::PpuFrameCount);
} else if(token == "cycle") {
output += std::to_string((int64_t)EvalValues::PpuCycle);
} else if(token == "scanline") {
output += std::to_string((int64_t)EvalValues::PpuScanline);
} else if(token == "irq") {
output += std::to_string((int64_t)EvalValues::Irq);
} else if(token == "nmi") {
output += std::to_string((int64_t)EvalValues::Nmi);
} else if(token == "value") {
output += std::to_string((int64_t)EvalValues::Value);
} else if(token == "address") {
output += std::to_string((int64_t)EvalValues::Address);
} else if(token == "romaddress") {
output += std::to_string((int64_t)EvalValues::AbsoluteAddress);
} else if(token == "iswrite") {
output += std::to_string((int64_t)EvalValues::IsWrite);
} else if(token == "isread") {
output += std::to_string((int64_t)EvalValues::IsRead);
} else {
string originalExpression = expression.substr(initialPos, pos - initialPos);
bool validLabel = _labelManager->ContainsLabel(originalExpression);
if(!validLabel) {
//Check if a multi-byte label exists for this name
string label = originalExpression + "+0";
validLabel = _labelManager->ContainsLabel(label);
if(_cpuType == CpuType::Gsu) {
int64_t gsuToken = ProcessGsuTokens(token);
if(gsuToken != -1) {
output += std::to_string(gsuToken);
return true;
}
if(validLabel) {
data.Labels.push_back(originalExpression);
output += std::to_string(EvalValues::FirstLabelIndex + data.Labels.size() - 1);
} else {
return false;
} else {
int64_t cpuToken = ProcessCpuSpcTokens(token);
if(cpuToken != -1) {
output += std::to_string(cpuToken);
return true;
}
}
return true;
int64_t sharedToken = ProcessSharedTokens(token);
if(sharedToken != -1) {
output += std::to_string(sharedToken);
return true;
}
string originalExpression = expression.substr(initialPos, pos - initialPos);
bool validLabel = _labelManager->ContainsLabel(originalExpression);
if(!validLabel) {
//Check if a multi-byte label exists for this name
string label = originalExpression + "+0";
validLabel = _labelManager->ContainsLabel(label);
}
if(validLabel) {
data.Labels.push_back(originalExpression);
output += std::to_string(EvalValues::FirstLabelIndex + data.Labels.size() - 1);
return true;
} else {
return false;
}
}
int64_t ExpressionEvaluator::ProcessCpuSpcTokens(string token)
{
if(token == "a") {
return EvalValues::RegA;
} else if(token == "x") {
return EvalValues::RegX;
} else if(token == "y") {
return EvalValues::RegY;
} else if(token == "ps") {
return EvalValues::RegPS;
} else if(token == "sp") {
return EvalValues::RegSP;
} else if(token == "pc") {
return EvalValues::RegPC;
} else if(token == "oppc") {
return EvalValues::RegOpPC;
} else if(token == "previousoppc") {
return EvalValues::PreviousOpPC;
} else if(token == "irq") {
return EvalValues::Irq;
} else if(token == "nmi") {
return EvalValues::Nmi;
}
return -1;
}
int64_t ExpressionEvaluator::ProcessSharedTokens(string token)
{
if(token == "frame") {
return EvalValues::PpuFrameCount;
} else if(token == "cycle") {
return EvalValues::PpuCycle;
} else if(token == "scanline") {
return EvalValues::PpuScanline;
} else if(token == "value") {
return EvalValues::Value;
} else if(token == "address") {
return EvalValues::Address;
} else if(token == "romaddress") {
return EvalValues::AbsoluteAddress;
} else if(token == "iswrite") {
return EvalValues::IsWrite;
} else if(token == "isread") {
return EvalValues::IsRead;
}
return -1;
}
int64_t ExpressionEvaluator::ProcessGsuTokens(string token)
{
if(token == "r0") {
return EvalValues::R0;
} else if(token == "r1") {
return EvalValues::R1;
} else if(token == "r2") {
return EvalValues::R2;
} else if(token == "r3") {
return EvalValues::R3;
} else if(token == "r4") {
return EvalValues::R4;
} else if(token == "r5") {
return EvalValues::R5;
} else if(token == "r6") {
return EvalValues::R6;
} else if(token == "r7") {
return EvalValues::R7;
} else if(token == "r8") {
return EvalValues::R8;
} else if(token == "r9") {
return EvalValues::R9;
} else if(token == "r10") {
return EvalValues::R10;
} else if(token == "r11") {
return EvalValues::R11;
} else if(token == "r12") {
return EvalValues::R12;
} else if(token == "r13") {
return EvalValues::R13;
} else if(token == "r14") {
return EvalValues::R14;
} else if(token == "r15") {
return EvalValues::R15;
} else if(token == "srcreg") {
return EvalValues::SrcReg;
} else if(token == "dstreg") {
return EvalValues::DstReg;
} else if(token == "sfr") {
return EvalValues::SFR;
} else if(token == "pbr") {
return EvalValues::PBR;
} else if(token == "rombr") {
return EvalValues::RomBR;
} else if(token == "rambr") {
return EvalValues::RamBR;
}
return -1;
}
string ExpressionEvaluator::GetNextToken(string expression, size_t &pos, ExpressionData &data, bool &success)
@ -406,6 +485,35 @@ int32_t ExpressionEvaluator::Evaluate(ExpressionData &data, DebugState &state, E
}
break;
case CpuType::Gsu:
switch(token) {
case EvalValues::R0: token = state.Gsu.R[0]; break;
case EvalValues::R1: token = state.Gsu.R[1]; break;
case EvalValues::R2: token = state.Gsu.R[2]; break;
case EvalValues::R3: token = state.Gsu.R[3]; break;
case EvalValues::R4: token = state.Gsu.R[4]; break;
case EvalValues::R5: token = state.Gsu.R[5]; break;
case EvalValues::R6: token = state.Gsu.R[6]; break;
case EvalValues::R7: token = state.Gsu.R[7]; break;
case EvalValues::R8: token = state.Gsu.R[8]; break;
case EvalValues::R9: token = state.Gsu.R[9]; break;
case EvalValues::R10: token = state.Gsu.R[10]; break;
case EvalValues::R11: token = state.Gsu.R[11]; break;
case EvalValues::R12: token = state.Gsu.R[12]; break;
case EvalValues::R13: token = state.Gsu.R[13]; break;
case EvalValues::R14: token = state.Gsu.R[14]; break;
case EvalValues::R15: token = state.Gsu.R[15]; break;
case EvalValues::SrcReg: token = state.Gsu.SrcReg; break;
case EvalValues::DstReg: token = state.Gsu.DestReg; break;
case EvalValues::SFR: token = (state.Gsu.SFR.GetFlagsHigh() << 8) | state.Gsu.SFR.GetFlagsLow(); break;
case EvalValues::PBR: token = state.Gsu.ProgramBank; break;
case EvalValues::RomBR: token = state.Gsu.ProgramBank; break;
case EvalValues::RamBR: token = state.Gsu.ProgramBank; break;
}
break;
case CpuType::NecDsp: throw std::runtime_error("Invalid CPU type");
}
break;

View file

@ -67,6 +67,29 @@ enum EvalValues : int64_t
IsRead = 20000000116,
PreviousOpPC = 20000000117,
R0 = 20000000120,
R1 = 20000000121,
R2 = 20000000122,
R3 = 20000000123,
R4 = 20000000124,
R5 = 20000000125,
R6 = 20000000126,
R7 = 20000000127,
R8 = 20000000128,
R9 = 20000000129,
R10 = 20000000130,
R11 = 20000000131,
R12 = 20000000132,
R13 = 20000000133,
R14 = 20000000134,
R15 = 20000000135,
SrcReg = 20000000137,
DstReg = 20000000138,
SFR = 20000000139,
PBR = 20000000140,
RomBR = 20000000141,
RamBR = 20000000142,
FirstLabelIndex = 20000002000,
};
@ -116,6 +139,9 @@ private:
bool IsOperator(string token, int &precedence, bool unaryOperator);
EvalOperators GetOperator(string token, bool unaryOperator);
bool CheckSpecialTokens(string expression, size_t &pos, string &output, ExpressionData &data);
int64_t ProcessCpuSpcTokens(string token);
int64_t ProcessSharedTokens(string token);
int64_t ProcessGsuTokens(string token);
string GetNextToken(string expression, size_t &pos, ExpressionData &data, bool &success);
bool ProcessSpecialOperator(EvalOperators evalOp, std::stack<EvalOperators> &opStack, std::stack<int> &precedenceStack, vector<int64_t> &outputQueue);
bool ToRpn(string expression, ExpressionData &data);

734
Core/Gsu.Instructions.cpp Normal file
View file

@ -0,0 +1,734 @@
#include "stdafx.h"
#include "Gsu.h"
#include "Cpu.h"
#include "MemoryManager.h"
void Gsu::STOP()
{
if(!_state.IrqDisabled) {
_state.SFR.Irq = true;
_cpu->SetIrqSource(IrqSource::Coprocessor);
}
_state.ProgramReadBuffer = 0x01; //Run a NOP first when the GSU is restarted
_state.SFR.Running = false;
ResetFlags();
UpdateRunningState();
}
void Gsu::NOP()
{
ResetFlags();
}
void Gsu::CACHE()
{
if(_state.CacheBase != (_state.R[15] & 0xFFF0)) {
_state.CacheBase = _state.R[15] & 0xFFF0;
InvalidateCache();
}
ResetFlags();
}
void Gsu::Branch(bool branch)
{
int8_t offset = (int8_t)ReadOperand();
if(branch) {
WriteRegister(15, _state.R[15] + offset);
}
}
void Gsu::BRA()
{
Branch(true);
}
void Gsu::BLT()
{
Branch(_state.SFR.Sign == _state.SFR.Overflow);
}
void Gsu::BGE()
{
Branch(_state.SFR.Sign != _state.SFR.Overflow);
}
void Gsu::BNE()
{
Branch(!_state.SFR.Zero);
}
void Gsu::BEQ()
{
Branch(_state.SFR.Zero);
}
void Gsu::BPL()
{
Branch(!_state.SFR.Sign);
}
void Gsu::BMI()
{
Branch(_state.SFR.Sign);
}
void Gsu::BCC()
{
Branch(!_state.SFR.Carry);
}
void Gsu::BCS()
{
Branch(_state.SFR.Carry);
}
void Gsu::BCV()
{
Branch(!_state.SFR.Overflow);
}
void Gsu::BVS()
{
Branch(_state.SFR.Overflow);
}
void Gsu::JMP(uint8_t reg)
{
if(_state.SFR.Alt1) {
//LJMP
_state.ProgramBank = _state.R[reg] & 0x7F;
WriteRegister(15, ReadSrcReg());
_state.CacheBase = _state.R[15] & 0xFFF0;
InvalidateCache();
} else {
//JMP
WriteRegister(15, _state.R[reg]);
}
ResetFlags();
}
void Gsu::TO(uint8_t reg)
{
if(_state.SFR.Prefix) {
//MOVE
WriteRegister(reg, ReadSrcReg());
ResetFlags();
} else {
//TO
_state.DestReg = reg;
}
}
void Gsu::FROM(uint8_t reg)
{
if(_state.SFR.Prefix) {
//MOVES
WriteDestReg(_state.R[reg]);
_state.SFR.Overflow = (_state.R[reg] & 0x80) != 0;
_state.SFR.Sign = (_state.R[reg] & 0x8000) != 0;
_state.SFR.Zero = (_state.R[reg] == 0);
ResetFlags();
} else {
//FROM
_state.SrcReg = reg;
}
}
void Gsu::WITH(uint8_t reg)
{
_state.SrcReg = reg;
_state.DestReg = reg;
_state.SFR.Prefix = true;
}
void Gsu::STORE(uint8_t reg)
{
_state.RamAddress = _state.R[reg];
WriteRam(_state.RamAddress, (uint8_t)ReadSrcReg());
if(!_state.SFR.Alt1) {
WriteRam(_state.RamAddress ^ 0x01, ReadSrcReg() >> 8);
}
ResetFlags();
}
void Gsu::LOAD(uint8_t reg)
{
_state.RamAddress = _state.R[reg];
uint16_t value = ReadRamBuffer(_state.RamAddress);
if(!_state.SFR.Alt1) {
value |= ReadRamBuffer(_state.RamAddress ^ 0x01) << 8;
}
WriteDestReg(value);
ResetFlags();
}
void Gsu::LOOP()
{
_state.R[12]--;
_state.SFR.Zero = (_state.R[12] == 0);
_state.SFR.Sign = (_state.R[12] & 0x8000) != 0;
//Loop until counter hits zero
if(!_state.SFR.Zero) {
WriteRegister(15, _state.R[13]);
}
ResetFlags();
}
void Gsu::ALT1()
{
_state.SFR.Prefix = false;
_state.SFR.Alt1 = true;
}
void Gsu::ALT2()
{
_state.SFR.Prefix = false;
_state.SFR.Alt2 = true;
}
void Gsu::ALT3()
{
_state.SFR.Prefix = false;
_state.SFR.Alt1 = true;
_state.SFR.Alt2 = true;
}
void Gsu::MERGE()
{
uint16_t value = (_state.R[7] & 0xFF00) | (_state.R[8] >> 8);
WriteDestReg(value);
_state.SFR.Carry = (value & 0xE0E0) != 0;
_state.SFR.Overflow = (value & 0xC0C0) != 0;
_state.SFR.Sign = (value & 0x8080) != 0;
_state.SFR.Zero = (value & 0xF0F0) != 0;
ResetFlags();
}
void Gsu::SWAP()
{
uint16_t value = (ReadSrcReg() >> 8) | (ReadSrcReg() << 8);
WriteDestReg(value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x8000) != 0;
ResetFlags();
}
void Gsu::Add(uint8_t reg)
{
uint16_t operand;
if(_state.SFR.Alt2) {
//Immediate value
operand = reg;
} else {
operand = _state.R[reg];
}
uint32_t result = ReadSrcReg() + operand;
if(_state.SFR.Alt1) {
//ADC - Add with carry
result += (uint8_t)_state.SFR.Carry;
}
_state.SFR.Carry = (result & 0x10000) != 0;
_state.SFR.Overflow = ~(ReadSrcReg() ^ operand) & (operand ^ result) & 0x8000;
_state.SFR.Sign = (result & 0x8000) != 0;
_state.SFR.Zero = (result & 0xFFFF) == 0;
WriteDestReg(result);
ResetFlags();
}
void Gsu::SubCompare(uint8_t reg)
{
uint16_t operand;
if(_state.SFR.Alt2 && !_state.SFR.Alt1) {
//Immediate value, SUB #val
operand = reg;
} else {
operand = _state.R[reg];
}
int32_t result = ReadSrcReg() - operand;
if(!_state.SFR.Alt2 && _state.SFR.Alt1) {
//SBC - SUB with carry
result -= _state.SFR.Carry ? 0 : 1;
}
_state.SFR.Carry = (result >= 0);
_state.SFR.Overflow = ((ReadSrcReg() ^ operand) & (ReadSrcReg() ^ result) & 0x8000) != 0;
_state.SFR.Sign = (result & 0x8000) != 0;
_state.SFR.Zero = (result & 0xFFFF) == 0;
if(!_state.SFR.Alt2 || !_state.SFR.Alt1) {
//SUB/SBC, other CMP (and no write occurs for CMP)
WriteDestReg(result);
}
ResetFlags();
}
void Gsu::MULT(uint8_t reg)
{
uint16_t operand;
if(_state.SFR.Alt2) {
//Immediate value
operand = reg;
} else {
operand = _state.R[reg];
}
uint16_t value;
if(_state.SFR.Alt1) {
//UMULT - Unsigned multiply
value = (uint16_t)((uint8_t)ReadSrcReg() * (uint8_t)operand);
} else {
//MULT - Signed multiply
value = (uint16_t)((int8_t)ReadSrcReg() * (int8_t)operand);
}
WriteDestReg(value);
_state.SFR.Sign = (value & 0x8000) != 0;
_state.SFR.Zero = value == 0;
ResetFlags();
Step(_state.HighSpeedMode ? 1 : 2);
}
void Gsu::FMultLMult()
{
uint32_t multResult = (int16_t)ReadSrcReg() * (int16_t)_state.R[6];
if(_state.SFR.Alt1) {
//LMULT - "16x16 signed multiply", LSB in R4, MSB in DREG
_state.R[4] = multResult;
}
uint16_t value = multResult >> 16;
WriteDestReg(value);
_state.SFR.Carry = (multResult & 0x8000);
_state.SFR.Sign = (value & 0x8000);
_state.SFR.Zero = (value == 0);
ResetFlags();
Step((_state.HighSpeedMode ? 3 : 7) * (_state.ClockSelect ? 1 : 2));
}
void Gsu::AndBitClear(uint8_t reg)
{
uint16_t operand;
if(_state.SFR.Alt2) {
//Immediate value
operand = reg;
} else {
operand = _state.R[reg];
}
uint16_t value;
if(_state.SFR.Alt1) {
//Bit clear
value = ReadSrcReg() & ~operand;
} else {
//AND
value = ReadSrcReg() & operand;
}
WriteDestReg(value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x8000) != 0;
ResetFlags();
}
void Gsu::SBK()
{
//"Store word data, last RAM address used"
WriteRam(_state.RamAddress, (uint8_t)ReadSrcReg());
WriteRam(_state.RamAddress ^ 1, ReadSrcReg() >> 8);
ResetFlags();
}
void Gsu::LINK(uint8_t value)
{
//"Link Return Address"
_state.R[11] = _state.R[15] + value;
ResetFlags();
}
void Gsu::SignExtend()
{
int16_t value = (int8_t)ReadSrcReg();
WriteDestReg((uint16_t)value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x8000) != 0;
ResetFlags();
}
void Gsu::NOT()
{
uint16_t value = ~ReadSrcReg();
WriteDestReg(value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x8000) != 0;
ResetFlags();
}
void Gsu::LSR()
{
uint16_t src = ReadSrcReg();
_state.SFR.Carry = (src & 0x01) != 0;
uint16_t dst = src >> 1;
WriteDestReg(dst);
_state.SFR.Zero = dst == 0;
_state.SFR.Sign = (dst & 0x8000) != 0;
ResetFlags();
}
void Gsu::ROL()
{
uint16_t src = ReadSrcReg();
uint16_t dst = (src << 1) | (uint8_t)_state.SFR.Carry;
_state.SFR.Carry = (src & 0x8000) != 0;
WriteDestReg(dst);
_state.SFR.Zero = dst == 0;
_state.SFR.Sign = (dst & 0x8000) != 0;
ResetFlags();
}
void Gsu::ASR()
{
uint16_t src = ReadSrcReg();
_state.SFR.Carry = (src & 0x01) != 0;
uint16_t dst = (int16_t)src >> 1;
if(_state.SFR.Alt1) {
dst += (src + 1) >> 16;
}
WriteDestReg(dst);
_state.SFR.Zero = dst == 0;
_state.SFR.Sign = (dst & 0x8000) != 0;
ResetFlags();
}
void Gsu::ROR()
{
uint16_t src = ReadSrcReg();
uint16_t dst = (src >> 1) | ((int)_state.SFR.Carry << 15);
_state.SFR.Carry = (src & 0x01) != 0;
WriteDestReg(dst);
_state.SFR.Zero = dst == 0;
_state.SFR.Sign = (dst & 0x8000) != 0;
ResetFlags();
}
void Gsu::LOB()
{
//"Value of low byte of register"
uint8_t value = (uint8_t)ReadSrcReg();
WriteDestReg(value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x80) != 0;
ResetFlags();
}
void Gsu::HIB()
{
//"Value of high byte of register"
uint8_t value = (uint8_t)(ReadSrcReg() >> 8);
WriteDestReg(value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x80) != 0;
ResetFlags();
}
void Gsu::IbtSmsLms(uint8_t reg)
{
if(_state.SFR.Alt1) {
//LMS - "Load word data from RAM, short address"
_state.RamAddress = ReadOperand() << 1;
uint8_t lsb = ReadRamBuffer(_state.RamAddress);
uint8_t msb = ReadRamBuffer(_state.RamAddress | 0x01);
WriteRegister(reg, (msb << 8) | lsb);
} else if(_state.SFR.Alt2) {
//SMS - "Store word data to RAM, short address"
_state.RamAddress = ReadOperand() << 1;
WriteRam(_state.RamAddress, (uint8_t)_state.R[reg]);
WriteRam(_state.RamAddress | 0x01, _state.R[reg] >> 8);
} else {
//IBT - "Load immediate byte data"
WriteRegister(reg, (int8_t)ReadOperand());
}
ResetFlags();
}
void Gsu::IwtLmSm(uint8_t reg)
{
if(_state.SFR.Alt1) {
//LM - Load memory
_state.RamAddress = ReadOperand();
_state.RamAddress |= ReadOperand() << 8;
uint8_t lsb = ReadRamBuffer(_state.RamAddress);
uint8_t msb = ReadRamBuffer(_state.RamAddress ^ 0x01);
WriteRegister(reg, (msb << 8) | lsb);
} else if(_state.SFR.Alt2) {
//SM - Store Memory
_state.RamAddress = ReadOperand();
_state.RamAddress |= ReadOperand() << 8;
WriteRam(_state.RamAddress, (uint8_t)_state.R[reg]);
WriteRam(_state.RamAddress ^ 0x01, _state.R[reg] >> 8);
} else {
//IWT - Load immediate word
uint8_t lsb = ReadOperand();
uint8_t msb = ReadOperand();
WriteRegister(reg, (msb << 8) | lsb);
}
ResetFlags();
}
void Gsu::OrXor(uint8_t operand)
{
uint16_t operandValue;
if(_state.SFR.Alt2) {
//Immediate value
operandValue = operand;
} else {
//Indirect register value
operandValue = _state.R[operand];
}
uint16_t value;
if(_state.SFR.Alt1) {
//XOR
value = ReadSrcReg() ^ operandValue;
} else {
//OR
value = ReadSrcReg() | operandValue;
}
WriteDestReg(value);
_state.SFR.Zero = value == 0;
_state.SFR.Sign = (value & 0x8000) != 0;
ResetFlags();
}
void Gsu::INC(uint8_t reg)
{
WriteRegister(reg, _state.R[reg] + 1);
_state.SFR.Zero = _state.R[reg] == 0;
_state.SFR.Sign = (_state.R[reg] & 0x8000) != 0;
ResetFlags();
}
void Gsu::DEC(uint8_t reg)
{
WriteRegister(reg, _state.R[reg] - 1);
_state.SFR.Zero = _state.R[reg] == 0;
_state.SFR.Sign = (_state.R[reg] & 0x8000) != 0;
ResetFlags();
}
void Gsu::GetCRamBRomB()
{
if(!_state.SFR.Alt2) {
//GETC - "Get byte from ROM to color register"
_state.ColorReg = GetColor(ReadRomBuffer());
} else if(!_state.SFR.Alt1) {
//RAMB - "Set RAM data bank"
WaitRamOperation();
_state.RamBank = ReadSrcReg() & 0x01;
} else {
//ROMB - "Set ROM data bank"
WaitRomOperation();
_state.RomBank = ReadSrcReg() & 0x7F;
}
ResetFlags();
}
void Gsu::GETB()
{
if(_state.SFR.Alt2 && _state.SFR.Alt1) {
//GETBS - "Get signed byte from ROM buffer"
WriteDestReg((int8_t)ReadRomBuffer());
} else if(_state.SFR.Alt2) {
//GETBL - "Get low byte from ROM buffer"
WriteDestReg((ReadSrcReg() & 0xFF00) | ReadRomBuffer());
} else if(_state.SFR.Alt1) {
//GETBH - "Get high byte from ROM buffer"
WriteDestReg((ReadSrcReg() & 0xFF) | (ReadRomBuffer() << 8));
} else {
//GETB - "Get byte from ROM buffer"
WriteDestReg(ReadRomBuffer());
}
ResetFlags();
}
void Gsu::PlotRpix()
{
if(_state.SFR.Alt1) {
//RPIX - "Read pixel color"
uint8_t value = ReadPixel((uint8_t)_state.R[1], (uint8_t)_state.R[2]);
_state.SFR.Zero = (value == 0);
_state.SFR.Sign = (value & 0x8000);
} else {
//PLOT
DrawPixel((uint8_t)_state.R[1], (uint8_t)_state.R[2]);
_state.R[1]++;
}
ResetFlags();
}
void Gsu::ColorCMode()
{
if(_state.SFR.Alt1) {
//CMODE - "Set plot mode"
uint8_t value = (uint8_t)ReadSrcReg();
_state.PlotTransparent = (value & 0x01) != 0;
_state.PlotDither = (value & 0x02) != 0;
_state.ColorHighNibble = (value & 0x04) != 0;
_state.ColorFreezeHigh = (value & 0x08) != 0;
_state.ObjMode = (value & 0x10) != 0;
} else {
//COLOR - "Set plot color"
_state.ColorReg = GetColor((uint8_t)ReadSrcReg());
}
ResetFlags();
}
uint16_t Gsu::GetTileIndex(uint8_t x, uint8_t y)
{
switch(_state.ObjMode ? 3 : _state.ScreenHeight) {
default:
case 0: return ((x & 0xF8) << 1) + ((y & 0xF8) >> 3); break;
case 1: return ((x & 0xF8) << 1) + ((x & 0xF8) >> 1) + ((y & 0xF8) >> 3); break;
case 2: return ((x & 0xF8) << 1) + ((x & 0xF8) << 0) + ((y & 0xF8) >> 3); break;
case 3: return ((y & 0x80) << 2) + ((x & 0x80) << 1) + ((y & 0x78) << 1) + ((x & 0x78) >> 3); break;
}
}
uint32_t Gsu::GetTileAddress(uint8_t x, uint8_t y)
{
uint16_t tileIndex = GetTileIndex(x, y);
return (0x700000 | (_state.ScreenBase << 10)) + (tileIndex * (_state.PlotBpp << 3)) + ((y & 0x07) * 2);
}
uint8_t Gsu::ReadPixel(uint8_t x, uint8_t y)
{
WritePixelCache(_state.SecondaryCache);
WritePixelCache(_state.PrimaryCache);
uint32_t tileAddress = GetTileAddress(x, y);
x = (x & 7) ^ 7;
uint8_t data = 0;
for(int i = 0; i < _state.PlotBpp; i++) {
//Select which byte to read/write based on the current bit (0/1, 16/17, 32/33, 48/49)
uint8_t byteOffset = ((i >> 1) << 4) + (i & 0x01);
data |= ((ReadGsu(tileAddress + byteOffset, MemoryOperationType::Read) >> x) & 1) << i;
Step(_state.ClockSelect ? 5 : 6);
}
return data;
}
bool Gsu::IsTransparentPixel()
{
uint8_t color = _state.ColorFreezeHigh ? (_state.ColorReg & 0x0F) : _state.ColorReg;
switch(_state.PlotBpp) {
default:
case 2: return (color & 0x03) == 0;
case 4: return (color & 0x0F) == 0;
case 8: return color == 0;
}
}
void Gsu::DrawPixel(uint8_t x, uint8_t y)
{
if(!_state.PlotTransparent && IsTransparentPixel()) {
return;
}
uint8_t color = _state.ColorReg;
if(_state.PlotDither && _state.PlotBpp != 8) {
if((x ^ y) & 0x01) {
color >>= 4;
}
color &= 0x0F;
}
if(_state.PrimaryCache.X != (x & 0xF8) || _state.PrimaryCache.Y != y) {
FlushPrimaryCache(x, y);
}
uint8_t xOffset = (x & 7) ^ 7;
_state.PrimaryCache.Pixels[xOffset] = color;
_state.PrimaryCache.ValidBits |= (1 << xOffset);
if(_state.PrimaryCache.ValidBits == 0xFF) {
FlushPrimaryCache(x, y);
}
}
void Gsu::FlushPrimaryCache(uint8_t x, uint8_t y)
{
WritePixelCache(_state.SecondaryCache);
_state.SecondaryCache = _state.PrimaryCache;
_state.PrimaryCache.ValidBits = 0;
_state.PrimaryCache.X = x & 0xF8;
_state.PrimaryCache.Y = y;
}
void Gsu::WritePixelCache(GsuPixelCache &cache)
{
if(cache.ValidBits == 0) {
return;
}
uint32_t tileAddress = GetTileAddress(cache.X, cache.Y);
for(int i = 0; i < _state.PlotBpp; i++) {
uint8_t value = 0;
for(int x = 0; x < 8; x++) {
value |= ((cache.Pixels[x] >> i) & 0x01) << x;
}
//Select which byte to read/write based on the current bit (0/1, 16/17, 32/33, 48/49)
uint8_t byte = ((i >> 1) << 4) + (i & 0x01);
if(cache.ValidBits != 0xFF) {
//Read the pixels in memory before to merge them before writing the cache's content to memory
Step(_state.ClockSelect ? 5 : 6);
value &= cache.ValidBits;
value |= ReadGsu(tileAddress + byte, MemoryOperationType::Read) & ~cache.ValidBits;
}
Step(_state.ClockSelect ? 5 : 6);
WaitForRamAccess();
WriteGsu(tileAddress + byte, value, MemoryOperationType::Write);
}
cache.ValidBits = 0;
}
uint8_t Gsu::GetColor(uint8_t value)
{
if(_state.ColorHighNibble) {
return (_state.ColorReg & 0xF0) | (value >> 4);
}
if(_state.ColorFreezeHigh) {
return (_state.ColorReg & 0xF0) | (value & 0x0F);
}
return value;
}

649
Core/Gsu.cpp Normal file
View file

@ -0,0 +1,649 @@
#include "stdafx.h"
#include "Gsu.h"
#include "Console.h"
#include "Cpu.h"
#include "MemoryManager.h"
#include "BaseCartridge.h"
#include "RamHandler.h"
#include "GsuRomHandler.h"
#include "GsuRamHandler.h"
#include "EmuSettings.h"
#include "MessageManager.h"
#include "../Utilities/HexUtilities.h"
Gsu::Gsu(Console *console, uint32_t gsuRamSize)
{
_console = console;
_memoryManager = console->GetMemoryManager().get();
_cpu = console->GetCpu().get();
_memoryType = SnesMemoryType::Register;
_settings = _console->GetSettings().get();
_clockMultiplier = _settings->GetEmulationConfig().GsuClockSpeed / 100;
_state = {};
_state.ProgramReadBuffer = 0x01; //Run a NOP on first cycle
_settings->InitializeRam(_cache, 512);
_gsuRamSize = gsuRamSize;
_gsuRam = new uint8_t[_gsuRamSize];
_settings->InitializeRam(_gsuRam, _gsuRamSize);
for(uint32_t i = 0; i < _gsuRamSize / 0x1000; i++) {
_gsuRamHandlers.push_back(unique_ptr<IMemoryHandler>(new RamHandler(_gsuRam, i * 0x1000, _gsuRamSize, SnesMemoryType::GsuWorkRam)));
_gsuCpuRamHandlers.push_back(unique_ptr<IMemoryHandler>(new GsuRamHandler(_state, _gsuRamHandlers.back().get())));
}
//CPU mappings
MemoryMappings *cpuMappings = _memoryManager->GetMemoryMappings();
vector<unique_ptr<IMemoryHandler>> &prgRomHandlers = _console->GetCartridge()->GetPrgRomHandlers();
for(unique_ptr<IMemoryHandler> &handler : prgRomHandlers) {
_gsuCpuRomHandlers.push_back(unique_ptr<IMemoryHandler>(new GsuRomHandler(_state, handler.get())));
}
//GSU registers in CPU memory space
cpuMappings->RegisterHandler(0x00, 0x3F, 0x3000, 0x3FFF, this);
cpuMappings->RegisterHandler(0x80, 0xBF, 0x3000, 0x3FFF, this);
for(int i = 0; i < 0x3F; i++) {
cpuMappings->RegisterHandler(i, i, 0x6000, 0x7FFF, _gsuCpuRamHandlers);
cpuMappings->RegisterHandler(i + 0x80, i + 0x80, 0x6000, 0x7FFF, _gsuCpuRamHandlers);
}
cpuMappings->RegisterHandler(0x70, 0x71, 0x0000, 0xFFFF, _gsuCpuRamHandlers);
cpuMappings->RegisterHandler(0xF0, 0xF1, 0x0000, 0xFFFF, _gsuCpuRamHandlers);
cpuMappings->RegisterHandler(0x00, 0x3F, 0x8000, 0xFFFF, _gsuCpuRomHandlers);
cpuMappings->RegisterHandler(0x80, 0xBF, 0x8000, 0xFFFF, _gsuCpuRomHandlers);
cpuMappings->RegisterHandler(0x40, 0x5F, 0x0000, 0xFFFF, _gsuCpuRomHandlers);
cpuMappings->RegisterHandler(0xC0, 0xDF, 0x0000, 0xFFFF, _gsuCpuRomHandlers);
//GSU mappings
_mappings.RegisterHandler(0x00, 0x3F, 0x8000, 0xFFFF, prgRomHandlers);
_mappings.RegisterHandler(0x00, 0x3F, 0x0000, 0x7FFF, prgRomHandlers); //Mirror
_mappings.RegisterHandler(0x40, 0x5F, 0x0000, 0xFFFF, prgRomHandlers);
_mappings.RegisterHandler(0x70, 0x71, 0x0000, 0xFFFF, _gsuRamHandlers);
}
void Gsu::ProcessEndOfFrame()
{
uint8_t clockMultiplier = _settings->GetEmulationConfig().GsuClockSpeed / 100;
if(_clockMultiplier != clockMultiplier) {
_state.CycleCount = _state.CycleCount / _clockMultiplier * clockMultiplier;
_clockMultiplier = clockMultiplier;
}
}
void Gsu::Run()
{
uint64_t targetCycle = _memoryManager->GetMasterClock() * _clockMultiplier;
while(!_stopped && _state.CycleCount < targetCycle) {
Exec();
}
if(targetCycle > _state.CycleCount) {
Step(targetCycle - _state.CycleCount);
}
}
void Gsu::Exec()
{
uint8_t opCode = ReadOpCode();
switch(opCode) {
case 0x00: STOP(); break;
case 0x01: NOP(); break;
case 0x02: CACHE(); break;
case 0x03: LSR(); break;
case 0x04: ROL(); break;
case 0x05: BRA(); break;
case 0x06: BLT(); break;
case 0x07: BGE(); break;
case 0x08: BNE(); break;
case 0x09: BEQ(); break;
case 0x0A: BPL(); break;
case 0x0B: BMI(); break;
case 0x0C: BCC(); break;
case 0x0D: BCS(); break;
case 0x0E: BCV(); break;
case 0x0F: BVS(); break;
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
TO(opCode & 0x0F);
break;
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
WITH(opCode & 0x0F);
break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
case 0x38: case 0x39: case 0x3A: case 0x3B:
STORE(opCode & 0x0F);
break;
case 0x3C: LOOP(); break;
case 0x3D: ALT1(); break;
case 0x3E: ALT2(); break;
case 0x3F: ALT3(); break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x4A: case 0x4B:
LOAD(opCode & 0x0F);
break;
case 0x4C: PlotRpix(); break;
case 0x4D: SWAP(); break;
case 0x4E: ColorCMode(); break;
case 0x4F: NOT(); break;
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F:
Add(opCode & 0x0F);
break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
SubCompare(opCode & 0x0F);
break;
case 0x70: MERGE(); break;
case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
AndBitClear(opCode & 0x0F);
break;
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F:
MULT(opCode & 0x0F);
break;
case 0x90: SBK(); break;
case 0x91: LINK(1); break;
case 0x92: LINK(2); break;
case 0x93: LINK(3); break;
case 0x94: LINK(4); break;
case 0x95: SignExtend(); break;
case 0x96: ASR(); break;
case 0x97: ROR(); break;
case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D:
JMP(opCode & 0x0F);
break;
case 0x9E: LOB(); break;
case 0x9F: FMultLMult(); break;
case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7:
case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF:
IbtSmsLms(opCode & 0x0F);
break;
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
FROM(opCode & 0x0F);
break;
case 0xC0: HIB(); break;
case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
OrXor(opCode & 0x0F);
break;
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7:
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE:
INC(opCode & 0x0F);
break;
case 0xDF: GetCRamBRomB(); break;
case 0xE0: case 0xE1: case 0xE2: case 0xE3: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE:
DEC(opCode & 0x0F);
break;
case 0xEF: GETB(); break;
case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
IwtLmSm(opCode & 0x0F);
break;
}
_console->ProcessMemoryRead<CpuType::Gsu>(_lastOpAddr, _state.ProgramReadBuffer, MemoryOperationType::ExecOpCode);
if(!_r15Changed) {
_state.R[15]++;
} else {
_r15Changed = false;
}
}
uint8_t Gsu::ReadGsu(uint32_t addr, MemoryOperationType opType)
{
IMemoryHandler *handler = _mappings.GetHandler(addr);
uint8_t value;
if(handler) {
value = handler->Read(addr);
} else {
//TODO: Open bus?
value = 0;
LogDebug("[Debug] GSU - Missing read handler: " + HexUtilities::ToHex(addr));
}
_console->ProcessMemoryRead<CpuType::Gsu>(addr, value, opType);
return value;
}
void Gsu::WriteGsu(uint32_t addr, uint8_t value, MemoryOperationType opType)
{
IMemoryHandler *handler = _mappings.GetHandler(addr);
if(handler) {
handler->Write(addr, value);
} else {
LogDebug("[Debug] GSU - Missing write handler: " + HexUtilities::ToHex(addr));
}
_console->ProcessMemoryWrite<CpuType::Gsu>(addr, value, opType);
}
void Gsu::InitProgramCache(uint16_t cacheAddr)
{
uint16_t dest = (cacheAddr & 0x01F0);
if(_state.ProgramBank <= 0x5F) {
WaitRomOperation();
WaitForRomAccess();
} else {
WaitRamOperation();
WaitForRamAccess();
}
uint32_t srcBaseAddr = (_state.ProgramBank << 16) + _state.CacheBase + dest;
for(int i = 0; i < 16; i++) {
_cache[dest + i] = ReadGsu(srcBaseAddr + i, MemoryOperationType::Read);
}
Step(_state.ClockSelect ? 5*16 : 6*16);
_cacheValid[cacheAddr >> 4] = true;
}
uint8_t Gsu::ReadOperand()
{
uint8_t result = _state.ProgramReadBuffer;
_state.R[15]++;
_state.ProgramReadBuffer = ReadProgramByte(MemoryOperationType::Read);
return result;
}
uint8_t Gsu::ReadOpCode()
{
uint8_t result = _state.ProgramReadBuffer;
_state.ProgramReadBuffer = ReadProgramByte(MemoryOperationType::Read);
return result;
}
uint8_t Gsu::ReadProgramByte(MemoryOperationType opType)
{
_lastOpAddr = (_state.ProgramBank << 16) | _state.R[15];
uint16_t cacheAddr = _state.R[15] - _state.CacheBase;
if(cacheAddr < 512) {
if(!_cacheValid[cacheAddr >> 4]) {
InitProgramCache(cacheAddr & 0xFFF0);
}
Step(_state.ClockSelect ? 1 : 2);
_console->ProcessMemoryRead<CpuType::Gsu>(_lastOpAddr, _cache[cacheAddr], opType);
return _cache[cacheAddr];
} else {
if(_state.ProgramBank <= 0x5F) {
WaitRomOperation();
WaitForRomAccess();
} else {
WaitRamOperation();
WaitForRamAccess();
}
Step(_state.ClockSelect ? 5 : 6);
return ReadGsu(_lastOpAddr, opType);
}
}
uint16_t Gsu::ReadSrcReg()
{
return _state.R[_state.SrcReg];
}
void Gsu::WriteDestReg(uint16_t value)
{
WriteRegister(_state.DestReg, value);
}
void Gsu::WriteRegister(uint8_t reg, uint16_t value)
{
_state.R[reg] = value;
if(reg == 14) {
_state.SFR.RomReadPending = true;
_state.RomDelay = _state.ClockSelect ? 5 : 6;
} else if(reg == 15) {
_r15Changed = true;
}
}
void Gsu::ResetFlags()
{
_state.SFR.Prefix = 0;
_state.SFR.Alt1 = false;
_state.SFR.Alt2 = false;
_state.SrcReg = 0;
_state.DestReg = 0;
}
void Gsu::InvalidateCache()
{
memset(_cacheValid, 0, sizeof(_cacheValid));
}
void Gsu::WaitRomOperation()
{
if(_state.RomDelay) {
//Wait for existing RAM operation to complete
Step(_state.RomDelay);
}
}
void Gsu::WaitRamOperation()
{
if(_state.RamDelay) {
//Wait for existing RAM operation to complete
Step(_state.RamDelay);
}
}
void Gsu::WaitForRomAccess()
{
if(!_state.GsuRomAccess) {
_waitForRomAccess = true;
_stopped = true;
}
}
void Gsu::WaitForRamAccess()
{
if(!_state.GsuRamAccess) {
_waitForRamAccess = true;
_stopped = true;
}
}
void Gsu::UpdateRunningState()
{
_stopped = !_state.SFR.Running || _waitForRamAccess || _waitForRomAccess;
}
uint8_t Gsu::ReadRomBuffer()
{
WaitRomOperation();
return _state.RomReadBuffer;
}
uint8_t Gsu::ReadRamBuffer(uint16_t addr)
{
WaitRamOperation();
WaitForRamAccess();
return ReadGsu(0x700000 | (_state.RamBank << 16) | addr, MemoryOperationType::Read);
}
void Gsu::WriteRam(uint16_t addr, uint8_t value)
{
WaitRamOperation();
_state.RamDelay = _state.ClockSelect ? 5 : 6;
_state.RamWriteAddress = addr;
_state.RamWriteValue = value;
}
void Gsu::Step(uint64_t cycles)
{
_state.CycleCount += cycles;
if(_state.RomDelay) {
_state.RomDelay -= std::min<uint8_t>((uint8_t)cycles, _state.RomDelay);
if(_state.RomDelay == 0) {
WaitForRomAccess();
_state.RomReadBuffer = ReadGsu((_state.RomBank << 16) | _state.R[14], MemoryOperationType::Read);
_state.SFR.RomReadPending = false;
}
}
if(_state.RamDelay) {
_state.RamDelay -= std::min<uint8_t>((uint8_t)cycles, _state.RamDelay);
if(_state.RamDelay == 0) {
WaitForRamAccess();
WriteGsu(0x700000 | (_state.RamBank << 16) | _state.RamWriteAddress, _state.RamWriteValue, MemoryOperationType::Write);
}
}
}
void Gsu::Reset()
{
_state = {};
_state.ProgramReadBuffer = 0x01; //Run a NOP on first cycle
_console->GetSettings()->InitializeRam(_cache, 512);
memset(_cacheValid, 0, sizeof(_cacheValid));
_waitForRomAccess = false;
_waitForRamAccess = false;
_stopped = true;
_lastOpAddr = 0;
}
uint8_t Gsu::Read(uint32_t addr)
{
addr &= 0x33FF;
if(_state.SFR.Running && addr != 0x3030 && addr != 0x3031 && addr != 0x303B) {
//"During GSU operation, only SFR, SCMR, and VCR may be accessed."
return 0;
}
switch(addr) {
case 0x3000: case 0x3002: case 0x3004: case 0x3006: case 0x3008: case 0x300A: case 0x300C:case 0x300E:
case 0x3010: case 0x3012: case 0x3014: case 0x3016: case 0x3018: case 0x301A: case 0x301C:case 0x301E:
return (uint8_t)_state.R[(addr >> 1) & 0x0F];
case 0x3001: case 0x3003: case 0x3005: case 0x3007: case 0x3009: case 0x300B: case 0x300D:case 0x300F:
case 0x3011: case 0x3013: case 0x3015: case 0x3017: case 0x3019: case 0x301B: case 0x301D:case 0x301F:
return _state.R[(addr >> 1) & 0x0F] >> 8;
case 0x3030: return _state.SFR.GetFlagsLow();
case 0x3031: {
uint8_t flags = _state.SFR.GetFlagsHigh();
_state.SFR.Irq = false;
_cpu->ClearIrqSource(IrqSource::Coprocessor);
return flags;
}
case 0x3034: return _state.ProgramBank;
case 0x3036: return _state.RomBank;
case 0x303B: return 0x04; //Version (can be 1 or 4?)
case 0x303C: return _state.RamBank;
case 0x303E: return (uint8_t)_state.CacheBase;
case 0x303F: return _state.CacheBase >> 8;
}
if(addr >= 0x3100 && addr <= 0x32FF) {
return _cache[(_state.CacheBase + (addr - 0x3100)) & 0x1FF];
}
LogDebug("[Debug] Missing read handler: $" + HexUtilities::ToHex(addr));
//TODO open bus and proper mirroring?
return 0;
}
void Gsu::Write(uint32_t addr, uint8_t value)
{
addr &= 0x33FF;
if(_state.SFR.Running && addr != 0x3030 && addr != 0x303A) {
//"During GSU operation, only SFR, SCMR, and VCR may be accessed."
return;
}
switch(addr) {
case 0x3000: case 0x3002: case 0x3004: case 0x3006: case 0x3008: case 0x300A: case 0x300C: case 0x300E:
case 0x3010: case 0x3012: case 0x3014: case 0x3016: case 0x3018: case 0x301A: case 0x301C: case 0x301E:
_state.RegisterLatch = value;
break;
case 0x3001: case 0x3003: case 0x3005: case 0x3007: case 0x3009: case 0x300B: case 0x300D: case 0x300F:
case 0x3011: case 0x3013: case 0x3015: case 0x3017: case 0x3019: case 0x301B: case 0x301D: case 0x301F: {
uint8_t reg = (addr >> 1) & 0x0F;
_state.R[reg] = (value << 8) | _state.RegisterLatch;
if(reg == 14) {
_state.SFR.RomReadPending = true;
_state.RomDelay = _state.ClockSelect ? 5 : 6;
} else if(addr == 0x301F) {
_state.SFR.Running = true;
UpdateRunningState();
}
break;
}
case 0x3030: {
bool running = _state.SFR.Running;
_state.SFR.Zero = (value & 0x02) != 0;
_state.SFR.Carry = (value & 0x04) != 0;
_state.SFR.Sign = (value & 0x08) != 0;
_state.SFR.Overflow = (value & 0x10) != 0;
_state.SFR.Running = (value & 0x20) != 0;
if(running && !_state.SFR.Running) {
_state.CacheBase = 0;
InvalidateCache();
}
UpdateRunningState();
break;
}
case 0x3033: _state.BackupRamEnabled = (value & 0x01); break;
case 0x3034: _state.ProgramBank = (value & 0x7F); InvalidateCache(); break;
case 0x3037:
_state.HighSpeedMode = (value & 0x20) != 0;
_state.IrqDisabled = (value & 0x80) != 0;
break;
case 0x3038: _state.ScreenBase = value; break;
case 0x3039: _state.ClockSelect = (value & 0x01); break;
case 0x303A:
_state.ColorGradient = (value & 0x03);
switch(_state.ColorGradient) {
case 0: _state.PlotBpp = 2; break;
case 1: _state.PlotBpp = 4; break;
case 2: _state.PlotBpp = 4; break;
case 3: _state.PlotBpp = 8; break;
}
_state.ScreenHeight = ((value & 0x04) >> 2) | ((value & 0x20) >> 4);
_state.GsuRamAccess = (value & 0x08) != 0;
_state.GsuRomAccess = (value & 0x10) != 0;
if(_state.GsuRamAccess) {
_waitForRamAccess = false;
}
if(_state.GsuRomAccess) {
_waitForRomAccess = false;
}
UpdateRunningState();
break;
}
if(addr >= 0x3100 && addr <= 0x32FF) {
uint16_t cacheAddr = (_state.CacheBase + (addr - 0x3100)) & 0x1FF;
_cache[cacheAddr] = value;
if((cacheAddr & 0x0F) == 0x0F) {
_cacheValid[cacheAddr >> 4] = true;
}
}
}
uint8_t Gsu::Peek(uint32_t addr)
{
return 0;
}
void Gsu::PeekBlock(uint8_t *output)
{
memset(output, 0, 0x1000);
}
AddressInfo Gsu::GetAbsoluteAddress(uint32_t address)
{
return { -1, SnesMemoryType::Register };
}
void Gsu::Serialize(Serializer &s)
{
s.Stream(
_state.CycleCount, _state.RegisterLatch, _state.ProgramBank, _state.RomBank, _state.RamBank, _state.IrqDisabled,
_state.HighSpeedMode, _state.ClockSelect, _state.BackupRamEnabled, _state.ScreenBase, _state.ColorGradient, _state.PlotBpp,
_state.ScreenHeight, _state.GsuRamAccess, _state.GsuRomAccess, _state.CacheBase, _state.PlotTransparent, _state.PlotDither,
_state.ColorHighNibble, _state.ColorFreezeHigh, _state.ObjMode, _state.ColorReg, _state.SrcReg, _state.DestReg,
_state.RomReadBuffer, _state.RomDelay, _state.ProgramReadBuffer, _state.RamWriteAddress, _state.RamWriteValue, _state.RamDelay,
_state.RamAddress, _state.PrimaryCache.X, _state.PrimaryCache.Y, _state.PrimaryCache.ValidBits, _state.SecondaryCache.X,
_state.SecondaryCache.Y, _state.SecondaryCache.ValidBits,
_state.SFR.Alt1, _state.SFR.Alt2, _state.SFR.Carry, _state.SFR.ImmHigh, _state.SFR.ImmLow, _state.SFR.Irq, _state.SFR.Overflow,
_state.SFR.Prefix, _state.SFR.RomReadPending, _state.SFR.Running, _state.SFR.Sign, _state.SFR.Zero
);
s.StreamArray(_state.R, 16);
s.StreamArray(_state.PrimaryCache.Pixels, 8);
s.StreamArray(_state.SecondaryCache.Pixels, 8);
s.Stream(_waitForRamAccess, _waitForRomAccess, _stopped);
s.StreamArray(_cacheValid, 32);
s.StreamArray(_cache, 512);
s.StreamArray(_gsuRam, _gsuRamSize);
}
void Gsu::LoadBattery(string filePath)
{
VirtualFile saveFile(filePath);
saveFile.ReadFile((uint8_t*)_gsuRam, _gsuRamSize);
}
void Gsu::SaveBattery(string filePath)
{
ofstream saveFile(filePath, ios::binary);
saveFile.write((char*)_gsuRam, _gsuRamSize);
}
GsuState Gsu::GetState()
{
return _state;
}
MemoryMappings* Gsu::GetMemoryMappings()
{
return &_mappings;
}
uint8_t* Gsu::DebugGetWorkRam()
{
return _gsuRam;
}
uint32_t Gsu::DebugGetWorkRamSize()
{
return _gsuRamSize;
}

172
Core/Gsu.h Normal file
View file

@ -0,0 +1,172 @@
#pragma once
#include "stdafx.h"
#include "BaseCoprocessor.h"
#include "GsuTypes.h"
#include "MemoryMappings.h"
#include "IMemoryHandler.h"
class Console;
class Cpu;
class MemoryManager;
class EmuSettings;
class Gsu : public BaseCoprocessor
{
private:
Console *_console;
MemoryManager *_memoryManager;
Cpu *_cpu;
EmuSettings *_settings;
uint8_t _clockMultiplier;
GsuState _state;
uint8_t _cache[512];
bool _cacheValid[32] = {};
bool _waitForRomAccess = false;
bool _waitForRamAccess = false;
bool _stopped = true;
bool _r15Changed = false;
uint32_t _lastOpAddr = 0;
uint32_t _gsuRamSize = 0;
uint8_t* _gsuRam = nullptr;
MemoryMappings _mappings;
vector<unique_ptr<IMemoryHandler>> _gsuRamHandlers;
vector<unique_ptr<IMemoryHandler>> _gsuCpuRamHandlers;
vector<unique_ptr<IMemoryHandler>> _gsuCpuRomHandlers;
void Exec();
void InitProgramCache(uint16_t cacheAddr);
uint8_t ReadOperand();
uint8_t ReadOpCode();
uint8_t ReadProgramByte(MemoryOperationType opType);
uint16_t ReadSrcReg();
void WriteDestReg(uint16_t value);
void WriteRegister(uint8_t reg, uint16_t value);
void ResetFlags();
void InvalidateCache();
void WaitRomOperation();
void WaitRamOperation();
void WaitForRomAccess();
void WaitForRamAccess();
void UpdateRunningState();
uint8_t ReadRomBuffer();
uint8_t ReadRamBuffer(uint16_t addr);
void WriteRam(uint16_t addr, uint8_t value);
void Step(uint64_t cycles);
void STOP();
void NOP();
void CACHE();
void Branch(bool branch);
void BRA();
void BLT();
void BGE();
void BNE();
void BEQ();
void BPL();
void BMI();
void BCC();
void BCS();
void BCV();
void BVS();
void JMP(uint8_t reg);
void TO(uint8_t reg);
void FROM(uint8_t reg);
void WITH(uint8_t reg);
void STORE(uint8_t reg);
void LOAD(uint8_t reg);
void LOOP();
void ALT1();
void ALT2();
void ALT3();
void MERGE();
void SWAP();
void PlotRpix();
void ColorCMode();
uint16_t GetTileIndex(uint8_t x, uint8_t y);
uint32_t GetTileAddress(uint8_t x, uint8_t y);
uint8_t ReadPixel(uint8_t x, uint8_t y);
bool IsTransparentPixel();
void DrawPixel(uint8_t x, uint8_t y);
void FlushPrimaryCache(uint8_t x, uint8_t y);
void WritePixelCache(GsuPixelCache &cache);
uint8_t GetColor(uint8_t source);
void Add(uint8_t reg);
void SubCompare(uint8_t reg);
void MULT(uint8_t reg);
void FMultLMult();
void AndBitClear(uint8_t reg);
void SBK();
void LINK(uint8_t reg);
void SignExtend();
void NOT();
void LSR();
void ROL();
void ASR();
void ROR();
void LOB();
void HIB();
void IbtSmsLms(uint8_t reg);
void IwtLmSm(uint8_t reg);
void OrXor(uint8_t reg);
void INC(uint8_t reg);
void DEC(uint8_t reg);
void GetCRamBRomB();
void GETB();
public:
Gsu(Console *console, uint32_t gsuRamSize);
void ProcessEndOfFrame() override;
uint8_t ReadGsu(uint32_t addr, MemoryOperationType opType);
void WriteGsu(uint32_t addr, uint8_t value, MemoryOperationType opType);
void LoadBattery(string filePath) override;
void SaveBattery(string filePath) override;
void Run();
void Reset() override;
uint8_t Read(uint32_t addr) override;
uint8_t Peek(uint32_t addr) override;
void PeekBlock(uint8_t *output) override;
void Write(uint32_t addr, uint8_t value) override;
AddressInfo GetAbsoluteAddress(uint32_t address) override;
void Serialize(Serializer &s) override;
GsuState GetState();
MemoryMappings* GetMemoryMappings();
uint8_t* DebugGetWorkRam();
uint32_t DebugGetWorkRamSize();
};

95
Core/GsuDebugger.cpp Normal file
View file

@ -0,0 +1,95 @@
#include "stdafx.h"
#include "GsuDebugger.h"
#include "DisassemblyInfo.h"
#include "Disassembler.h"
#include "BaseCartridge.h"
#include "Gsu.h"
#include "TraceLogger.h"
#include "CallstackManager.h"
#include "MemoryManager.h"
#include "Debugger.h"
#include "Console.h"
#include "MemoryAccessCounter.h"
GsuDebugger::GsuDebugger(Debugger* debugger)
{
_debugger = debugger;
_traceLogger = debugger->GetTraceLogger().get();
_disassembler = debugger->GetDisassembler().get();
_memoryAccessCounter = debugger->GetMemoryAccessCounter().get();
_gsu = debugger->GetConsole()->GetCartridge()->GetGsu();
_memoryManager = debugger->GetConsole()->GetMemoryManager().get();
_step.reset(new StepRequest());
}
void GsuDebugger::Reset()
{
_prevOpCode = 0xFF;
}
void GsuDebugger::ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType type)
{
if(type == MemoryOperationType::DummyRead) {
//Ignore all dummy reads for now
return;
}
AddressInfo addressInfo = _gsu->GetMemoryMappings()->GetAbsoluteAddress(addr);
MemoryOperationInfo operation { addr, value, type };
if(type == MemoryOperationType::ExecOpCode) {
DebugState debugState;
_debugger->GetState(debugState, true);
_disassembler->BuildCache(addressInfo, debugState.Gsu.SFR.GetFlagsHigh() & 0x13, CpuType::Gsu);
debugState.Gsu.R[15] = addr;
DisassemblyInfo disInfo = _disassembler->GetDisassemblyInfo(addressInfo);
_traceLogger->Log(CpuType::Gsu, debugState, disInfo);
_prevOpCode = value;
_prevProgramCounter = addr;
if(_step->StepCount > 0) {
_step->StepCount--;
}
}
_debugger->ProcessBreakConditions(_step->StepCount == 0, CpuType::Gsu, operation, addressInfo);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
}
void GsuDebugger::ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type)
{
AddressInfo addressInfo = _gsu->GetMemoryMappings()->GetAbsoluteAddress(addr);
MemoryOperationInfo operation { addr, value, type };
_debugger->ProcessBreakConditions(false, CpuType::Gsu, operation, addressInfo);
_disassembler->InvalidateCache(addressInfo, CpuType::Gsu);
_memoryAccessCounter->ProcessMemoryAccess(addressInfo, type, _memoryManager->GetMasterClock());
}
void GsuDebugger::Run()
{
_step.reset(new StepRequest());
}
void GsuDebugger::Step(int32_t stepCount, StepType type)
{
StepRequest step;
switch(type) {
case StepType::StepOut:
case StepType::StepOver:
case StepType::Step: step.StepCount = stepCount; break;
case StepType::SpecificScanline:
case StepType::PpuStep:
break;
}
_step.reset(new StepRequest(step));
}

35
Core/GsuDebugger.h Normal file
View file

@ -0,0 +1,35 @@
#pragma once
#include "stdafx.h"
#include "DebugTypes.h"
class Disassembler;
class Debugger;
class TraceLogger;
class Gsu;
class MemoryAccessCounter;
class MemoryManager;
class GsuDebugger
{
Debugger* _debugger;
Disassembler* _disassembler;
TraceLogger* _traceLogger;
MemoryAccessCounter* _memoryAccessCounter;
MemoryManager* _memoryManager;
Gsu* _gsu;
unique_ptr<StepRequest> _step;
uint8_t _prevOpCode = 0xFF;
uint32_t _prevProgramCounter = 0;
public:
GsuDebugger(Debugger* debugger);
void Reset();
void ProcessRead(uint32_t addr, uint8_t value, MemoryOperationType type);
void ProcessWrite(uint32_t addr, uint8_t value, MemoryOperationType type);
void Run();
void Step(int32_t stepCount, StepType type);
};

198
Core/GsuDisUtils.cpp Normal file
View file

@ -0,0 +1,198 @@
#include "stdafx.h"
#include "GsuDisUtils.h"
#include "DisassemblyInfo.h"
#include "../Utilities/FastString.h"
#include "../Utilities/HexUtilities.h"
void GsuDisUtils::GetDisassembly(DisassemblyInfo &info, string &out, uint32_t memoryAddr, LabelManager *labelManager)
{
constexpr const char* registerNames[16] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
bool alt1 = (info.GetFlags() & 0x01) != 0;
bool alt2 = (info.GetFlags() & 0x02) != 0;
bool prefix = (info.GetFlags() & 0x10) != 0;
uint8_t opCode = info.GetOpCode();
FastString str;
const char* reg = registerNames[opCode & 0x0F];
uint32_t jmpTarget = memoryAddr + (int8_t)info.GetByteCode()[1];
switch(opCode) {
case 0x00: str.Write("STOP"); break;
case 0x01: str.Write("NOP"); break;
case 0x02: str.Write("CACHE"); break;
case 0x03: str.Write("LSR"); break;
case 0x04: str.Write("ROL"); break;
case 0x05: str.WriteAll("BRA $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x06: str.WriteAll("BLT $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x07: str.WriteAll("BGE $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x08: str.WriteAll("BNE $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x09: str.WriteAll("BEQ $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x0A: str.WriteAll("BPL $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x0B: str.WriteAll("BMI $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x0C: str.WriteAll("BCC $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x0D: str.WriteAll("BCS $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x0E: str.WriteAll("BCV $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x0F: str.WriteAll("BVS $", HexUtilities::ToHex24(jmpTarget)); break;
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
str.WriteAll(prefix ? "MOVE R" : "TO R", reg);
break;
case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F:
str.WriteAll("WITH R", reg);
break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
case 0x38: case 0x39: case 0x3A: case 0x3B:
str.WriteAll(alt1 ? "STB (R" : "STW (R", reg, ')');
break;
case 0x3C: str.Write("LOOP"); break;
case 0x3D: str.Write("ALT1"); break;
case 0x3E: str.Write("ALT2"); break;
case 0x3F: str.Write("ALT3"); break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
case 0x48: case 0x49: case 0x4A: case 0x4B:
str.WriteAll(alt1 ? "LDB (R" : "LDW (R", reg, ')');
break;
case 0x4C: str.Write(alt1 ? "RPIX" : "PLOT"); break;
case 0x4D: str.Write("SWAP"); break;
case 0x4E: str.Write(alt1 ? "CMODE" : "COLOR"); break;
case 0x4F: str.Write("NOT"); break;
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F:
str.Write(alt1 ? "ADC " : "ADD ");
str.WriteAll(alt2 ? '#' : 'R', reg);
break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F:
if(alt2 && alt1) {
str.WriteAll("CMP R", reg);
} else {
if(!alt2 && alt1) {
str.Write("SBC ");
} else {
str.Write("SUB ");
}
if(alt2 && !alt1) {
str.WriteAll('#', reg);
} else {
str.WriteAll('R', reg);
}
}
break;
case 0x70: str.Write("MERGE"); break;
case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F:
str.Write(alt1 ? "BIC " : "AND ");
str.WriteAll(alt2 ? '#' : 'R', reg);
break;
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87:
case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F:
str.Write(alt1 ? "UMULT " : "MULT ");
str.WriteAll(alt2 ? '#' : 'R', reg);
break;
case 0x90: str.Write("SBK"); break;
case 0x91: case 0x92: case 0x93: case 0x94:
str.WriteAll("LINK #", reg);
break;
case 0x95: str.Write("SEX"); break;
case 0x96: str.Write(alt1 ? "DIV2" : "ASR"); break;
case 0x97: str.Write("ROR"); break;
case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D:
str.WriteAll(alt1 ? "LJMP R" : "JMP R", reg);
break;
case 0x9E: str.Write("LOB"); break;
case 0x9F: str.Write(alt1 ? "LMULT" : "FMULT"); break;
case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7:
case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF:
if(alt1) {
str.WriteAll("LMS R", reg, ", ($", HexUtilities::ToHex(info.GetByteCode()[1] << 1), ')');
} else if(alt2) {
str.WriteAll("SMS R", reg, ", ($", HexUtilities::ToHex(info.GetByteCode()[1] << 1), ')');
} else {
str.WriteAll("IBT R", reg, ", #$", HexUtilities::ToHex(info.GetByteCode()[1]));
}
break;
case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7:
case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF:
str.WriteAll(prefix ? "MOVES R" : "FROM R", reg);
break;
case 0xC0: str.Write("HIB"); break;
case 0xC1: case 0xC2: case 0xC3: case 0xC4: case 0xC5: case 0xC6: case 0xC7:
case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF:
str.Write(alt1 ? "XOR " : "OR ");
str.WriteAll(alt2 ? '#' : 'R', reg);
break;
case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: case 0xD5: case 0xD6: case 0xD7:
case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE:
str.WriteAll("INC R", reg);
break;
case 0xDF:
if(!alt2) {
//GETC - "Get byte from ROM to color register"
str.Write("GETC");
} else if(!alt1) {
//RAMB - "Set RAM data bank"
str.Write("RAMB");
} else {
str.Write("ROMB");
}
break;
case 0xE0: case 0xE1: case 0xE2: case 0xE3: case 0xE4: case 0xE5: case 0xE6: case 0xE7:
case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE:
str.WriteAll("DEC R", reg);
break;
case 0xEF:
if(alt2 && alt1) {
str.Write("GETBS");
} else if(alt2) {
str.Write("GETBL");
} else if(alt1) {
str.Write("GETBH");
} else {
str.Write("GETB");
}
break;
case 0xF0: case 0xF1: case 0xF2: case 0xF3: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF:
if(alt1) {
str.WriteAll("LM R", reg, ", ($", HexUtilities::ToHex(info.GetByteCode()[2]), HexUtilities::ToHex(info.GetByteCode()[1]), ')');
} else if(alt2) {
str.WriteAll("SM R", reg, ", ($", HexUtilities::ToHex(info.GetByteCode()[2]), HexUtilities::ToHex(info.GetByteCode()[1]), ')');
} else {
str.WriteAll("IWT R", reg, ", #$", HexUtilities::ToHex(info.GetByteCode()[2]), HexUtilities::ToHex(info.GetByteCode()[1]));
}
break;
}
out += str.ToString();
}

11
Core/GsuDisUtils.h Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#include "stdafx.h"
class DisassemblyInfo;
class LabelManager;
class GsuDisUtils
{
public:
static void GetDisassembly(DisassemblyInfo &info, string &out, uint32_t memoryAddr, LabelManager* labelManager);
};

57
Core/GsuRamHandler.h Normal file
View file

@ -0,0 +1,57 @@
#pragma once
#include "stdafx.h"
#include "IMemoryHandler.h"
#include "GsuTypes.h"
class GsuRamHandler : public IMemoryHandler
{
private:
GsuState *_state;
IMemoryHandler *_handler;
public:
GsuRamHandler(GsuState &state, IMemoryHandler *handler)
{
_memoryType = SnesMemoryType::GsuWorkRam;
_handler = handler;
_state = &state;
}
uint8_t Read(uint32_t addr) override
{
if(!_state->SFR.Running || !_state->GsuRamAccess) {
return _handler->Read(addr);
}
//TODO: open bus
return 0;
}
uint8_t Peek(uint32_t addr) override
{
return Read(addr);
}
void PeekBlock(uint8_t *output) override
{
for(int i = 0; i < 0x1000; i++) {
output[i] = Read(i);
}
}
void Write(uint32_t addr, uint8_t value) override
{
if(!_state->SFR.Running || !_state->GsuRamAccess) {
_handler->Write(addr, value);
}
}
AddressInfo GetAbsoluteAddress(uint32_t address) override
{
if(!_state->SFR.Running || !_state->GsuRamAccess) {
return _handler->GetAbsoluteAddress(address);
} else {
return { -1, SnesMemoryType::Register };
}
}
};

66
Core/GsuRomHandler.h Normal file
View file

@ -0,0 +1,66 @@
#pragma once
#include "stdafx.h"
#include "IMemoryHandler.h"
#include "GsuTypes.h"
class GsuRomHandler : public IMemoryHandler
{
private:
GsuState *_state;
IMemoryHandler *_romHandler;
public:
GsuRomHandler(GsuState &state, IMemoryHandler *romHandler)
{
_memoryType = SnesMemoryType::PrgRom;
_romHandler = romHandler;
_state = &state;
}
uint8_t Read(uint32_t addr) override
{
if(!_state->SFR.Running || !_state->GsuRomAccess) {
return _romHandler->Read(addr);
}
if(addr & 0x01) {
return 0x01;
}
switch(addr & 0x0E) {
default:
case 2: case 6: case 8: case 0x0C:
return 0;
case 4: return 0x04;
case 0x0A: return 0x08;
case 0x0E: return 0x0C;
}
}
uint8_t Peek(uint32_t addr) override
{
return Read(addr);
}
void PeekBlock(uint8_t *output) override
{
for(int i = 0; i < 0x1000; i++) {
output[i] = Read(i);
}
}
void Write(uint32_t addr, uint8_t value) override
{
//ROM
}
AddressInfo GetAbsoluteAddress(uint32_t address) override
{
if(!_state->SFR.Running || !_state->GsuRomAccess) {
return _romHandler->GetAbsoluteAddress(address);
} else {
return { -1, SnesMemoryType::Register };
}
}
};

103
Core/GsuTypes.h Normal file
View file

@ -0,0 +1,103 @@
#pragma once
#include "stdafx.h"
struct GsuFlags
{
bool Zero;
bool Carry;
bool Sign;
bool Overflow;
bool Running;
bool RomReadPending;
bool Alt1;
bool Alt2;
bool ImmLow;
bool ImmHigh;
bool Prefix;
bool Irq;
uint8_t GetFlagsLow()
{
return (
(Zero << 1) |
(Carry << 2) |
(Sign << 3) |
(Overflow << 4) |
(Running << 5) |
(RomReadPending << 6)
);
}
uint8_t GetFlagsHigh()
{
return (
(Alt1 << 0) |
(Alt2 << 1) |
(ImmLow << 2) |
(ImmHigh << 3) |
(Prefix << 4) |
(Irq << 7)
);
}
};
struct GsuPixelCache
{
uint8_t X;
uint8_t Y;
uint8_t Pixels[8];
uint8_t ValidBits;
};
struct GsuState
{
uint64_t CycleCount;
uint16_t R[16];
GsuFlags SFR;
uint8_t RegisterLatch;
uint8_t ProgramBank;
uint8_t RomBank;
uint8_t RamBank;
bool IrqDisabled;
bool HighSpeedMode;
bool ClockSelect;
bool BackupRamEnabled;
uint8_t ScreenBase;
uint8_t ColorGradient;
uint8_t PlotBpp;
uint8_t ScreenHeight;
bool GsuRamAccess;
bool GsuRomAccess;
uint16_t CacheBase;
bool PlotTransparent;
bool PlotDither;
bool ColorHighNibble;
bool ColorFreezeHigh;
bool ObjMode;
uint8_t ColorReg;
uint8_t SrcReg;
uint8_t DestReg;
uint8_t RomReadBuffer;
uint8_t RomDelay;
uint8_t ProgramReadBuffer;
uint16_t RamWriteAddress;
uint8_t RamWriteValue;
uint8_t RamDelay;
uint16_t RamAddress;
GsuPixelCache PrimaryCache;
GsuPixelCache SecondaryCache;
};

View file

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "LabelManager.h"
#include "Debugger.h"
#include "DebugUtilities.h"
LabelManager::LabelManager(Debugger *debugger)
{
@ -49,6 +50,7 @@ int64_t LabelManager::GetLabelKey(uint32_t absoluteAddr, SnesMemoryType memType)
case SnesMemoryType::SpcRam: return absoluteAddr | ((uint64_t)5 << 32);
case SnesMemoryType::SpcRom: return absoluteAddr | ((uint64_t)6 << 32);
case SnesMemoryType::Sa1InternalRam: return absoluteAddr | ((uint64_t)7 << 32);
case SnesMemoryType::GsuWorkRam: return absoluteAddr | ((uint64_t)8 << 32);
default: return -1;
}
}
@ -63,6 +65,7 @@ SnesMemoryType LabelManager::GetKeyMemoryType(uint64_t key)
case ((uint64_t)5 << 32): return SnesMemoryType::SpcRam; break;
case ((uint64_t)6 << 32): return SnesMemoryType::SpcRom; break;
case ((uint64_t)7 << 32): return SnesMemoryType::Sa1InternalRam; break;
case ((uint64_t)8 << 32): return SnesMemoryType::GsuWorkRam; break;
}
throw std::runtime_error("Invalid label key");
@ -70,7 +73,7 @@ SnesMemoryType LabelManager::GetKeyMemoryType(uint64_t key)
string LabelManager::GetLabel(AddressInfo address)
{
if(address.Type <= SnesMemoryType::Sa1Memory) {
if(address.Type <= DebugUtilities::GetLastCpuMemoryType()) {
address = _debugger->GetAbsoluteAddress(address);
}
@ -103,7 +106,7 @@ string LabelManager::GetComment(AddressInfo absAddress)
void LabelManager::GetLabelAndComment(AddressInfo address, string &label, string &comment)
{
if(address.Type <= SnesMemoryType::Sa1Memory) {
if(address.Type <= DebugUtilities::GetLastCpuMemoryType()) {
address = _debugger->GetAbsoluteAddress(address);
}
@ -151,7 +154,7 @@ int32_t LabelManager::GetLabelRelativeAddress(string &label)
bool LabelManager::HasLabelOrComment(AddressInfo address)
{
if(address.Type <= SnesMemoryType::Sa1Memory) {
if(address.Type <= DebugUtilities::GetLastCpuMemoryType()) {
address = _debugger->GetAbsoluteAddress(address);
}

View file

@ -103,6 +103,7 @@ int LuaApi::GetLibrary(lua_State *lua)
lua_pushintvalue(cpu, SnesMemoryType::CpuMemory);
lua_pushintvalue(spc, SnesMemoryType::SpcMemory);
lua_pushintvalue(sa1, SnesMemoryType::Sa1Memory);
lua_pushintvalue(gsu, SnesMemoryType::GsuMemory);
lua_pushintvalue(cgram, SnesMemoryType::CGRam);
lua_pushintvalue(vram, SnesMemoryType::VideoRam);
lua_pushintvalue(oam, SnesMemoryType::SpriteRam);
@ -112,6 +113,7 @@ int LuaApi::GetLibrary(lua_State *lua)
lua_pushintvalue(cpuDebug, SnesMemoryType::CpuMemory | 0x100);
lua_pushintvalue(spcDebug, SnesMemoryType::SpcMemory | 0x100);
lua_pushintvalue(sa1Debug, SnesMemoryType::Sa1Memory | 0x100);
lua_pushintvalue(gsuDebug, SnesMemoryType::GsuMemory | 0x100);
lua_settable(lua, -3);
lua_pushliteral(lua, "memCallbackType");

View file

@ -6,6 +6,7 @@
#include "MemoryDumper.h"
#include "Spc.h"
#include "Sa1.h"
#include "Gsu.h"
#include "BaseCartridge.h"
MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger, Console *console)
@ -14,6 +15,7 @@ MemoryAccessCounter::MemoryAccessCounter(Debugger* debugger, Console *console)
_memoryManager = console->GetMemoryManager().get();
_spc = console->GetSpc().get();
_sa1 = console->GetCartridge()->GetSa1();
_gsu = console->GetCartridge()->GetGsu();
for(int i = (int)SnesMemoryType::PrgRom; i < (int)SnesMemoryType::Register; i++) {
uint32_t memSize = _debugger->GetMemoryDumper()->GetMemorySize((SnesMemoryType)i);
@ -133,6 +135,15 @@ void MemoryAccessCounter::GetAccessStamps(uint32_t offset, uint32_t length, Snes
}
break;
case SnesMemoryType::GsuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _gsu->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
stamps[i] = GetStampArray(operationType, info.Type)[info.Address];
}
}
break;
default:
memcpy(stamps, GetStampArray(operationType, memoryType).data() + offset, length * sizeof(uint64_t));
break;
@ -169,6 +180,15 @@ void MemoryAccessCounter::GetAccessCounts(uint32_t offset, uint32_t length, Snes
}
break;
case SnesMemoryType::GsuMemory:
for(uint32_t i = 0; i < length; i++) {
AddressInfo info = _gsu->GetMemoryMappings()->GetAbsoluteAddress(offset + i);
if(info.Address >= 0) {
counts[i] = GetCountArray(operationType, info.Type)[info.Address];
}
}
break;
default:
memcpy(counts, GetCountArray(operationType, memoryType).data() + offset, length * sizeof(uint32_t));
break;

View file

@ -7,6 +7,7 @@ class MemoryManager;
class Spc;
class Console;
class Sa1;
class Gsu;
class MemoryAccessCounter
{
@ -25,6 +26,7 @@ private:
MemoryManager* _memoryManager;
Spc* _spc;
Sa1* _sa1;
Gsu* _gsu;
vector<uint32_t>& GetCountArray(MemoryOperationType operationType, SnesMemoryType memType);
vector<uint64_t>& GetStampArray(MemoryOperationType operationType, SnesMemoryType memType);

View file

@ -5,6 +5,7 @@
#include "Spc.h"
#include "NecDsp.h"
#include "Sa1.h"
#include "Gsu.h"
#include "MemoryDumper.h"
#include "BaseCartridge.h"
#include "VideoDecoder.h"
@ -29,6 +30,7 @@ void MemoryDumper::SetMemoryState(SnesMemoryType type, uint8_t *buffer, uint32_t
case SnesMemoryType::CpuMemory:
case SnesMemoryType::SpcMemory:
case SnesMemoryType::Sa1Memory:
case SnesMemoryType::GsuMemory:
break;
case SnesMemoryType::PrgRom: memcpy(_cartridge->DebugGetPrgRom(), buffer, length); break;
@ -45,6 +47,8 @@ void MemoryDumper::SetMemoryState(SnesMemoryType type, uint8_t *buffer, uint32_t
case SnesMemoryType::DspDataRam: memcpy(_cartridge->GetDsp()->DebugGetDataRam(), buffer, length); break;
case SnesMemoryType::Sa1InternalRam: memcpy(_cartridge->GetSa1()->DebugGetInternalRam(), buffer, length); break;
case SnesMemoryType::GsuWorkRam: memcpy(_cartridge->GetGsu()->DebugGetWorkRam(), buffer, length); break;
}
}
@ -55,6 +59,7 @@ uint32_t MemoryDumper::GetMemorySize(SnesMemoryType type)
case SnesMemoryType::CpuMemory: return 0x1000000;
case SnesMemoryType::SpcMemory: return 0x10000;
case SnesMemoryType::Sa1Memory: return 0x1000000;
case SnesMemoryType::GsuMemory: return 0x1000000;
case SnesMemoryType::PrgRom: return _cartridge->DebugGetPrgRomSize();
case SnesMemoryType::WorkRam: return MemoryManager::WorkRamSize;
case SnesMemoryType::SaveRam: return _cartridge->DebugGetSaveRamSize();
@ -70,6 +75,8 @@ uint32_t MemoryDumper::GetMemorySize(SnesMemoryType type)
case SnesMemoryType::DspDataRam: return _cartridge->GetDsp() ? _cartridge->GetDsp()->DebugGetDataRamSize() : 0;
case SnesMemoryType::Sa1InternalRam: return _cartridge->GetSa1() ? _cartridge->GetSa1()->DebugGetInternalRamSize() : 0;;
case SnesMemoryType::GsuWorkRam: return _cartridge->GetGsu() ? _cartridge->GetGsu()->DebugGetWorkRamSize() : 0;;
}
}
@ -96,6 +103,12 @@ void MemoryDumper::GetMemoryState(SnesMemoryType type, uint8_t *buffer)
}
break;
case SnesMemoryType::GsuMemory:
for(int i = 0; i <= 0xFFFFFF; i += 0x1000) {
_cartridge->GetGsu()->GetMemoryMappings()->PeekBlock(i, buffer + i);
}
break;
case SnesMemoryType::PrgRom: memcpy(buffer, _cartridge->DebugGetPrgRom(), _cartridge->DebugGetPrgRomSize()); break;
case SnesMemoryType::WorkRam: memcpy(buffer, _memoryManager->DebugGetWorkRam(), MemoryManager::WorkRamSize); break;
case SnesMemoryType::SaveRam: memcpy(buffer, _cartridge->DebugGetSaveRam(), _cartridge->DebugGetSaveRamSize()); break;
@ -110,6 +123,8 @@ void MemoryDumper::GetMemoryState(SnesMemoryType type, uint8_t *buffer)
case SnesMemoryType::DspDataRam: memcpy(buffer, _cartridge->GetDsp()->DebugGetDataRam(), _cartridge->GetDsp()->DebugGetDataRamSize()); break;
case SnesMemoryType::Sa1InternalRam: memcpy(buffer, _cartridge->GetSa1()->DebugGetInternalRam(), _cartridge->GetSa1()->DebugGetInternalRamSize()); break;
case SnesMemoryType::GsuWorkRam: memcpy(buffer, _cartridge->GetGsu()->DebugGetWorkRam(), _cartridge->GetGsu()->DebugGetWorkRamSize()); break;
}
}
@ -133,6 +148,7 @@ void MemoryDumper::SetMemoryValue(SnesMemoryType memoryType, uint32_t address, u
case SnesMemoryType::CpuMemory: _memoryManager->Write(address, value, MemoryOperationType::Write); break;
case SnesMemoryType::SpcMemory: _spc->DebugWrite(address, value); break;
case SnesMemoryType::Sa1Memory: _cartridge->GetSa1()->WriteSa1(address, value, MemoryOperationType::Write); break;
case SnesMemoryType::GsuMemory: _cartridge->GetGsu()->WriteGsu(address, value, MemoryOperationType::Write); break;
case SnesMemoryType::PrgRom: _cartridge->DebugGetPrgRom()[address] = value; break;
case SnesMemoryType::WorkRam: _memoryManager->DebugGetWorkRam()[address] = value; break;
@ -149,6 +165,8 @@ void MemoryDumper::SetMemoryValue(SnesMemoryType memoryType, uint32_t address, u
case SnesMemoryType::DspDataRam: _cartridge->GetDsp()->DebugGetDataRam()[address] = value;
case SnesMemoryType::Sa1InternalRam: _cartridge->GetSa1()->DebugGetInternalRam()[address] = value;
case SnesMemoryType::GsuWorkRam: _cartridge->GetGsu()->DebugGetWorkRam()[address] = value;
}
}
@ -164,6 +182,7 @@ uint8_t MemoryDumper::GetMemoryValue(SnesMemoryType memoryType, uint32_t address
case SnesMemoryType::CpuMemory: return _memoryManager->Peek(address);
case SnesMemoryType::SpcMemory: return _spc->DebugRead(address);
case SnesMemoryType::Sa1Memory: return _cartridge->GetSa1()->GetMemoryMappings()->Peek(address);
case SnesMemoryType::GsuMemory: return _cartridge->GetGsu()->GetMemoryMappings()->Peek(address);
case SnesMemoryType::PrgRom: return _cartridge->DebugGetPrgRom()[address];
case SnesMemoryType::WorkRam: return _memoryManager->DebugGetWorkRam()[address];
@ -180,6 +199,8 @@ uint8_t MemoryDumper::GetMemoryValue(SnesMemoryType memoryType, uint32_t address
case SnesMemoryType::DspDataRam: return _cartridge->GetDsp()->DebugGetDataRam()[address];
case SnesMemoryType::Sa1InternalRam: return _cartridge->GetSa1()->DebugGetInternalRam()[address];
case SnesMemoryType::GsuWorkRam: return _cartridge->GetGsu()->DebugGetWorkRam()[address];
}
}

View file

@ -11,6 +11,8 @@
#include "MessageManager.h"
#include "DebugTypes.h"
#include "EmuSettings.h"
#include "Sa1.h"
#include "Gsu.h"
#include "BaseCoprocessor.h"
#include "../Utilities/Serializer.h"
#include "../Utilities/HexUtilities.h"
@ -189,6 +191,17 @@ void MemoryManager::UpdateEvents()
_hasEvent[_dramRefreshPosition] = true;
}
void MemoryManager::SyncCoprocessors()
{
if(_cart->GetCoprocessor()) {
if(_cart->GetGsu()) {
_cart->GetGsu()->Run();
} else if(_cart->GetSa1()) {
_cart->GetSa1()->Run();
}
}
}
void MemoryManager::Exec()
{
_masterClock += 2;
@ -222,9 +235,7 @@ void MemoryManager::Exec()
_regs->ProcessIrqCounters();
}
if(_cart->GetCoprocessor()) {
_cart->GetCoprocessor()->Run();
}
SyncCoprocessors();
}
uint8_t MemoryManager::Read(uint32_t addr, MemoryOperationType type)

View file

@ -47,6 +47,7 @@ private:
uint8_t _masterClockTable[2][0x10000];
void UpdateEvents();
__forceinline void SyncCoprocessors();
void Exec();
public:

View file

@ -17,6 +17,7 @@ NecDsp::NecDsp(CoprocessorType type, Console* console, vector<uint8_t> &programR
_console = console;
_type = type;
_memoryManager = console->GetMemoryManager().get();
_memoryType = SnesMemoryType::Register;
MemoryMappings *mm = _memoryManager->GetMemoryMappings();
if(type == CoprocessorType::ST010 || type == CoprocessorType::ST011) {
@ -219,6 +220,7 @@ void NecDsp::Write(uint32_t addr, uint8_t value)
uint8_t NecDsp::Peek(uint32_t addr)
{
//Avoid side effects for now
return 0;
}
@ -229,7 +231,7 @@ void NecDsp::PeekBlock(uint8_t *output)
AddressInfo NecDsp::GetAbsoluteAddress(uint32_t address)
{
return { -1, SnesMemoryType::CpuMemory };
return { -1, SnesMemoryType::Register };
}
void NecDsp::RunApuOp(uint8_t aluOperation, uint16_t source)

View file

@ -48,15 +48,13 @@ private:
void Load(uint8_t dest, uint16_t value);
uint16_t GetSourceValue(uint8_t source);
static bool LoadFirmware(Console *console, string combinedFilename, string splitFilenameProgram, string splitFilenameData, vector<uint8_t> &programRom, vector<uint8_t> &dataRom, uint32_t programSize, uint32_t dataSize);
NecDsp(CoprocessorType type, Console* console, vector<uint8_t> &programRom, vector<uint8_t> &dataRom);
public:
static NecDsp* InitCoprocessor(CoprocessorType type, Console* console);
void Reset() override;
void Run() override;
void Run();
void LoadBattery(string filePath) override;
void SaveBattery(string filePath) override;

View file

@ -2,9 +2,7 @@
#include "stdafx.h"
class DisassemblyInfo;
class Console;
class LabelManager;
struct NecDspState;
class NecDspDisUtils
{

View file

@ -16,6 +16,7 @@ Sa1::Sa1(Console* console)
{
_console = console;
_memoryManager = console->GetMemoryManager().get();
_memoryType = SnesMemoryType::Register;
_lastAccessMemType = SnesMemoryType::PrgRom;
_openBus = 0;
_cart = _console->GetCartridge().get();
@ -405,11 +406,14 @@ uint8_t Sa1::Read(uint32_t addr)
uint8_t Sa1::Peek(uint32_t addr)
{
return 0;
return Sa1RegisterRead(addr);
}
void Sa1::PeekBlock(uint8_t *output)
{
for(int i = 0; i < 0x1000; i++) {
output[i] = Sa1RegisterRead(i);
}
}
void Sa1::Write(uint32_t addr, uint8_t value)

View file

@ -68,7 +68,7 @@ public:
void Write(uint32_t addr, uint8_t value) override;
AddressInfo GetAbsoluteAddress(uint32_t address) override;
void Run() override;
void Run();
void Reset() override;
SnesMemoryType GetSa1MemoryType();

View file

@ -263,6 +263,7 @@ struct EmulationConfig
uint32_t PpuExtraScanlinesBeforeNmi = 0;
uint32_t PpuExtraScanlinesAfterNmi = 0;
uint32_t GsuClockSpeed = 0;
RamState RamPowerOnState = RamState::Random;
};
@ -443,6 +444,7 @@ enum class DebuggerFlags : uint32_t
ShowUnidentifiedData = 0x400,
DisassembleUnidentifiedData = 0x800,
GsuDebuggerEnabled = 0x10000000,
Sa1DebuggerEnabled = 0x20000000,
SpcDebuggerEnabled = 0x40000000,
CpuDebuggerEnabled = 0x80000000

View file

@ -7,6 +7,7 @@
#include "Debugger.h"
#include "MemoryManager.h"
#include "LabelManager.h"
#include "DebugUtilities.h"
#include "CpuTypes.h"
#include "SpcTypes.h"
#include "NecDspTypes.h"
@ -64,6 +65,7 @@ void TraceLogger::SetOptions(TraceLoggerOptions options)
_logCpu[(int)CpuType::Spc] = options.LogSpc;
_logCpu[(int)CpuType::NecDsp] = options.LogNecDsp;
_logCpu[(int)CpuType::Sa1] = options.LogSa1;
_logCpu[(int)CpuType::Gsu] = options.LogGsu;
string condition = _options.Condition;
string format = _options.Format;
@ -79,8 +81,9 @@ void TraceLogger::SetOptions(TraceLoggerOptions options)
}*/
ParseFormatString(_rowParts, format);
ParseFormatString(_spcRowParts, "[PC,4h] [ByteCode,15h] [Disassembly][EffectiveAddress] [MemoryValue,h][Align,48] A:[A,2h] X:[X,2h] Y:[Y,2h] S:[SP,2h] P:[P,8] H:[Cycle,3] V:[Scanline,3]");
ParseFormatString(_dspRowParts, "[PC,4h] [ByteCode,15h] [Disassembly] [Align,65] [A,2h] S:[SP,2h] H:[Cycle,3] V:[Scanline,3]");
ParseFormatString(_spcRowParts, "[PC,4h] [ByteCode,11h] [Disassembly][EffectiveAddress] [MemoryValue,h][Align,48] A:[A,2h] X:[X,2h] Y:[Y,2h] S:[SP,2h] P:[P,8] H:[Cycle,3] V:[Scanline,3]");
ParseFormatString(_dspRowParts, "[PC,4h] [ByteCode,11h] [Disassembly] [Align,65] [A,2h] S:[SP,2h] H:[Cycle,3] V:[Scanline,3]");
ParseFormatString(_gsuRowParts, "[PC,6h] [ByteCode,11h] [Disassembly] [Align,50] SRC:[X,2] DST:[Y,2] R0:[A,2h] H:[Cycle,3] V:[Scanline,3]");
}
void TraceLogger::ParseFormatString(vector<RowPart> &rowParts, string format)
@ -384,6 +387,37 @@ void TraceLogger::GetTraceRow(string &output, NecDspState &cpuState, PpuState &p
output += _options.UseWindowsEol ? "\r\n" : "\n";
}
void TraceLogger::GetTraceRow(string &output, GsuState &gsuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo)
{
int originalSize = (int)output.size();
uint32_t pcAddress = (gsuState.ProgramBank << 16) | gsuState.R[15];
for(RowPart& rowPart : _gsuRowParts) {
switch(rowPart.DataType) {
case RowDataType::Text: output += rowPart.Text; break;
case RowDataType::ByteCode: WriteByteCode(disassemblyInfo, rowPart, output); break;
case RowDataType::Disassembly: WriteDisassembly(disassemblyInfo, rowPart, 0, pcAddress, output); break;
case RowDataType::Align: WriteAlign(originalSize, rowPart, output); break;
case RowDataType::PC: WriteValue(output, HexUtilities::ToHex24(pcAddress), rowPart); break;
case RowDataType::A:
WriteValue(output, gsuState.R[0], rowPart);
for(int i = 1; i < 16; i++) {
output += " R" + std::to_string(i) + ":" + HexUtilities::ToHex(gsuState.R[i]);
}
break;
case RowDataType::X: WriteValue(output, gsuState.SrcReg, rowPart); break;
case RowDataType::Y: WriteValue(output, gsuState.DestReg, rowPart); break;
case RowDataType::Cycle: WriteValue(output, ppuState.Cycle, rowPart); break;
case RowDataType::Scanline: WriteValue(output, ppuState.Scanline, rowPart); break;
case RowDataType::HClock: WriteValue(output, ppuState.HClock, rowPart); break;
case RowDataType::FrameCount: WriteValue(output, ppuState.FrameCount, rowPart); break;
default: break;
}
}
output += _options.UseWindowsEol ? "\r\n" : "\n";
}
/*
bool TraceLogger::ConditionMatches(DebugState &state, DisassemblyInfo &disassemblyInfo, OperationInfo &operationInfo)
{
@ -410,6 +444,7 @@ void TraceLogger::GetTraceRow(string &output, CpuType cpuType, DisassemblyInfo &
case CpuType::Spc: GetTraceRow(output, state.Spc, state.Ppu, disassemblyInfo); break;
case CpuType::NecDsp: GetTraceRow(output, state.Dsp, state.Ppu, disassemblyInfo); break;
case CpuType::Sa1: GetTraceRow(output, state.Sa1, state.Ppu, disassemblyInfo, SnesMemoryType::Sa1Memory); break;
case CpuType::Gsu: GetTraceRow(output, state.Gsu, state.Ppu, disassemblyInfo); break;
}
}
@ -476,7 +511,7 @@ const char* TraceLogger::GetExecutionTrace(uint32_t lineCount)
}
bool enabled = false;
for(int i = 0; i < (int)CpuType::Sa1 + 1; i++) {
for(int i = 0; i <= (int)DebugUtilities::GetLastCpuType(); i++) {
enabled |= _logCpu[i];
}
@ -503,6 +538,7 @@ const char* TraceLogger::GetExecutionTrace(uint32_t lineCount)
case CpuType::Spc: _executionTrace += "\x3\x1" + HexUtilities::ToHex(_stateCacheCopy[index].Spc.PC) + "\x1"; break;
case CpuType::NecDsp: _executionTrace += "\x4\x1" + HexUtilities::ToHex(_stateCacheCopy[index].Dsp.PC) + "\x1"; break;
case CpuType::Sa1: _executionTrace += "\x4\x1" + HexUtilities::ToHex24((_stateCacheCopy[index].Sa1.K << 16) | _stateCacheCopy[index].Sa1.PC) + "\x1"; break;
case CpuType::Gsu: _executionTrace += "\x4\x1" + HexUtilities::ToHex24((_stateCacheCopy[index].Gsu.ProgramBank << 16) | _stateCacheCopy[index].Gsu.R[15]) + "\x1"; break;
}
string byteCode;

View file

@ -19,6 +19,7 @@ struct TraceLoggerOptions
bool LogSpc;
bool LogNecDsp;
bool LogSa1;
bool LogGsu;
bool ShowExtraInfo;
bool IndentCode;
@ -80,8 +81,9 @@ private:
vector<RowPart> _rowParts;
vector<RowPart> _spcRowParts;
vector<RowPart> _dspRowParts;
vector<RowPart> _gsuRowParts;
bool _logCpu[(int)CpuType::Sa1 + 1] = {};
bool _logCpu[(int)CpuType::Gsu + 1] = {};
bool _pendingLog;
//CpuState _lastState;
@ -116,6 +118,7 @@ private:
void GetTraceRow(string &output, CpuState &cpuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo, SnesMemoryType memType);
void GetTraceRow(string &output, SpcState &cpuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo);
void GetTraceRow(string &output, NecDspState &cpuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo);
void GetTraceRow(string &output, GsuState &gsuState, PpuState &ppuState, DisassemblyInfo &disassemblyInfo);
template<typename T> void WriteValue(string &output, T value, RowPart& rowPart);

View file

@ -47,6 +47,10 @@ SOURCES_CXX := $(LIBRETRO_DIR)/libretro.cpp \
$(CORE_DIR)/EmuSettings.cpp \
$(CORE_DIR)/EventManager.cpp \
$(CORE_DIR)/ExpressionEvaluator.cpp \
$(CORE_DIR)/Gsu.cpp \
$(CORE_DIR)/Gsu.Instructions.cpp \
$(CORE_DIR)/GsuDisUtils.cpp \
$(CORE_DIR)/GsuDebugger.cpp \
$(CORE_DIR)/InternalRegisters.cpp \
$(CORE_DIR)/KeyManager.cpp \
$(CORE_DIR)/LabelManager.cpp \

View file

@ -41,6 +41,7 @@ static constexpr const char* MesenOverscanHorizontal = "mesen-s_overscan_horizon
static constexpr const char* MesenRamState = "mesen-s_ramstate";
static constexpr const char* MesenOverclock = "mesen-s_overclock";
static constexpr const char* MesenOverclockType = "mesen-s_overclock_type";
static constexpr const char* MesenSuperFxOverclock = "mesen-s_superfx_overclock";
extern "C" {
void logMessage(retro_log_level level, const char* message)
@ -105,6 +106,7 @@ extern "C" {
{ MesenAspectRatio, "Aspect Ratio; Auto|No Stretching|NTSC|PAL|4:3|16:9" },
{ MesenOverclock, "Overclock; None|Low|Medium|High|Very High" },
{ MesenOverclockType, "Overclock Type; Before NMI|After NMI" },
{ MesenSuperFxOverclock, "Super FX Clock Speed; 100%|200%|300%|400%|500%|1000%" },
{ MesenRamState, "Default power-on state for RAM; Random Values (Default)|All 0s|All 1s" },
{ NULL, NULL },
};
@ -260,6 +262,24 @@ extern "C" {
}
}
emulation.GsuClockSpeed = 100;
if(readVariable(MesenSuperFxOverclock, var)) {
string value = string(var.value);
if(value == "100%") {
emulation.GsuClockSpeed = 100;
} else if(value == "200%") {
emulation.GsuClockSpeed = 200;
} else if(value == "300%") {
emulation.GsuClockSpeed = 300;
} else if(value == "400%") {
emulation.GsuClockSpeed = 400;
} else if(value == "500%") {
emulation.GsuClockSpeed = 500;
} else if(value == "1000%") {
emulation.GsuClockSpeed = 1000;
}
}
int overscanHorizontal = 0;
int overscanVertical = 0;
if(readVariable(MesenOverscanHorizontal, var)) {

View file

@ -21,6 +21,7 @@ namespace Mesen.GUI.Config
[MinMax(0, 1000)] public UInt32 PpuExtraScanlinesBeforeNmi = 0;
[MinMax(0, 1000)] public UInt32 PpuExtraScanlinesAfterNmi = 0;
[MinMax(100, 1000)] public UInt32 GsuClockSpeed = 100;
public RamState RamPowerOnState = RamState.Random;

View file

@ -109,6 +109,7 @@ namespace Mesen.GUI.Debugger
case SnesMemoryType.CpuMemory: type = "CPU"; break;
case SnesMemoryType.SpcMemory: type = "SPC"; break;
case SnesMemoryType.Sa1Memory: type = "SA1"; break;
case SnesMemoryType.GsuMemory: type = "GSU"; break;
case SnesMemoryType.PrgRom: type = "PRG"; break;
case SnesMemoryType.WorkRam: type = "WRAM"; break;
@ -121,6 +122,7 @@ namespace Mesen.GUI.Debugger
case SnesMemoryType.SpcRom: type = "ROM"; break;
case SnesMemoryType.Sa1InternalRam: type = "IRAM"; break;
case SnesMemoryType.GsuWorkRam: type = "GWRAM"; break;
case SnesMemoryType.Register: type = "REG"; break;
}

View file

@ -37,14 +37,14 @@ namespace Mesen.GUI.Debugger
_cpuType = breakpoint.CpuType;
cboBreakpointType.Items.Clear();
if(_cpuType == CpuType.Cpu || _cpuType == CpuType.Sa1) {
if(_cpuType == CpuType.Cpu || _cpuType == CpuType.Sa1 || _cpuType == CpuType.Gsu) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(_cpuType.ToMemoryType()));
cboBreakpointType.Items.Add("-");
if(DebugApi.GetMemorySize(SnesMemoryType.PrgRom) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.PrgRom));
}
if(DebugApi.GetMemorySize(SnesMemoryType.WorkRam) > 0) {
if(_cpuType == CpuType.Cpu && DebugApi.GetMemorySize(SnesMemoryType.WorkRam) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.WorkRam));
}
if(DebugApi.GetMemorySize(SnesMemoryType.SaveRam) > 0) {
@ -53,6 +53,9 @@ namespace Mesen.GUI.Debugger
if(DebugApi.GetMemorySize(SnesMemoryType.Sa1InternalRam) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.Sa1InternalRam));
}
if(DebugApi.GetMemorySize(SnesMemoryType.GsuWorkRam) > 0) {
cboBreakpointType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.GsuWorkRam));
}
if(_cpuType == CpuType.Cpu) {
if(cboBreakpointType.Items.Count > 2) {

View file

@ -0,0 +1,29 @@
using Mesen.GUI.Debugger.Controls;
using Mesen.GUI.Debugger.Integration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.GUI.Debugger.Code
{
public class GsuDisassemblyManager : CpuDisassemblyManager
{
public override CpuType CpuType { get { return CpuType.Gsu; } }
public override SnesMemoryType RelativeMemoryType { get { return SnesMemoryType.GsuMemory; } }
public override int AddressSize { get { return 6; } }
public override int ByteCodeSize { get { return 3; } }
public override bool AllowSourceView { get { return false; } }
public override void RefreshCode(DbgImporter symbolProvider, DbgImporter.FileInfo file)
{
this._provider = new CodeDataProvider(CpuType.Gsu);
}
protected override int GetFullAddress(int address, int length)
{
return address;
}
}
}

View file

@ -0,0 +1,64 @@
using Mesen.GUI.Config;
using Mesen.GUI.Debugger.Controls;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Mesen.GUI.Debugger.Code
{
public class GsuLineStyleProvider : BaseStyleProvider
{
public GsuLineStyleProvider()
{
}
public override string GetLineComment(int lineNumber)
{
return null;
}
public static void ConfigureActiveStatement(LineProperties props)
{
props.FgColor = Color.Black;
props.TextBgColor = ConfigManager.Config.Debug.Debugger.CodeActiveStatementColor;
props.Symbol |= LineSymbol.Arrow;
}
public override LineProperties GetLineStyle(CodeLineData lineData, int lineIndex)
{
DebuggerInfo cfg = ConfigManager.Config.Debug.Debugger;
LineProperties props = new LineProperties();
if(lineData.Address >= 0) {
GetBreakpointLineProperties(props, lineData.Address);
}
bool isActiveStatement = ActiveAddress.HasValue && ActiveAddress.Value == lineData.Address;
if(isActiveStatement) {
ConfigureActiveStatement(props);
}
if(lineData.Flags.HasFlag(LineFlags.VerifiedData)) {
props.LineBgColor = cfg.CodeVerifiedDataColor;
} else if(!lineData.Flags.HasFlag(LineFlags.VerifiedCode)) {
props.LineBgColor = cfg.CodeUnidentifiedDataColor;
}
return props;
}
private void GetBreakpointLineProperties(LineProperties props, int cpuAddress)
{
AddressInfo absAddress = DebugApi.GetAbsoluteAddress(new AddressInfo() { Address = cpuAddress, Type = SnesMemoryType.GsuMemory });
foreach(Breakpoint breakpoint in BreakpointManager.Breakpoints) {
if(breakpoint.Matches((uint)cpuAddress, SnesMemoryType.GsuMemory, CpuType.Gsu) || (absAddress.Address >= 0 && breakpoint.Matches((uint)absAddress.Address, absAddress.Type, CpuType.Gsu))) {
SetBreakpointLineProperties(props, breakpoint);
return;
}
}
}
}
}

View file

@ -77,6 +77,8 @@ namespace Mesen.GUI.Config
public XmlKeys OpenSpcDebugger = Keys.Control | Keys.F;
[ShortcutName("Open SA-1 Debugger")]
public XmlKeys OpenSa1Debugger = Keys.None;
[ShortcutName("Open GSU Debugger")]
public XmlKeys OpenGsuDebugger = Keys.None;
[ShortcutName("Open Event Viewer")]
public XmlKeys OpenEventViewer = Keys.Control | Keys.E;
[ShortcutName("Open Memory Tools")]

View file

@ -49,6 +49,7 @@ namespace Mesen.GUI.Config
public bool LogSpc;
public bool LogNecDsp;
public bool LogSa1;
public bool LogGsu;
public bool ShowByteCode;
public bool ShowRegisters;

View file

@ -0,0 +1,778 @@
namespace Mesen.GUI.Debugger.Controls
{
partial class ctrlGsuStatus
{
/// <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.grpSpc = new System.Windows.Forms.GroupBox();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.label1 = new System.Windows.Forms.Label();
this.lblR0 = new System.Windows.Forms.Label();
this.txtR0 = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtR1 = new System.Windows.Forms.TextBox();
this.txtR2 = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.txtR3 = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label();
this.label9 = new System.Windows.Forms.Label();
this.label10 = new System.Windows.Forms.Label();
this.label11 = new System.Windows.Forms.Label();
this.label12 = new System.Windows.Forms.Label();
this.label13 = new System.Windows.Forms.Label();
this.label14 = new System.Windows.Forms.Label();
this.label15 = new System.Windows.Forms.Label();
this.label16 = new System.Windows.Forms.Label();
this.txtR4 = new System.Windows.Forms.TextBox();
this.txtR8 = new System.Windows.Forms.TextBox();
this.txtR12 = new System.Windows.Forms.TextBox();
this.txtR5 = new System.Windows.Forms.TextBox();
this.txtR9 = new System.Windows.Forms.TextBox();
this.txtR13 = new System.Windows.Forms.TextBox();
this.txtR6 = new System.Windows.Forms.TextBox();
this.txtR10 = new System.Windows.Forms.TextBox();
this.txtR14 = new System.Windows.Forms.TextBox();
this.txtR7 = new System.Windows.Forms.TextBox();
this.txtR11 = new System.Windows.Forms.TextBox();
this.txtR15 = new System.Windows.Forms.TextBox();
this.label17 = new System.Windows.Forms.Label();
this.label18 = new System.Windows.Forms.Label();
this.txtSrc = new System.Windows.Forms.TextBox();
this.txtDest = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.txtSFR = new System.Windows.Forms.TextBox();
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
this.chkPrefix = new System.Windows.Forms.CheckBox();
this.chkAlt2 = new System.Windows.Forms.CheckBox();
this.chkZero = new System.Windows.Forms.CheckBox();
this.chkCarry = new System.Windows.Forms.CheckBox();
this.chkNegative = new System.Windows.Forms.CheckBox();
this.chkOverflow = new System.Windows.Forms.CheckBox();
this.chkAlt1 = new System.Windows.Forms.CheckBox();
this.chkIrq = new System.Windows.Forms.CheckBox();
this.chkRomRead = new System.Windows.Forms.CheckBox();
this.chkRunning = new System.Windows.Forms.CheckBox();
this.label19 = new System.Windows.Forms.Label();
this.txtProgramBank = new System.Windows.Forms.TextBox();
this.txtRamBank = new System.Windows.Forms.TextBox();
this.txtRomBank = new System.Windows.Forms.TextBox();
this.label20 = new System.Windows.Forms.Label();
this.label21 = new System.Windows.Forms.Label();
this.grpSpc.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
this.SuspendLayout();
//
// grpSpc
//
this.grpSpc.Controls.Add(this.tableLayoutPanel1);
this.grpSpc.Dock = System.Windows.Forms.DockStyle.Top;
this.grpSpc.Location = new System.Drawing.Point(0, 0);
this.grpSpc.Name = "grpSpc";
this.grpSpc.Size = new System.Drawing.Size(342, 226);
this.grpSpc.TabIndex = 0;
this.grpSpc.TabStop = false;
this.grpSpc.Text = "GSU (Super FX)";
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 9;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.label1, 2, 0);
this.tableLayoutPanel1.Controls.Add(this.lblR0, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.txtR0, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.label2, 4, 0);
this.tableLayoutPanel1.Controls.Add(this.txtR1, 3, 0);
this.tableLayoutPanel1.Controls.Add(this.txtR2, 5, 0);
this.tableLayoutPanel1.Controls.Add(this.label6, 6, 0);
this.tableLayoutPanel1.Controls.Add(this.txtR3, 7, 0);
this.tableLayoutPanel1.Controls.Add(this.label3, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.label4, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.label5, 2, 1);
this.tableLayoutPanel1.Controls.Add(this.label8, 4, 1);
this.tableLayoutPanel1.Controls.Add(this.label9, 6, 1);
this.tableLayoutPanel1.Controls.Add(this.label10, 2, 2);
this.tableLayoutPanel1.Controls.Add(this.label11, 4, 2);
this.tableLayoutPanel1.Controls.Add(this.label12, 6, 2);
this.tableLayoutPanel1.Controls.Add(this.label13, 0, 3);
this.tableLayoutPanel1.Controls.Add(this.label14, 2, 3);
this.tableLayoutPanel1.Controls.Add(this.label15, 4, 3);
this.tableLayoutPanel1.Controls.Add(this.label16, 6, 3);
this.tableLayoutPanel1.Controls.Add(this.txtR4, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.txtR8, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.txtR12, 1, 3);
this.tableLayoutPanel1.Controls.Add(this.txtR5, 3, 1);
this.tableLayoutPanel1.Controls.Add(this.txtR9, 3, 2);
this.tableLayoutPanel1.Controls.Add(this.txtR13, 3, 3);
this.tableLayoutPanel1.Controls.Add(this.txtR6, 5, 1);
this.tableLayoutPanel1.Controls.Add(this.txtR10, 5, 2);
this.tableLayoutPanel1.Controls.Add(this.txtR14, 5, 3);
this.tableLayoutPanel1.Controls.Add(this.txtR7, 7, 1);
this.tableLayoutPanel1.Controls.Add(this.txtR11, 7, 2);
this.tableLayoutPanel1.Controls.Add(this.txtR15, 7, 3);
this.tableLayoutPanel1.Controls.Add(this.label17, 0, 4);
this.tableLayoutPanel1.Controls.Add(this.label18, 2, 4);
this.tableLayoutPanel1.Controls.Add(this.txtSrc, 1, 4);
this.tableLayoutPanel1.Controls.Add(this.txtDest, 3, 4);
this.tableLayoutPanel1.Controls.Add(this.label7, 0, 5);
this.tableLayoutPanel1.Controls.Add(this.txtSFR, 1, 5);
this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 1, 7);
this.tableLayoutPanel1.Controls.Add(this.label19, 6, 4);
this.tableLayoutPanel1.Controls.Add(this.txtProgramBank, 7, 4);
this.tableLayoutPanel1.Controls.Add(this.txtRamBank, 7, 5);
this.tableLayoutPanel1.Controls.Add(this.txtRomBank, 5, 5);
this.tableLayoutPanel1.Controls.Add(this.label20, 6, 5);
this.tableLayoutPanel1.Controls.Add(this.label21, 4, 5);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 16);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 10;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel1.Size = new System.Drawing.Size(336, 207);
this.tableLayoutPanel1.TabIndex = 0;
//
// label1
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(87, 6);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(24, 13);
this.label1.TabIndex = 2;
this.label1.Text = "R1:";
//
// lblR0
//
this.lblR0.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblR0.AutoSize = true;
this.lblR0.Location = new System.Drawing.Point(3, 6);
this.lblR0.Name = "lblR0";
this.lblR0.Size = new System.Drawing.Size(24, 13);
this.lblR0.TabIndex = 0;
this.lblR0.Text = "R0:";
//
// txtR0
//
this.txtR0.Location = new System.Drawing.Point(41, 3);
this.txtR0.Name = "txtR0";
this.txtR0.Size = new System.Drawing.Size(40, 20);
this.txtR0.TabIndex = 1;
this.txtR0.Text = "DDDD";
//
// label2
//
this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(171, 6);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(24, 13);
this.label2.TabIndex = 3;
this.label2.Text = "R2:";
//
// txtR1
//
this.txtR1.Location = new System.Drawing.Point(125, 3);
this.txtR1.Name = "txtR1";
this.txtR1.Size = new System.Drawing.Size(40, 20);
this.txtR1.TabIndex = 4;
//
// txtR2
//
this.txtR2.Location = new System.Drawing.Point(209, 3);
this.txtR2.Name = "txtR2";
this.txtR2.Size = new System.Drawing.Size(40, 20);
this.txtR2.TabIndex = 5;
//
// label6
//
this.label6.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(255, 6);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(24, 13);
this.label6.TabIndex = 12;
this.label6.Text = "R3:";
//
// txtR3
//
this.txtR3.Location = new System.Drawing.Point(292, 3);
this.txtR3.Name = "txtR3";
this.txtR3.Size = new System.Drawing.Size(40, 20);
this.txtR3.TabIndex = 13;
this.txtR3.Text = "DDDD";
//
// label3
//
this.label3.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(3, 32);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(24, 13);
this.label3.TabIndex = 17;
this.label3.Text = "R4:";
//
// label4
//
this.label4.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(3, 58);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(24, 13);
this.label4.TabIndex = 18;
this.label4.Text = "R8:";
//
// label5
//
this.label5.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(87, 32);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(24, 13);
this.label5.TabIndex = 19;
this.label5.Text = "R5:";
//
// label8
//
this.label8.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(171, 32);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(24, 13);
this.label8.TabIndex = 20;
this.label8.Text = "R6:";
//
// label9
//
this.label9.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label9.AutoSize = true;
this.label9.Location = new System.Drawing.Point(255, 32);
this.label9.Name = "label9";
this.label9.Size = new System.Drawing.Size(24, 13);
this.label9.TabIndex = 21;
this.label9.Text = "R7:";
//
// label10
//
this.label10.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(87, 58);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(24, 13);
this.label10.TabIndex = 22;
this.label10.Text = "R9:";
//
// label11
//
this.label11.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(171, 58);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(30, 13);
this.label11.TabIndex = 23;
this.label11.Text = "R10:";
//
// label12
//
this.label12.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(255, 58);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(30, 13);
this.label12.TabIndex = 24;
this.label12.Text = "R11:";
//
// label13
//
this.label13.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(3, 84);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(30, 13);
this.label13.TabIndex = 25;
this.label13.Text = "R12:";
//
// label14
//
this.label14.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label14.AutoSize = true;
this.label14.Location = new System.Drawing.Point(87, 84);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(30, 13);
this.label14.TabIndex = 26;
this.label14.Text = "R13:";
//
// label15
//
this.label15.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label15.AutoSize = true;
this.label15.Location = new System.Drawing.Point(171, 84);
this.label15.Name = "label15";
this.label15.Size = new System.Drawing.Size(30, 13);
this.label15.TabIndex = 27;
this.label15.Text = "R14:";
//
// label16
//
this.label16.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label16.AutoSize = true;
this.label16.Location = new System.Drawing.Point(255, 84);
this.label16.Name = "label16";
this.label16.Size = new System.Drawing.Size(30, 13);
this.label16.TabIndex = 28;
this.label16.Text = "R15:";
//
// txtR4
//
this.txtR4.Location = new System.Drawing.Point(41, 29);
this.txtR4.Name = "txtR4";
this.txtR4.Size = new System.Drawing.Size(40, 20);
this.txtR4.TabIndex = 29;
this.txtR4.Text = "DDDD";
//
// txtR8
//
this.txtR8.Location = new System.Drawing.Point(41, 55);
this.txtR8.Name = "txtR8";
this.txtR8.Size = new System.Drawing.Size(40, 20);
this.txtR8.TabIndex = 30;
this.txtR8.Text = "DDDD";
//
// txtR12
//
this.txtR12.Location = new System.Drawing.Point(41, 81);
this.txtR12.Name = "txtR12";
this.txtR12.Size = new System.Drawing.Size(40, 20);
this.txtR12.TabIndex = 31;
this.txtR12.Text = "DDDD";
//
// txtR5
//
this.txtR5.Location = new System.Drawing.Point(125, 29);
this.txtR5.Name = "txtR5";
this.txtR5.Size = new System.Drawing.Size(40, 20);
this.txtR5.TabIndex = 32;
this.txtR5.Text = "DDDD";
//
// txtR9
//
this.txtR9.Location = new System.Drawing.Point(125, 55);
this.txtR9.Name = "txtR9";
this.txtR9.Size = new System.Drawing.Size(40, 20);
this.txtR9.TabIndex = 33;
this.txtR9.Text = "DDDD";
//
// txtR13
//
this.txtR13.Location = new System.Drawing.Point(125, 81);
this.txtR13.Name = "txtR13";
this.txtR13.Size = new System.Drawing.Size(40, 20);
this.txtR13.TabIndex = 34;
this.txtR13.Text = "DDDD";
//
// txtR6
//
this.txtR6.Location = new System.Drawing.Point(209, 29);
this.txtR6.Name = "txtR6";
this.txtR6.Size = new System.Drawing.Size(40, 20);
this.txtR6.TabIndex = 35;
this.txtR6.Text = "DDDD";
//
// txtR10
//
this.txtR10.Location = new System.Drawing.Point(209, 55);
this.txtR10.Name = "txtR10";
this.txtR10.Size = new System.Drawing.Size(40, 20);
this.txtR10.TabIndex = 36;
this.txtR10.Text = "DDDD";
//
// txtR14
//
this.txtR14.Location = new System.Drawing.Point(209, 81);
this.txtR14.Name = "txtR14";
this.txtR14.Size = new System.Drawing.Size(40, 20);
this.txtR14.TabIndex = 37;
this.txtR14.Text = "DDDD";
//
// txtR7
//
this.txtR7.Location = new System.Drawing.Point(292, 29);
this.txtR7.Name = "txtR7";
this.txtR7.Size = new System.Drawing.Size(40, 20);
this.txtR7.TabIndex = 38;
this.txtR7.Text = "DDDD";
//
// txtR11
//
this.txtR11.Location = new System.Drawing.Point(292, 55);
this.txtR11.Name = "txtR11";
this.txtR11.Size = new System.Drawing.Size(40, 20);
this.txtR11.TabIndex = 39;
this.txtR11.Text = "DDDD";
//
// txtR15
//
this.txtR15.Location = new System.Drawing.Point(292, 81);
this.txtR15.Name = "txtR15";
this.txtR15.Size = new System.Drawing.Size(40, 20);
this.txtR15.TabIndex = 40;
this.txtR15.Text = "DDDD";
//
// label17
//
this.label17.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label17.AutoSize = true;
this.label17.Location = new System.Drawing.Point(3, 110);
this.label17.Name = "label17";
this.label17.Size = new System.Drawing.Size(32, 13);
this.label17.TabIndex = 41;
this.label17.Text = "SRC:";
//
// label18
//
this.label18.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label18.AutoSize = true;
this.label18.Location = new System.Drawing.Point(87, 110);
this.label18.Name = "label18";
this.label18.Size = new System.Drawing.Size(32, 13);
this.label18.TabIndex = 42;
this.label18.Text = "DST:";
//
// txtSrc
//
this.txtSrc.Location = new System.Drawing.Point(41, 107);
this.txtSrc.Name = "txtSrc";
this.txtSrc.Size = new System.Drawing.Size(40, 20);
this.txtSrc.TabIndex = 43;
//
// txtDest
//
this.txtDest.Location = new System.Drawing.Point(125, 107);
this.txtDest.Name = "txtDest";
this.txtDest.Size = new System.Drawing.Size(40, 20);
this.txtDest.TabIndex = 44;
//
// label7
//
this.label7.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(3, 136);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(31, 13);
this.label7.TabIndex = 14;
this.label7.Text = "SFR:";
//
// txtSFR
//
this.txtSFR.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.txtSFR.Location = new System.Drawing.Point(41, 133);
this.txtSFR.Name = "txtSFR";
this.txtSFR.Size = new System.Drawing.Size(40, 20);
this.txtSFR.TabIndex = 15;
this.txtSFR.Text = "DD";
//
// tableLayoutPanel2
//
this.tableLayoutPanel2.ColumnCount = 6;
this.tableLayoutPanel1.SetColumnSpan(this.tableLayoutPanel2, 7);
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Controls.Add(this.chkPrefix, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.chkAlt2, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.chkZero, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.chkCarry, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.chkNegative, 2, 0);
this.tableLayoutPanel2.Controls.Add(this.chkOverflow, 3, 0);
this.tableLayoutPanel2.Controls.Add(this.chkAlt1, 0, 1);
this.tableLayoutPanel2.Controls.Add(this.chkIrq, 1, 1);
this.tableLayoutPanel2.Controls.Add(this.chkRomRead, 4, 0);
this.tableLayoutPanel2.Controls.Add(this.chkRunning, 4, 1);
this.tableLayoutPanel2.Location = new System.Drawing.Point(41, 159);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
this.tableLayoutPanel2.RowCount = 2;
this.tableLayoutPanel1.SetRowSpan(this.tableLayoutPanel2, 2);
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.Size = new System.Drawing.Size(288, 46);
this.tableLayoutPanel2.TabIndex = 16;
//
// chkPrefix
//
this.chkPrefix.AutoSize = true;
this.chkPrefix.Location = new System.Drawing.Point(103, 26);
this.chkPrefix.Name = "chkPrefix";
this.chkPrefix.Size = new System.Drawing.Size(33, 17);
this.chkPrefix.TabIndex = 27;
this.chkPrefix.Text = "B";
this.chkPrefix.UseVisualStyleBackColor = true;
//
// chkAlt2
//
this.chkAlt2.AutoSize = true;
this.chkAlt2.Location = new System.Drawing.Point(53, 26);
this.chkAlt2.Name = "chkAlt2";
this.chkAlt2.Size = new System.Drawing.Size(44, 17);
this.chkAlt2.TabIndex = 26;
this.chkAlt2.Text = "Alt2";
this.chkAlt2.UseVisualStyleBackColor = true;
//
// chkZero
//
this.chkZero.AutoSize = true;
this.chkZero.Location = new System.Drawing.Point(3, 3);
this.chkZero.Name = "chkZero";
this.chkZero.Size = new System.Drawing.Size(33, 17);
this.chkZero.TabIndex = 21;
this.chkZero.Text = "Z";
this.chkZero.UseVisualStyleBackColor = true;
//
// chkCarry
//
this.chkCarry.AutoSize = true;
this.chkCarry.Location = new System.Drawing.Point(53, 3);
this.chkCarry.Name = "chkCarry";
this.chkCarry.Size = new System.Drawing.Size(33, 17);
this.chkCarry.TabIndex = 23;
this.chkCarry.Text = "C";
this.chkCarry.UseVisualStyleBackColor = true;
//
// chkNegative
//
this.chkNegative.AutoSize = true;
this.chkNegative.Location = new System.Drawing.Point(103, 3);
this.chkNegative.Name = "chkNegative";
this.chkNegative.Size = new System.Drawing.Size(33, 17);
this.chkNegative.TabIndex = 17;
this.chkNegative.Text = "S";
this.chkNegative.UseVisualStyleBackColor = true;
//
// chkOverflow
//
this.chkOverflow.AutoSize = true;
this.chkOverflow.Location = new System.Drawing.Point(142, 3);
this.chkOverflow.Name = "chkOverflow";
this.chkOverflow.Size = new System.Drawing.Size(33, 17);
this.chkOverflow.TabIndex = 20;
this.chkOverflow.Text = "V";
this.chkOverflow.UseVisualStyleBackColor = true;
//
// chkAlt1
//
this.chkAlt1.AutoSize = true;
this.chkAlt1.Location = new System.Drawing.Point(3, 26);
this.chkAlt1.Name = "chkAlt1";
this.chkAlt1.Size = new System.Drawing.Size(44, 17);
this.chkAlt1.TabIndex = 19;
this.chkAlt1.Text = "Alt1";
this.chkAlt1.UseVisualStyleBackColor = true;
//
// chkIrq
//
this.chkIrq.AutoSize = true;
this.chkIrq.Location = new System.Drawing.Point(142, 26);
this.chkIrq.Name = "chkIrq";
this.chkIrq.Size = new System.Drawing.Size(45, 17);
this.chkIrq.TabIndex = 18;
this.chkIrq.Text = "IRQ";
this.chkIrq.UseVisualStyleBackColor = true;
//
// chkRomRead
//
this.chkRomRead.AutoSize = true;
this.chkRomRead.Location = new System.Drawing.Point(193, 3);
this.chkRomRead.Name = "chkRomRead";
this.chkRomRead.Size = new System.Drawing.Size(80, 17);
this.chkRomRead.TabIndex = 24;
this.chkRomRead.Text = "ROM Read";
this.chkRomRead.UseVisualStyleBackColor = true;
//
// chkRunning
//
this.chkRunning.AutoSize = true;
this.chkRunning.Location = new System.Drawing.Point(193, 26);
this.chkRunning.Name = "chkRunning";
this.chkRunning.Size = new System.Drawing.Size(66, 17);
this.chkRunning.TabIndex = 25;
this.chkRunning.Text = "Running";
this.chkRunning.UseVisualStyleBackColor = true;
//
// label19
//
this.label19.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label19.AutoSize = true;
this.label19.Location = new System.Drawing.Point(255, 110);
this.label19.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label19.Name = "label19";
this.label19.Size = new System.Drawing.Size(32, 13);
this.label19.TabIndex = 45;
this.label19.Text = "PBR:";
//
// txtProgramBank
//
this.txtProgramBank.Location = new System.Drawing.Point(292, 107);
this.txtProgramBank.Name = "txtProgramBank";
this.txtProgramBank.Size = new System.Drawing.Size(25, 20);
this.txtProgramBank.TabIndex = 46;
this.txtProgramBank.Text = "DD";
//
// txtRamBank
//
this.txtRamBank.Location = new System.Drawing.Point(292, 133);
this.txtRamBank.Name = "txtRamBank";
this.txtRamBank.Size = new System.Drawing.Size(25, 20);
this.txtRamBank.TabIndex = 49;
this.txtRamBank.Text = "DD";
//
// txtRomBank
//
this.txtRomBank.Location = new System.Drawing.Point(209, 133);
this.txtRomBank.Name = "txtRomBank";
this.txtRomBank.Size = new System.Drawing.Size(25, 20);
this.txtRomBank.TabIndex = 50;
this.txtRomBank.Text = "DD";
//
// label20
//
this.label20.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label20.AutoSize = true;
this.label20.Location = new System.Drawing.Point(255, 136);
this.label20.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label20.Name = "label20";
this.label20.Size = new System.Drawing.Size(34, 13);
this.label20.TabIndex = 47;
this.label20.Text = "RAM:";
//
// label21
//
this.label21.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.label21.AutoSize = true;
this.label21.Location = new System.Drawing.Point(171, 136);
this.label21.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label21.Name = "label21";
this.label21.Size = new System.Drawing.Size(35, 13);
this.label21.TabIndex = 48;
this.label21.Text = "ROM:";
//
// ctrlGsuStatus
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.grpSpc);
this.Name = "ctrlGsuStatus";
this.Size = new System.Drawing.Size(342, 225);
this.grpSpc.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.tableLayoutPanel2.ResumeLayout(false);
this.tableLayoutPanel2.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox grpSpc;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label lblR0;
private System.Windows.Forms.TextBox txtR0;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtR1;
private System.Windows.Forms.TextBox txtR2;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox txtR3;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.TextBox txtSFR;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
private System.Windows.Forms.CheckBox chkRunning;
private System.Windows.Forms.CheckBox chkRomRead;
private System.Windows.Forms.CheckBox chkCarry;
private System.Windows.Forms.CheckBox chkZero;
private System.Windows.Forms.CheckBox chkIrq;
private System.Windows.Forms.CheckBox chkAlt1;
private System.Windows.Forms.CheckBox chkNegative;
private System.Windows.Forms.CheckBox chkOverflow;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.Label label9;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.Label label11;
private System.Windows.Forms.Label label12;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.Label label15;
private System.Windows.Forms.Label label16;
private System.Windows.Forms.TextBox txtR4;
private System.Windows.Forms.TextBox txtR8;
private System.Windows.Forms.TextBox txtR12;
private System.Windows.Forms.TextBox txtR5;
private System.Windows.Forms.TextBox txtR9;
private System.Windows.Forms.TextBox txtR13;
private System.Windows.Forms.TextBox txtR6;
private System.Windows.Forms.TextBox txtR10;
private System.Windows.Forms.TextBox txtR14;
private System.Windows.Forms.TextBox txtR7;
private System.Windows.Forms.TextBox txtR11;
private System.Windows.Forms.TextBox txtR15;
private System.Windows.Forms.Label label17;
private System.Windows.Forms.Label label18;
private System.Windows.Forms.TextBox txtSrc;
private System.Windows.Forms.TextBox txtDest;
private System.Windows.Forms.CheckBox chkAlt2;
private System.Windows.Forms.CheckBox chkPrefix;
private System.Windows.Forms.Label label19;
private System.Windows.Forms.TextBox txtProgramBank;
private System.Windows.Forms.TextBox txtRamBank;
private System.Windows.Forms.TextBox txtRomBank;
private System.Windows.Forms.Label label20;
private System.Windows.Forms.Label label21;
}
}

View file

@ -0,0 +1,83 @@
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 Mesen.GUI.Controls;
using Mesen.GUI.Forms;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlGsuStatus : BaseControl
{
public ctrlGsuStatus()
{
InitializeComponent();
if(IsDesignMode) {
return;
}
}
public void UpdateStatus(GsuState state)
{
txtR0.Text = state.R[0].ToString("X4");
txtR1.Text = state.R[1].ToString("X4");
txtR2.Text = state.R[2].ToString("X4");
txtR3.Text = state.R[3].ToString("X4");
txtR4.Text = state.R[4].ToString("X4");
txtR5.Text = state.R[5].ToString("X4");
txtR6.Text = state.R[6].ToString("X4");
txtR7.Text = state.R[7].ToString("X4");
txtR8.Text = state.R[8].ToString("X4");
txtR9.Text = state.R[9].ToString("X4");
txtR10.Text = state.R[10].ToString("X4");
txtR11.Text = state.R[11].ToString("X4");
txtR12.Text = state.R[12].ToString("X4");
txtR13.Text = state.R[13].ToString("X4");
txtR14.Text = state.R[14].ToString("X4");
txtR15.Text = state.R[15].ToString("X4");
txtProgramBank.Text = state.ProgramBank.ToString("X2");
txtRamBank.Text = state.RamBank.ToString("X2");
txtRomBank.Text = state.RomBank.ToString("X2");
txtSrc.Text = state.SrcReg.ToString();
txtDest.Text = state.DestReg.ToString();
chkAlt1.Checked = state.SFR.Alt1;
chkAlt2.Checked = state.SFR.Alt2;
chkPrefix.Checked = state.SFR.Prefix;
chkIrq.Checked = state.SFR.Irq;
chkRunning.Checked = state.SFR.Running;
chkNegative.Checked = state.SFR.Sign;
chkZero.Checked = state.SFR.Zero;
chkOverflow.Checked = state.SFR.Overflow;
chkCarry.Checked = state.SFR.Carry;
chkRomRead.Checked = state.SFR.RomReadPending;
txtSFR.Text = GetFlags(ref state).ToString("X4");
}
private UInt16 GetFlags(ref GsuState state)
{
return (UInt16)(
(state.SFR.Zero ? 2 : 0) |
(state.SFR.Carry ? 4 : 0) |
(state.SFR.Sign ? 8 : 0) |
(state.SFR.Overflow ? 0x10 : 0) |
(state.SFR.Running ? 0x20 : 0) |
(state.SFR.RomReadPending ? 0x40 : 0) |
(state.SFR.Alt1 ? 0x100 : 0) |
(state.SFR.Alt2 ? 0x200 : 0) |
(state.SFR.ImmLow ? 0x400 : 0) |
(state.SFR.ImmHigh ? 0x800 : 0) |
(state.SFR.Prefix ? 0x1000 : 0) |
(state.SFR.Irq ? 0x8000 : 0)
);
}
}
}

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

@ -29,6 +29,7 @@ namespace Mesen.GUI.Debugger
case DebugWindow.Debugger: frm = new frmDebugger(CpuType.Cpu); frm.Icon = Properties.Resources.Debugger; break;
case DebugWindow.SpcDebugger: frm = new frmDebugger(CpuType.Spc); frm.Icon = Properties.Resources.SpcDebugger; break;
case DebugWindow.Sa1Debugger: frm = new frmDebugger(CpuType.Sa1); frm.Icon = Properties.Resources.Sa1Debugger; break;
case DebugWindow.GsuDebugger: frm = new frmDebugger(CpuType.Gsu); frm.Icon = Properties.Resources.GsuDebugger; break;
case DebugWindow.TraceLogger: frm = new frmTraceLogger(); frm.Icon = Properties.Resources.LogWindow; break;
case DebugWindow.MemoryTools: frm = new frmMemoryTools(); frm.Icon = Properties.Resources.CheatCode; break;
case DebugWindow.TileViewer: frm = new frmTileViewer(); frm.Icon = Properties.Resources.VerticalLayout; break;
@ -82,6 +83,7 @@ namespace Mesen.GUI.Debugger
case CpuType.Cpu: return (frmDebugger)OpenDebugWindow(DebugWindow.Debugger);
case CpuType.Spc: return (frmDebugger)OpenDebugWindow(DebugWindow.SpcDebugger);
case CpuType.Sa1: return (frmDebugger)OpenDebugWindow(DebugWindow.Sa1Debugger);
case CpuType.Gsu: return (frmDebugger)OpenDebugWindow(DebugWindow.GsuDebugger);
}
throw new Exception("Invalid CPU type");
}
@ -114,6 +116,7 @@ namespace Mesen.GUI.Debugger
case DebugWindow.Debugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger) && ((frmDebugger)form).CpuType == CpuType.Cpu);
case DebugWindow.SpcDebugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger) && ((frmDebugger)form).CpuType == CpuType.Spc);
case DebugWindow.Sa1Debugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger) && ((frmDebugger)form).CpuType == CpuType.Sa1);
case DebugWindow.GsuDebugger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmDebugger) && ((frmDebugger)form).CpuType == CpuType.Gsu);
case DebugWindow.TraceLogger: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmTraceLogger));
case DebugWindow.EventViewer: return _openedWindows.ToList().Find((form) => form.GetType() == typeof(frmEventViewer));
}
@ -153,6 +156,7 @@ namespace Mesen.GUI.Debugger
Debugger,
SpcDebugger,
Sa1Debugger,
GsuDebugger,
MemoryTools,
TraceLogger,
TileViewer,

View file

@ -68,9 +68,9 @@ namespace Mesen.GUI.Debugger.Labels
return _labels.Where((lbl) => lbl.Matches(cpu)).ToList<CodeLabel>();
}
private static UInt64 GetKey(UInt32 address, SnesMemoryType SnesMemoryType)
private static UInt64 GetKey(UInt32 address, SnesMemoryType memType)
{
switch(SnesMemoryType) {
switch(memType) {
case SnesMemoryType.PrgRom: return address | ((ulong)1 << 32);
case SnesMemoryType.WorkRam: return address | ((ulong)2 << 32);
case SnesMemoryType.SaveRam: return address | ((ulong)3 << 32);
@ -78,6 +78,7 @@ namespace Mesen.GUI.Debugger.Labels
case SnesMemoryType.SpcRam: return address | ((ulong)5 << 32);
case SnesMemoryType.SpcRom: return address | ((ulong)6 << 32);
case SnesMemoryType.Sa1InternalRam: return address | ((ulong)7 << 32);
case SnesMemoryType.GsuWorkRam: return address | ((ulong)8 << 32);
}
throw new Exception("Invalid type");
}

View file

@ -173,6 +173,12 @@ namespace Mesen.GUI.Debugger
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.Sa1InternalRam));
}
if(DebugApi.GetMemorySize(SnesMemoryType.GsuWorkRam) > 0) {
cboMemoryType.Items.Add("-");
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.GsuMemory));
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.GsuWorkRam));
}
cboMemoryType.SelectedIndex = 0;
cboMemoryType.SetEnumValue(originalValue);
cboMemoryType.SelectedIndexChanged += this.cboMemoryType_SelectedIndexChanged;

View file

@ -266,6 +266,10 @@ namespace Mesen.GUI.Debugger
cboMemoryType.Items.Add("-");
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.PrgRom));
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.WorkRam));
if(DebugApi.GetMemorySize(SnesMemoryType.GsuWorkRam) > 0) {
cboMemoryType.Items.Add("-");
cboMemoryType.Items.Add(ResourceHelper.GetEnumText(SnesMemoryType.GsuWorkRam));
}
cboMemoryType.SelectedIndex = 0;
cboMemoryType.EndUpdate();

View file

@ -18,6 +18,7 @@ namespace Mesen.GUI.Debugger.Workspace
public List<string> WatchValues = new List<string>();
public List<string> SpcWatchValues = new List<string>();
public List<string> Sa1WatchValues = new List<string>();
public List<string> GsuWatchValues = new List<string>();
public List<CodeLabel> CpuLabels = new List<CodeLabel>();
public List<CodeLabel> SpcLabels = new List<CodeLabel>();
public List<string> TblMappings = null;

View file

@ -26,6 +26,7 @@ namespace Mesen.GUI.Debugger.Workspace
_workspace.WatchValues = new List<string>(WatchManager.GetWatchManager(CpuType.Cpu).WatchEntries);
_workspace.SpcWatchValues = new List<string>(WatchManager.GetWatchManager(CpuType.Spc).WatchEntries);
_workspace.Sa1WatchValues = new List<string>(WatchManager.GetWatchManager(CpuType.Sa1).WatchEntries);
_workspace.GsuWatchValues = new List<string>(WatchManager.GetWatchManager(CpuType.Gsu).WatchEntries);
_workspace.Breakpoints = new List<Breakpoint>(BreakpointManager.Breakpoints);
_workspace.CpuLabels = new List<CodeLabel>(LabelManager.GetLabels(CpuType.Cpu));
_workspace.SpcLabels = new List<CodeLabel>(LabelManager.GetLabels(CpuType.Spc));
@ -47,11 +48,13 @@ namespace Mesen.GUI.Debugger.Workspace
_workspace.WatchValues = new List<string>();
_workspace.SpcWatchValues = new List<string>();
_workspace.Sa1WatchValues = new List<string>();
_workspace.GsuWatchValues = new List<string>();
_workspace.CpuLabels = new List<CodeLabel>();
_workspace.SpcLabels = new List<CodeLabel>();
WatchManager.GetWatchManager(CpuType.Cpu).WatchEntries = _workspace.WatchValues;
WatchManager.GetWatchManager(CpuType.Spc).WatchEntries = _workspace.SpcWatchValues;
WatchManager.GetWatchManager(CpuType.Sa1).WatchEntries = _workspace.Sa1WatchValues;
WatchManager.GetWatchManager(CpuType.Gsu).WatchEntries = _workspace.GsuWatchValues;
BreakpointManager.SetBreakpoints(_workspace.Breakpoints);
LabelManager.SetDefaultLabels();
LabelManager.RefreshLabels();
@ -85,6 +88,7 @@ namespace Mesen.GUI.Debugger.Workspace
WatchManager.GetWatchManager(CpuType.Cpu).WatchEntries = _workspace.WatchValues;
WatchManager.GetWatchManager(CpuType.Spc).WatchEntries = _workspace.SpcWatchValues;
WatchManager.GetWatchManager(CpuType.Sa1).WatchEntries = _workspace.Sa1WatchValues;
WatchManager.GetWatchManager(CpuType.Gsu).WatchEntries = _workspace.GsuWatchValues;
LabelManager.ResetLabels();
LabelManager.SetLabels(_workspace.CpuLabels);

View file

@ -59,6 +59,7 @@ namespace Mesen.GUI.Debugger
GetMember(nameof(DebuggerShortcutsConfig.OpenSpcDebugger)),
GetMember(nameof(DebuggerShortcutsConfig.OpenSa1Debugger)),
GetMember(nameof(DebuggerShortcutsConfig.OpenGsuDebugger)),
};
ctrlDbgShortcutsMemoryViewer.Shortcuts = new FieldInfo[] {

View file

@ -116,9 +116,10 @@
this.panel1 = new System.Windows.Forms.Panel();
this.ctrlLabelList = new Mesen.GUI.Debugger.Controls.ctrlLabelList();
this.ctrlPpuStatus = new Mesen.GUI.Debugger.Controls.ctrlPpuStatus();
this.ctrlGsuStatus = new Mesen.GUI.Debugger.Controls.ctrlGsuStatus();
this.ctrlSpcStatus = new Mesen.GUI.Debugger.Controls.ctrlSpcStatus();
this.ctrlCpuStatus = new Mesen.GUI.Debugger.Controls.ctrlCpuStatus();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.tlpBottomPanel = new System.Windows.Forms.TableLayoutPanel();
this.grpWatch = new System.Windows.Forms.GroupBox();
this.picWatchHelp = new System.Windows.Forms.PictureBox();
this.ctrlWatch = new Mesen.GUI.Debugger.ctrlWatch();
@ -133,7 +134,7 @@
this.ctrlSplitContainer.Panel2.SuspendLayout();
this.ctrlSplitContainer.SuspendLayout();
this.panel1.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.tlpBottomPanel.SuspendLayout();
this.grpWatch.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).BeginInit();
this.grpBreakpoints.SuspendLayout();
@ -208,7 +209,7 @@
//
this.mnuResetCdlLog.Image = global::Mesen.GUI.Properties.Resources.Refresh;
this.mnuResetCdlLog.Name = "mnuResetCdlLog";
this.mnuResetCdlLog.Size = new System.Drawing.Size(152, 22);
this.mnuResetCdlLog.Size = new System.Drawing.Size(122, 22);
this.mnuResetCdlLog.Text = "Reset log";
this.mnuResetCdlLog.Click += new System.EventHandler(this.mnuResetCdlLog_Click);
//
@ -766,7 +767,7 @@
//
// ctrlSplitContainer.Panel2
//
this.ctrlSplitContainer.Panel2.Controls.Add(this.tableLayoutPanel1);
this.ctrlSplitContainer.Panel2.Controls.Add(this.tlpBottomPanel);
this.ctrlSplitContainer.Panel2MinSize = 100;
this.ctrlSplitContainer.Size = new System.Drawing.Size(832, 595);
this.ctrlSplitContainer.SplitterDistance = 433;
@ -776,6 +777,7 @@
//
this.panel1.Controls.Add(this.ctrlLabelList);
this.panel1.Controls.Add(this.ctrlPpuStatus);
this.panel1.Controls.Add(this.ctrlGsuStatus);
this.panel1.Controls.Add(this.ctrlSpcStatus);
this.panel1.Controls.Add(this.ctrlCpuStatus);
this.panel1.Dock = System.Windows.Forms.DockStyle.Right;
@ -788,20 +790,29 @@
//
this.ctrlLabelList.CpuType = Mesen.GUI.CpuType.Cpu;
this.ctrlLabelList.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlLabelList.Location = new System.Drawing.Point(0, 315);
this.ctrlLabelList.Location = new System.Drawing.Point(0, 551);
this.ctrlLabelList.Name = "ctrlLabelList";
this.ctrlLabelList.Size = new System.Drawing.Size(348, 118);
this.ctrlLabelList.Size = new System.Drawing.Size(348, 0);
this.ctrlLabelList.TabIndex = 4;
//
// ctrlPpuStatus
//
this.ctrlPpuStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlPpuStatus.Location = new System.Drawing.Point(0, 268);
this.ctrlPpuStatus.Location = new System.Drawing.Point(0, 504);
this.ctrlPpuStatus.Name = "ctrlPpuStatus";
this.ctrlPpuStatus.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.ctrlPpuStatus.Size = new System.Drawing.Size(348, 47);
this.ctrlPpuStatus.TabIndex = 3;
//
// ctrlGsuStatus
//
this.ctrlGsuStatus.Dock = System.Windows.Forms.DockStyle.Top;
this.ctrlGsuStatus.Location = new System.Drawing.Point(0, 268);
this.ctrlGsuStatus.Name = "ctrlGsuStatus";
this.ctrlGsuStatus.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.ctrlGsuStatus.Size = new System.Drawing.Size(348, 236);
this.ctrlGsuStatus.TabIndex = 5;
//
// ctrlSpcStatus
//
this.ctrlSpcStatus.Dock = System.Windows.Forms.DockStyle.Top;
@ -820,22 +831,22 @@
this.ctrlCpuStatus.Size = new System.Drawing.Size(348, 148);
this.ctrlCpuStatus.TabIndex = 1;
//
// tableLayoutPanel1
// tlpBottomPanel
//
this.tableLayoutPanel1.ColumnCount = 3;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tableLayoutPanel1.Controls.Add(this.grpWatch, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.grpBreakpoints, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.grpCallstack, 2, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 1;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(832, 158);
this.tableLayoutPanel1.TabIndex = 0;
this.tlpBottomPanel.ColumnCount = 3;
this.tlpBottomPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tlpBottomPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tlpBottomPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
this.tlpBottomPanel.Controls.Add(this.grpWatch, 0, 0);
this.tlpBottomPanel.Controls.Add(this.grpBreakpoints, 1, 0);
this.tlpBottomPanel.Controls.Add(this.grpCallstack, 2, 0);
this.tlpBottomPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.tlpBottomPanel.Location = new System.Drawing.Point(0, 0);
this.tlpBottomPanel.Name = "tlpBottomPanel";
this.tlpBottomPanel.RowCount = 1;
this.tlpBottomPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tlpBottomPanel.Size = new System.Drawing.Size(832, 158);
this.tlpBottomPanel.TabIndex = 0;
//
// grpWatch
//
@ -937,7 +948,7 @@
((System.ComponentModel.ISupportInitialize)(this.ctrlSplitContainer)).EndInit();
this.ctrlSplitContainer.ResumeLayout(false);
this.panel1.ResumeLayout(false);
this.tableLayoutPanel1.ResumeLayout(false);
this.tlpBottomPanel.ResumeLayout(false);
this.grpWatch.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.picWatchHelp)).EndInit();
this.grpBreakpoints.ResumeLayout(false);
@ -973,7 +984,7 @@
private System.Windows.Forms.ToolStripMenuItem mnuBreakIn;
private System.Windows.Forms.ToolStripMenuItem mnuBreakOn;
private GUI.Controls.ctrlSplitContainer ctrlSplitContainer;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.TableLayoutPanel tlpBottomPanel;
private ctrlWatch ctrlWatch;
private System.Windows.Forms.GroupBox grpWatch;
private System.Windows.Forms.GroupBox grpBreakpoints;
@ -1045,5 +1056,6 @@
private System.Windows.Forms.ToolStripMenuItem mnuResetCdlLog;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem13;
private System.Windows.Forms.ToolStripMenuItem mnuExit;
private Controls.ctrlGsuStatus ctrlGsuStatus;
}
}

View file

@ -63,6 +63,18 @@ namespace Mesen.GUI.Debugger
ConfigApi.SetDebuggerFlag(DebuggerFlags.Sa1DebuggerEnabled, true);
this.Text = "SA-1 Debugger";
break;
case CpuType.Gsu:
ctrlDisassemblyView.Initialize(new GsuDisassemblyManager(), new GsuLineStyleProvider());
ConfigApi.SetDebuggerFlag(DebuggerFlags.GsuDebuggerEnabled, true);
this.Text = "GSU Debugger";
ctrlCallstack.Visible = false;
ctrlLabelList.Visible = false;
mnuStepOver.Visible = false;
mnuStepOut.Visible = false;
mnuStepInto.Text = "Step";
tlpBottomPanel.ColumnCount = 2;
break;
}
ctrlBreakpoints.CpuType = _cpuType;
@ -94,6 +106,7 @@ namespace Mesen.GUI.Debugger
case CpuType.Cpu: ConfigApi.SetDebuggerFlag(DebuggerFlags.CpuDebuggerEnabled, false); break;
case CpuType.Spc: ConfigApi.SetDebuggerFlag(DebuggerFlags.SpcDebuggerEnabled, false); break;
case CpuType.Sa1: ConfigApi.SetDebuggerFlag(DebuggerFlags.Sa1DebuggerEnabled, false); break;
case CpuType.Gsu: ConfigApi.SetDebuggerFlag(DebuggerFlags.GsuDebuggerEnabled, false); break;
}
BreakpointManager.RemoveCpuType(_cpuType);
@ -248,9 +261,15 @@ namespace Mesen.GUI.Debugger
private void InitToolbar()
{
tsToolbar.AddItemsToToolbar(mnuContinue, mnuBreak, null);
if(_cpuType != CpuType.Gsu) {
tsToolbar.AddItemsToToolbar(mnuStepInto, mnuStepOver, mnuStepOut, null);
} else {
tsToolbar.AddItemsToToolbar(mnuStepInto, null);
}
tsToolbar.AddItemsToToolbar(
mnuContinue, mnuBreak, null,
mnuStepInto, mnuStepOver, mnuStepOut, null,
mnuRunPpuCycle, mnuRunScanline, mnuRunOneFrame, null,
mnuToggleBreakpoint, mnuEnableDisableBreakpoint, null,
mnuBreakIn, null, mnuBreakOn
@ -338,11 +357,20 @@ namespace Mesen.GUI.Debugger
ctrlSpcStatus.Visible = false;
}
if(_cpuType == CpuType.Gsu) {
ctrlGsuStatus.UpdateStatus(state.Gsu);
} else {
ctrlGsuStatus.Visible = false;
}
ctrlPpuStatus.UpdateStatus(state);
ctrlDisassemblyView.UpdateCode();
ctrlDisassemblyView.SetActiveAddress(activeAddress);
ctrlWatch.UpdateWatch(true);
ctrlCallstack.UpdateCallstack(_cpuType);
if(_cpuType != CpuType.Gsu) {
ctrlCallstack.UpdateCallstack(_cpuType);
}
}
void ProcessBreakEvent(BreakEvent evt, DebugState state, int activeAddress)
@ -414,6 +442,7 @@ namespace Mesen.GUI.Debugger
case CpuType.Cpu: activeAddress = (int)((state.Cpu.K << 16) | state.Cpu.PC); break;
case CpuType.Spc: activeAddress = (int)state.Spc.PC; break;
case CpuType.Sa1: activeAddress = (int)((state.Sa1.K << 16) | state.Sa1.PC); break;
case CpuType.Gsu: activeAddress = (int)((state.Gsu.ProgramBank << 16) | state.Gsu.R[15]); break;
default: throw new Exception("Unsupported cpu type");
}

View file

@ -61,9 +61,11 @@ namespace Mesen.GUI.Debugger
this.cboStatusFlagFormat = new System.Windows.Forms.ComboBox();
this.chkUseWindowsEol = new System.Windows.Forms.CheckBox();
this.chkExtendZeroPage = new System.Windows.Forms.CheckBox();
this.lblTarget = new System.Windows.Forms.Label();
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
this.chkLogSa1 = new System.Windows.Forms.CheckBox();
this.chkLogCpu = new System.Windows.Forms.CheckBox();
this.chkLogSpc = new System.Windows.Forms.CheckBox();
this.lblTarget = new System.Windows.Forms.Label();
this.chkLogNecDsp = new System.Windows.Forms.CheckBox();
this.btnClearLog = new System.Windows.Forms.Button();
this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel();
@ -91,8 +93,7 @@ namespace Mesen.GUI.Debugger
this.mnuAutoRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
this.mnuRefresh = new System.Windows.Forms.ToolStripMenuItem();
this.tableLayoutPanel6 = new System.Windows.Forms.TableLayoutPanel();
this.chkLogSa1 = new System.Windows.Forms.CheckBox();
this.chkLogGsu = new System.Windows.Forms.CheckBox();
this.tableLayoutPanel1.SuspendLayout();
this.grpLogOptions.SuspendLayout();
this.tableLayoutPanel2.SuspendLayout();
@ -101,11 +102,11 @@ namespace Mesen.GUI.Debugger
this.tableLayoutPanel4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).BeginInit();
this.tableLayoutPanel6.SuspendLayout();
this.tableLayoutPanel3.SuspendLayout();
this.grpExecutionLog.SuspendLayout();
this.ctxMenu.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.tableLayoutPanel6.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
@ -541,6 +542,51 @@ namespace Mesen.GUI.Debugger
this.chkExtendZeroPage.Visible = false;
this.chkExtendZeroPage.CheckedChanged += new System.EventHandler(this.chkOptions_CheckedChanged);
//
// lblTarget
//
this.lblTarget.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblTarget.AutoSize = true;
this.lblTarget.Location = new System.Drawing.Point(3, 4);
this.lblTarget.Name = "lblTarget";
this.lblTarget.Size = new System.Drawing.Size(46, 13);
this.lblTarget.TabIndex = 23;
this.lblTarget.Text = "Targets:";
//
// tableLayoutPanel6
//
this.tableLayoutPanel6.ColumnCount = 5;
this.tableLayoutPanel2.SetColumnSpan(this.tableLayoutPanel6, 5);
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel6.Controls.Add(this.chkLogSa1, 3, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogCpu, 0, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogSpc, 1, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogNecDsp, 2, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogGsu, 4, 0);
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel6.Location = new System.Drawing.Point(81, 0);
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
this.tableLayoutPanel6.RowCount = 1;
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel6.Size = new System.Drawing.Size(589, 22);
this.tableLayoutPanel6.TabIndex = 25;
//
// chkLogSa1
//
this.chkLogSa1.AutoSize = true;
this.chkLogSa1.Checked = true;
this.chkLogSa1.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkLogSa1.Location = new System.Drawing.Point(212, 3);
this.chkLogSa1.Name = "chkLogSa1";
this.chkLogSa1.Size = new System.Drawing.Size(49, 16);
this.chkLogSa1.TabIndex = 25;
this.chkLogSa1.Text = "SA-1";
this.chkLogSa1.UseVisualStyleBackColor = true;
//
// chkLogCpu
//
this.chkLogCpu.AutoSize = true;
@ -567,16 +613,6 @@ namespace Mesen.GUI.Debugger
this.chkLogSpc.UseVisualStyleBackColor = true;
this.chkLogSpc.CheckedChanged += new System.EventHandler(this.chkOptions_CheckedChanged);
//
// lblTarget
//
this.lblTarget.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblTarget.AutoSize = true;
this.lblTarget.Location = new System.Drawing.Point(3, 4);
this.lblTarget.Name = "lblTarget";
this.lblTarget.Size = new System.Drawing.Size(46, 13);
this.lblTarget.TabIndex = 23;
this.lblTarget.Text = "Targets:";
//
// chkLogNecDsp
//
this.chkLogNecDsp.AutoSize = true;
@ -824,39 +860,17 @@ namespace Mesen.GUI.Debugger
this.mnuRefresh.Text = "Refresh";
this.mnuRefresh.Click += new System.EventHandler(this.mnuRefresh_Click);
//
// tableLayoutPanel6
// chkLogGsu
//
this.tableLayoutPanel6.ColumnCount = 5;
this.tableLayoutPanel2.SetColumnSpan(this.tableLayoutPanel6, 5);
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel6.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel6.Controls.Add(this.chkLogSa1, 3, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogCpu, 0, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogSpc, 1, 0);
this.tableLayoutPanel6.Controls.Add(this.chkLogNecDsp, 2, 0);
this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel6.Location = new System.Drawing.Point(81, 0);
this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0, 0, 0, 0);
this.tableLayoutPanel6.Name = "tableLayoutPanel6";
this.tableLayoutPanel6.RowCount = 1;
this.tableLayoutPanel6.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel6.Size = new System.Drawing.Size(589, 22);
this.tableLayoutPanel6.TabIndex = 25;
//
// chkLogSa1
//
this.chkLogSa1.AutoSize = true;
this.chkLogSa1.Checked = true;
this.chkLogSa1.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkLogSa1.Location = new System.Drawing.Point(212, 3);
this.chkLogSa1.Name = "chkLogSa1";
this.chkLogSa1.Size = new System.Drawing.Size(49, 16);
this.chkLogSa1.TabIndex = 25;
this.chkLogSa1.Text = "SA-1";
this.chkLogSa1.UseVisualStyleBackColor = true;
this.chkLogGsu.AutoSize = true;
this.chkLogGsu.Checked = true;
this.chkLogGsu.CheckState = System.Windows.Forms.CheckState.Checked;
this.chkLogGsu.Location = new System.Drawing.Point(267, 3);
this.chkLogGsu.Name = "chkLogGsu";
this.chkLogGsu.Size = new System.Drawing.Size(49, 16);
this.chkLogGsu.TabIndex = 26;
this.chkLogGsu.Text = "GSU";
this.chkLogGsu.UseVisualStyleBackColor = true;
//
// frmTraceLogger
//
@ -882,13 +896,13 @@ namespace Mesen.GUI.Debugger
this.tableLayoutPanel4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.picHelp)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.picExpressionWarning)).EndInit();
this.tableLayoutPanel6.ResumeLayout(false);
this.tableLayoutPanel6.PerformLayout();
this.tableLayoutPanel3.ResumeLayout(false);
this.grpExecutionLog.ResumeLayout(false);
this.ctxMenu.ResumeLayout(false);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.tableLayoutPanel6.ResumeLayout(false);
this.tableLayoutPanel6.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -959,5 +973,6 @@ namespace Mesen.GUI.Debugger
private System.Windows.Forms.CheckBox chkLogNecDsp;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6;
private System.Windows.Forms.CheckBox chkLogSa1;
private System.Windows.Forms.CheckBox chkLogGsu;
}
}

View file

@ -49,6 +49,7 @@ namespace Mesen.GUI.Debugger
_entityBinder.AddBinding(nameof(TraceLoggerOptions.LogSpc), chkLogSpc);
_entityBinder.AddBinding(nameof(TraceLoggerOptions.LogNecDsp), chkLogNecDsp);
_entityBinder.AddBinding(nameof(TraceLoggerOptions.LogSa1), chkLogSa1);
_entityBinder.AddBinding(nameof(TraceLoggerOptions.LogGsu), chkLogGsu);
_entityBinder.AddBinding(nameof(TraceLoggerOptions.ShowByteCode), chkShowByteCode);
//_entityBinder.AddBinding(nameof(TraceLoggerOptions.ShowCpuCycles), chkShowCpuCycles);
@ -221,6 +222,7 @@ namespace Mesen.GUI.Debugger
interopOptions.LogSpc = !disableLogging && options.LogSpc;
interopOptions.LogNecDsp = !disableLogging && options.LogNecDsp;
interopOptions.LogSa1 = !disableLogging && options.LogSa1;
interopOptions.LogGsu = !disableLogging && options.LogGsu;
interopOptions.IndentCode = options.IndentCode;
interopOptions.ShowExtraInfo = options.ShowExtraInfo;
interopOptions.UseLabels = options.UseLabels;

View file

@ -948,6 +948,7 @@
<Value ID="CpuMemory">CPU Memory</Value>
<Value ID="SpcMemory">SPC Memory</Value>
<Value ID="Sa1Memory">SA-1 Memory</Value>
<Value ID="GsuMemory">GSU Memory</Value>
<Value ID="PrgRom">PRG ROM</Value>
<Value ID="WorkRam">Work RAM</Value>
<Value ID="SaveRam">Save RAM</Value>
@ -956,10 +957,11 @@
<Value ID="CGRam">CG RAM (Palette)</Value>
<Value ID="SpcRam">SPC RAM</Value>
<Value ID="SpcRom">SPC ROM (IPL)</Value>
<Value ID="DspProgramRom">DSP-n - Program ROM</Value>
<Value ID="DspDataRom">DSP-n - Data ROM</Value>
<Value ID="DspDataRam">DSP-n - Data RAM</Value>
<Value ID="DspProgramRom">DSP-n Program ROM</Value>
<Value ID="DspDataRom">DSP-n Data ROM</Value>
<Value ID="DspDataRam">DSP-n Data RAM</Value>
<Value ID="Sa1InternalRam">SA-1 IRAM</Value>
<Value ID="GsuWorkRam">GSU Work RAM</Value>
<Value ID="Register">Register</Value>
</Enum>
<Enum ID="TileFormat">

View file

@ -59,6 +59,9 @@
this.nudExtraScanlinesBeforeNmi = new Mesen.GUI.Controls.MesenNumericUpDown();
this.lblExtraScanlinesBeforeNmi = new System.Windows.Forms.Label();
this.lblExtraScanlinesAfterNmi = new System.Windows.Forms.Label();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.nudGsuClockSpeed = new Mesen.GUI.Controls.MesenNumericUpDown();
this.lblGsuClockSpeed = new System.Windows.Forms.Label();
this.tabMain.SuspendLayout();
this.tpgGeneral.SuspendLayout();
this.tableLayoutPanel4.SuspendLayout();
@ -72,6 +75,7 @@
this.tableLayoutPanel3.SuspendLayout();
this.grpPpuTiming.SuspendLayout();
this.tableLayoutPanel5.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// baseConfigPanel
@ -405,18 +409,15 @@
this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.Controls.Add(this.lblOverclockHint, 0, 0);
this.tableLayoutPanel3.Controls.Add(this.grpPpuTiming, 0, 1);
this.tableLayoutPanel3.Controls.Add(this.tableLayoutPanel1, 0, 2);
this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel3.Name = "tableLayoutPanel3";
this.tableLayoutPanel3.RowCount = 3;
this.tableLayoutPanel3.RowCount = 4;
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel3.Size = new System.Drawing.Size(406, 264);
this.tableLayoutPanel3.TabIndex = 1;
//
@ -542,6 +543,64 @@
this.lblExtraScanlinesAfterNmi.TabIndex = 1;
this.lblExtraScanlinesAfterNmi.Text = "Additional scanlines after NMI:";
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 2;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Controls.Add(this.nudGsuClockSpeed, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.lblGsuClockSpeed, 0, 0);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 131);
this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 1;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(406, 25);
this.tableLayoutPanel1.TabIndex = 8;
//
// nudGsuClockSpeed
//
this.nudGsuClockSpeed.DecimalPlaces = 0;
this.nudGsuClockSpeed.Increment = new decimal(new int[] {
100,
0,
0,
0});
this.nudGsuClockSpeed.Location = new System.Drawing.Point(138, 3);
this.nudGsuClockSpeed.Margin = new System.Windows.Forms.Padding(0, 3, 0, 3);
this.nudGsuClockSpeed.Maximum = new decimal(new int[] {
1000,
0,
0,
0});
this.nudGsuClockSpeed.MaximumSize = new System.Drawing.Size(10000, 20);
this.nudGsuClockSpeed.Minimum = new decimal(new int[] {
100,
0,
0,
0});
this.nudGsuClockSpeed.MinimumSize = new System.Drawing.Size(0, 21);
this.nudGsuClockSpeed.Name = "nudGsuClockSpeed";
this.nudGsuClockSpeed.Size = new System.Drawing.Size(46, 21);
this.nudGsuClockSpeed.TabIndex = 4;
this.nudGsuClockSpeed.Value = new decimal(new int[] {
100,
0,
0,
0});
this.nudGsuClockSpeed.Leave += new System.EventHandler(this.nudGsuClockSpeed_Leave);
//
// lblGsuClockSpeed
//
this.lblGsuClockSpeed.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.lblGsuClockSpeed.AutoSize = true;
this.lblGsuClockSpeed.Location = new System.Drawing.Point(3, 6);
this.lblGsuClockSpeed.Name = "lblGsuClockSpeed";
this.lblGsuClockSpeed.Size = new System.Drawing.Size(132, 13);
this.lblGsuClockSpeed.TabIndex = 0;
this.lblGsuClockSpeed.Text = "Super FX clock speed (%):";
//
// frmEmulationConfig
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -577,6 +636,8 @@
this.grpPpuTiming.ResumeLayout(false);
this.tableLayoutPanel5.ResumeLayout(false);
this.tableLayoutPanel5.PerformLayout();
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -615,5 +676,8 @@
private System.Windows.Forms.Label lblExtraScanlinesBeforeNmi;
private System.Windows.Forms.Label lblExtraScanlinesAfterNmi;
private System.Windows.Forms.PictureBox picHint;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private Controls.MesenNumericUpDown nudGsuClockSpeed;
private System.Windows.Forms.Label lblGsuClockSpeed;
}
}

View file

@ -31,6 +31,7 @@ namespace Mesen.GUI.Forms.Config
AddBinding(nameof(EmulationConfig.PpuExtraScanlinesBeforeNmi), nudExtraScanlinesBeforeNmi);
AddBinding(nameof(EmulationConfig.PpuExtraScanlinesAfterNmi), nudExtraScanlinesAfterNmi);
AddBinding(nameof(EmulationConfig.GsuClockSpeed), nudGsuClockSpeed);
}
protected override void OnApply()
@ -38,5 +39,10 @@ namespace Mesen.GUI.Forms.Config
ConfigManager.Config.Emulation = (EmulationConfig)this.Entity;
ConfigManager.ApplyChanges();
}
private void nudGsuClockSpeed_Leave(object sender, EventArgs e)
{
nudGsuClockSpeed.Value = Math.Ceiling(nudGsuClockSpeed.Value / 100) * 100;
}
}
}

View file

@ -123,8 +123,7 @@
this.mnuTakeScreenshot = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDebug = new System.Windows.Forms.ToolStripMenuItem();
this.mnuDebugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSpcDebugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSa1Debugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuEventViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuMemoryTools = new System.Windows.Forms.ToolStripMenuItem();
this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuScriptWindow = new System.Windows.Forms.ToolStripMenuItem();
@ -134,7 +133,9 @@
this.mnuSpriteViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuPaletteViewer = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem22 = new System.Windows.Forms.ToolStripSeparator();
this.mnuEventViewer = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSpcDebugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuSa1Debugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuGsuDebugger = new System.Windows.Forms.ToolStripMenuItem();
this.mnuHelp = new System.Windows.Forms.ToolStripMenuItem();
this.mnuCheckForUpdates = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem20 = new System.Windows.Forms.ToolStripSeparator();
@ -868,7 +869,8 @@
this.mnuPaletteViewer,
this.toolStripMenuItem22,
this.mnuSpcDebugger,
this.mnuSa1Debugger});
this.mnuSa1Debugger,
this.mnuGsuDebugger});
this.mnuDebug.Name = "mnuDebug";
this.mnuDebug.Size = new System.Drawing.Size(54, 20);
this.mnuDebug.Text = "Debug";
@ -882,19 +884,12 @@
this.mnuDebugger.Size = new System.Drawing.Size(155, 22);
this.mnuDebugger.Text = "Debugger";
//
// mnuSpcDebugger
// mnuEventViewer
//
this.mnuSpcDebugger.Image = global::Mesen.GUI.Properties.Resources.SpcDebugger;
this.mnuSpcDebugger.Name = "mnuSpcDebugger";
this.mnuSpcDebugger.Size = new System.Drawing.Size(155, 22);
this.mnuSpcDebugger.Text = "SPC Debugger";
//
// mnuSa1Debugger
//
this.mnuSa1Debugger.Image = global::Mesen.GUI.Properties.Resources.Sa1Debugger;
this.mnuSa1Debugger.Name = "mnuSa1Debugger";
this.mnuSa1Debugger.Size = new System.Drawing.Size(155, 22);
this.mnuSa1Debugger.Text = "SA-1 Debugger";
this.mnuEventViewer.Image = global::Mesen.GUI.Properties.Resources.NesEventViewer;
this.mnuEventViewer.Name = "mnuEventViewer";
this.mnuEventViewer.Size = new System.Drawing.Size(155, 22);
this.mnuEventViewer.Text = "Event Viewer";
//
// mnuMemoryTools
//
@ -955,12 +950,26 @@
this.toolStripMenuItem22.Name = "toolStripMenuItem22";
this.toolStripMenuItem22.Size = new System.Drawing.Size(152, 6);
//
// mnuEventViewer
// mnuSpcDebugger
//
this.mnuEventViewer.Image = global::Mesen.GUI.Properties.Resources.NesEventViewer;
this.mnuEventViewer.Name = "mnuEventViewer";
this.mnuEventViewer.Size = new System.Drawing.Size(155, 22);
this.mnuEventViewer.Text = "Event Viewer";
this.mnuSpcDebugger.Image = global::Mesen.GUI.Properties.Resources.SpcDebugger;
this.mnuSpcDebugger.Name = "mnuSpcDebugger";
this.mnuSpcDebugger.Size = new System.Drawing.Size(155, 22);
this.mnuSpcDebugger.Text = "SPC Debugger";
//
// mnuSa1Debugger
//
this.mnuSa1Debugger.Image = global::Mesen.GUI.Properties.Resources.Sa1Debugger;
this.mnuSa1Debugger.Name = "mnuSa1Debugger";
this.mnuSa1Debugger.Size = new System.Drawing.Size(155, 22);
this.mnuSa1Debugger.Text = "SA-1 Debugger";
//
// mnuGsuDebugger
//
this.mnuGsuDebugger.Image = global::Mesen.GUI.Properties.Resources.GsuDebugger;
this.mnuGsuDebugger.Name = "mnuGsuDebugger";
this.mnuGsuDebugger.Size = new System.Drawing.Size(155, 22);
this.mnuGsuDebugger.Text = "GSU Debugger";
//
// mnuHelp
//
@ -1171,5 +1180,6 @@
private System.Windows.Forms.ToolStripMenuItem mnuSpriteViewer;
private System.Windows.Forms.ToolStripMenuItem mnuScriptWindow;
private System.Windows.Forms.ToolStripMenuItem mnuSa1Debugger;
private System.Windows.Forms.ToolStripMenuItem mnuGsuDebugger;
}
}

View file

@ -247,6 +247,7 @@ namespace Mesen.GUI.Forms
mnuDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenDebugger));
mnuSpcDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSpcDebugger));
mnuSa1Debugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenSa1Debugger));
mnuGsuDebugger.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenGsuDebugger));
mnuMemoryTools.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenMemoryTools));
mnuEventViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenEventViewer));
mnuTilemapViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.OpenTilemapViewer));
@ -293,6 +294,7 @@ namespace Mesen.GUI.Forms
mnuDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Debugger); };
mnuSpcDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.SpcDebugger); };
mnuSa1Debugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.Sa1Debugger); };
mnuGsuDebugger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.GsuDebugger); };
mnuTraceLogger.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.TraceLogger); };
mnuMemoryTools.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.MemoryTools); };
mnuTilemapViewer.Click += (s, e) => { DebugWindowManager.OpenDebugWindow(DebugWindow.TilemapViewer); };
@ -313,6 +315,11 @@ namespace Mesen.GUI.Forms
CoprocessorType coprocessor = EmuApi.GetRomInfo().CoprocessorType;
mnuSa1Debugger.Enabled = coprocessor == CoprocessorType.SA1;
mnuSa1Debugger.Visible = coprocessor == CoprocessorType.SA1;
mnuGsuDebugger.Enabled = coprocessor == CoprocessorType.GSU;
mnuGsuDebugger.Visible = coprocessor == CoprocessorType.GSU;
mnuTraceLogger.Enabled = running;
mnuScriptWindow.Enabled = running;

View file

@ -57,6 +57,7 @@ namespace Mesen.GUI
ShowUnidentifiedData = 0x400,
DisassembleUnidentifiedData = 0x800,
GsuDebuggerEnabled = 0x10000000,
Sa1DebuggerEnabled = 0x20000000,
SpcDebuggerEnabled = 0x40000000,
CpuDebuggerEnabled = 0x80000000

View file

@ -162,6 +162,7 @@ namespace Mesen.GUI
CpuMemory,
SpcMemory,
Sa1Memory,
GsuMemory,
PrgRom,
WorkRam,
SaveRam,
@ -174,6 +175,7 @@ namespace Mesen.GUI
DspDataRom,
DspDataRam,
Sa1InternalRam,
GsuWorkRam,
Register,
}
@ -422,6 +424,85 @@ namespace Mesen.GUI
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;
@ -430,6 +511,7 @@ namespace Mesen.GUI
public SpcState Spc;
public NecDspState NecDsp;
public CpuState Sa1;
public GsuState Gsu;
}
public enum MemoryOperationType
@ -570,6 +652,7 @@ namespace Mesen.GUI
[MarshalAs(UnmanagedType.I1)] public bool LogSpc;
[MarshalAs(UnmanagedType.I1)] public bool LogNecDsp;
[MarshalAs(UnmanagedType.I1)] public bool LogSa1;
[MarshalAs(UnmanagedType.I1)] public bool LogGsu;
[MarshalAs(UnmanagedType.I1)] public bool ShowExtraInfo;
[MarshalAs(UnmanagedType.I1)] public bool IndentCode;
@ -614,6 +697,7 @@ namespace Mesen.GUI
Spc,
NecDsp,
Sa1,
Gsu
}
public static class CpuTypeExtensions
@ -624,6 +708,7 @@ namespace Mesen.GUI
case CpuType.Cpu: return SnesMemoryType.CpuMemory;
case CpuType.Spc: return SnesMemoryType.SpcMemory;
case CpuType.Sa1: return SnesMemoryType.Sa1Memory;
case CpuType.Gsu: return SnesMemoryType.GsuMemory;
default:
throw new Exception("Invalid CPU type");
@ -636,6 +721,7 @@ namespace Mesen.GUI
case CpuType.Cpu: return 6;
case CpuType.Spc: return 4;
case CpuType.Sa1: return 6;
case CpuType.Gsu: return 6;
default:
throw new Exception("Invalid CPU type");

View file

@ -166,9 +166,7 @@ namespace Mesen.GUI
DSP2,
DSP3,
DSP4,
GSU1,
GSU2,
MarioChip,
GSU,
OBC1,
SA1,
DD1,

View file

@ -460,6 +460,16 @@ namespace Mesen.GUI.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap GsuDebugger {
get {
object obj = ResourceManager.GetObject("GsuDebugger", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>

View file

@ -457,4 +457,7 @@
<data name="Sa1Debugger" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Sa1Debugger.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="GsuDebugger" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\GsuDebugger.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

View file

@ -248,6 +248,8 @@
<Compile Include="Debugger\Code\Sa1LineStyleProvider.cs" />
<Compile Include="Debugger\Code\DbgCodeDataProvider.cs" />
<Compile Include="Debugger\Code\Sa1DisassemblyManager.cs" />
<Compile Include="Debugger\Code\GsuDisassemblyManager.cs" />
<Compile Include="Debugger\Code\GsuLineStyleProvider.cs" />
<Compile Include="Debugger\Code\SpcLineStyleProvider.cs" />
<Compile Include="Debugger\Code\CodeDataProvider.cs" />
<Compile Include="Debugger\Code\SpcDisassemblyManager.cs" />
@ -269,6 +271,12 @@
<Compile Include="Debugger\Controls\ctrlPpuStatus.Designer.cs">
<DependentUpon>ctrlPpuStatus.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlGsuStatus.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Debugger\Controls\ctrlGsuStatus.Designer.cs">
<DependentUpon>ctrlGsuStatus.cs</DependentUpon>
</Compile>
<Compile Include="Debugger\Controls\ctrlSpcStatus.cs">
<SubType>UserControl</SubType>
</Compile>
@ -822,6 +830,7 @@
<Compile Include="Utilities\Md5Helper.cs" />
<Compile Include="Updates\UpdateHelper.cs" />
<Compile Include="Utilities\XmlColor.cs" />
<None Include="Resources\GsuDebugger.png" />
<None Include="Resources\Sa1Debugger.png" />
<None Include="Dependencies\LuaScripts\DrawMode.lua">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@ -874,6 +883,9 @@
<EmbeddedResource Include="Debugger\Controls\ctrlPpuStatus.resx">
<DependentUpon>ctrlPpuStatus.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlGsuStatus.resx">
<DependentUpon>ctrlGsuStatus.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Debugger\Controls\ctrlSpcStatus.resx">
<DependentUpon>ctrlSpcStatus.cs</DependentUpon>
</EmbeddedResource>