Merge pull request #12 from lab313ru/regs_write

Registers change APIs.
This commit is contained in:
NovaSquirrel 2020-10-11 14:34:31 -04:00 committed by GitHub
commit 9d3d0bccc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 532 additions and 8 deletions

View file

@ -117,3 +117,45 @@ void Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
UpdateIrqNmiFlags();
}
#endif
void Cpu::SetReg(CpuRegister reg, uint16_t value)
{
switch (reg) {
case CpuRegister::CpuRegA:
{
_state.A = value;
} break;
case CpuRegister::CpuRegX:
{
_state.X = value;
} break;
case CpuRegister::CpuRegY:
{
_state.Y = value;
} break;
case CpuRegister::CpuRegSP:
{
_state.SP = value;
} break;
case CpuRegister::CpuRegD:
{
_state.D = value;
} break;
case CpuRegister::CpuRegPC:
{
_state.PC = value;
} break;
case CpuRegister::CpuRegK:
{
_state.K = value & 0xFF;
} break;
case CpuRegister::CpuRegDBR:
{
_state.DBR = value & 0xFF;
} break;
case CpuRegister::CpuRegPS:
{
_state.PS = value & 0xFF;
} break;
}
}

View file

@ -7,6 +7,7 @@
#include "stdafx.h"
#include "CpuTypes.h"
#include "DebugTypes.h"
#include "../Utilities/ISerializable.h"
class MemoryMappings;
@ -345,6 +346,8 @@ public:
// Inherited via ISerializable
void Serialize(Serializer &s) override;
void SetReg(CpuRegister reg, uint16_t value);
#ifdef DUMMYCPU
private:
MemoryMappings* _memoryMappings;
@ -370,6 +373,8 @@ public:
#endif
};
void SetReg(CpuRegister reg, uint16_t value);
template<uint64_t count>
void Cpu::IncreaseCycleCount()
{

View file

@ -478,4 +478,37 @@ uint32_t Cx4::DebugGetDataRamSize()
Cx4State Cx4::GetState()
{
return _state;
}
void Cx4::SetReg(Cx4Register reg, uint32_t value)
{
switch (reg)
{
case Cx4Register::Cx4Reg0: case Cx4Register::Cx4Reg1: case Cx4Register::Cx4Reg2: case Cx4Register::Cx4Reg3:
case Cx4Register::Cx4Reg4: case Cx4Register::Cx4Reg5: case Cx4Register::Cx4Reg6: case Cx4Register::Cx4Reg7:
case Cx4Register::Cx4Reg8: case Cx4Register::Cx4Reg9: case Cx4Register::Cx4Reg10: case Cx4Register::Cx4Reg11:
case Cx4Register::Cx4Reg12: case Cx4Register::Cx4Reg13: case Cx4Register::Cx4Reg14: case Cx4Register::Cx4Reg15:
_state.Regs[(static_cast<int>(reg) - static_cast<int>(Cx4Register::Cx4Reg0)) & 0x0F] = value & 0xFFFFFF; // 24-bit
break;
case Cx4Register::Cx4RegPB:
{
_state.PB = value & 0xFFFF;
} break;
case Cx4Register::Cx4RegPC:
{
_state.PC = value & 0xFF;
} break;
case Cx4Register::Cx4RegA:
{
_state.A = value & 0xFFFFFF; // 24-bit
} break;
case Cx4Register::Cx4RegP:
{
_state.P = value & 0xFFFF;
} break;
case Cx4Register::Cx4RegSP:
{
_state.SP = value & 0xFF;
} break;
}
}

View file

@ -129,4 +129,6 @@ public:
uint8_t* DebugGetDataRam();
uint32_t DebugGetDataRamSize();
Cx4State GetState();
void SetReg(Cx4Register reg, uint32_t value);
};

View file

@ -284,3 +284,108 @@ enum class CpuType : uint8_t
Cx4,
Gameboy
};
enum class CpuRegister : uint8_t
{
CpuRegA,
CpuRegX,
CpuRegY,
CpuRegSP,
CpuRegD,
CpuRegPC,
CpuRegK,
CpuRegDBR,
CpuRegPS
};
enum class Cx4Register : uint8_t
{
Cx4Reg0,
Cx4Reg1,
Cx4Reg2,
Cx4Reg3,
Cx4Reg4,
Cx4Reg5,
Cx4Reg6,
Cx4Reg7,
Cx4Reg8,
Cx4Reg9,
Cx4Reg10,
Cx4Reg11,
Cx4Reg12,
Cx4Reg13,
Cx4Reg14,
Cx4Reg15,
Cx4RegPB,
Cx4RegPC,
Cx4RegA,
Cx4RegP,
Cx4RegSP
};
enum class GbRegister : uint8_t
{
GbRegPC,
GbRegSP,
GbRegA,
GbRegFlags,
GbRegB,
GbRegC,
GbRegD,
GbRegE,
GbRegH,
GbRegL
};
enum class GsuRegister : uint8_t
{
GsuReg0,
GsuReg1,
GsuReg2,
GsuReg3,
GsuReg4,
GsuReg5,
GsuReg6,
GsuReg7,
GsuReg8,
GsuReg9,
GsuRegA,
GsuRegB,
GsuRegC,
GsuRegD,
GsuRegE,
GsuRegF,
GsuRegSFR
};
enum class NecDspRegister : uint8_t
{
NecDspRegA,
NecDspRegFlagsA,
NecDspRegB,
NecDspRegFlagsB,
NecDspRegTR,
NecDspRegTRB,
NecDspRegPC,
NecDspRegRP,
NecDspRegDP,
NecDspRegDR,
NecDspRegSR,
NecDspRegK,
NecDspRegL,
NecDspRegM,
NecDspRegN,
NecDspRegSerialOut,
NecDspRegSerialIn,
NecDspRegSP
};
enum class SpcRegister : uint8_t
{
SpcRegPC,
SpcRegA,
SpcRegX,
SpcRegY,
SpcRegSP,
SpcRegPS
};

View file

@ -511,6 +511,41 @@ void Debugger::GetState(DebugState &state, bool partialPpuState)
}
}
void Debugger::SetCpuRegister(CpuRegister reg, uint16_t value)
{
_cpu->SetReg(reg, value);
}
void Debugger::SetCx4Register(Cx4Register reg, uint32_t value)
{
_cart->GetCx4()->SetReg(reg, value);
}
void Debugger::SetGameboyRegister(GbRegister reg, uint16_t value)
{
_cart->GetGameboy()->SetReg(reg, value);
}
void Debugger::SetGsuRegister(GsuRegister reg, uint16_t value)
{
_cart->GetGsu()->SetReg(reg, value);
}
void Debugger::SetNecDspRegister(NecDspRegister reg, uint16_t value)
{
_cart->GetDsp()->SetReg(reg, value);
}
void Debugger::SetSa1Register(CpuRegister reg, uint16_t value)
{
_cart->GetSa1()->SetReg(reg, value);
}
void Debugger::SetSpcRegister(SpcRegister reg, uint16_t value)
{
_spc->SetReg(reg, value);
}
AddressInfo Debugger::GetAbsoluteAddress(AddressInfo relAddress)
{
if(relAddress.Type == SnesMemoryType::CpuMemory) {

View file

@ -127,7 +127,15 @@ public:
void ProcessBreakConditions(bool needBreak, BreakpointManager *bpManager, MemoryOperationInfo &operation, AddressInfo &addressInfo, BreakSource source = BreakSource::Unspecified);
void SleepUntilResume(BreakSource source, MemoryOperationInfo* operation = nullptr, int breakpointId = -1);
void GetState(DebugState &state, bool partialPpuState);
void GetState(DebugState& state, bool partialPpuState);
void SetCpuRegister(CpuRegister reg, uint16_t value);
void SetCx4Register(Cx4Register reg, uint32_t value);
void SetGameboyRegister(GbRegister reg, uint16_t value);
void SetGsuRegister(GsuRegister reg, uint16_t value);
void SetNecDspRegister(NecDspRegister reg, uint16_t value);
void SetSa1Register(CpuRegister reg, uint16_t value);
void SetSpcRegister(SpcRegister reg, uint16_t value);
AddressInfo GetAbsoluteAddress(AddressInfo relAddress);
AddressInfo GetRelativeAddress(AddressInfo absAddress, CpuType cpuType);

View file

@ -364,3 +364,8 @@ void Gameboy::Serialize(Serializer& s)
s.StreamArray(_spriteRam, Gameboy::SpriteRamSize);
s.StreamArray(_highRam, Gameboy::HighRamSize);
}
void Gameboy::SetReg(GbRegister reg, uint16_t value)
{
_cpu->SetReg(reg, value);
}

View file

@ -92,4 +92,6 @@ public:
uint64_t GetApuCycleCount();
void Serialize(Serializer& s) override;
void SetReg(GbRegister reg, uint16_t value);
};

View file

@ -1389,3 +1389,50 @@ void GbCpu::Serialize(Serializer& s)
_state.EiPending
);
}
void GbCpu::SetReg(GbRegister reg, uint16_t value)
{
switch (reg)
{
case GbRegister::GbRegPC:
{
_state.PC = value;
} break;
case GbRegister::GbRegSP:
{
_state.SP = value;
} break;
case GbRegister::GbRegA:
{
_state.A = value & 0xFF;
} break;
case GbRegister::GbRegFlags:
{
_state.Flags = value & 0xFF;
} break;
case GbRegister::GbRegB:
{
_state.B = value & 0xFF;
} break;
case GbRegister::GbRegC:
{
_state.C = value & 0xFF;
} break;
case GbRegister::GbRegD:
{
_state.D = value & 0xFF;
} break;
case GbRegister::GbRegE:
{
_state.E = value & 0xFF;
} break;
case GbRegister::GbRegH:
{
_state.H = value & 0xFF;
} break;
case GbRegister::GbRegL:
{
_state.L = value & 0xFF;
} break;
}
}

View file

@ -150,4 +150,6 @@ public:
void Exec();
void Serialize(Serializer& s) override;
void SetReg(GbRegister reg, uint16_t value);
};

View file

@ -651,3 +651,33 @@ uint32_t Gsu::DebugGetWorkRamSize()
{
return _gsuRamSize;
}
void Gsu::SetReg(GsuRegister reg, uint16_t value)
{
switch (reg)
{
case GsuRegister::GsuReg0:
case GsuRegister::GsuReg1:
case GsuRegister::GsuReg2:
case GsuRegister::GsuReg3:
case GsuRegister::GsuReg4:
case GsuRegister::GsuReg5:
case GsuRegister::GsuReg6:
case GsuRegister::GsuReg7:
case GsuRegister::GsuReg8:
case GsuRegister::GsuReg9:
case GsuRegister::GsuRegA:
case GsuRegister::GsuRegB:
case GsuRegister::GsuRegC:
case GsuRegister::GsuRegD:
case GsuRegister::GsuRegE:
case GsuRegister::GsuRegF:
{
_state.R[static_cast<int>(reg) & 0xF] = value;
} break;
case GsuRegister::GsuRegSFR:
{
_state.SFR.SetFlags(value);
} break;
}
}

View file

@ -170,4 +170,6 @@ public:
MemoryMappings* GetMemoryMappings();
uint8_t* DebugGetWorkRam();
uint32_t DebugGetWorkRamSize();
void SetReg(GsuRegister reg, uint16_t value);
};

View file

@ -39,6 +39,27 @@ struct GsuFlags
(Irq << 7)
);
}
void SetFlags(uint16_t flags)
{
// 0 bit is clear
Zero = flags & (1 << 1);
Carry = flags & (1 << 2);
Sign = flags & (1 << 3);
Overflow = flags & (1 << 4);
Running = flags & (1 << 5);
RomReadPending = flags & (1 << 6);
// 7 bit is clear
Alt1 = flags & (1 << (8 + 0));
Alt2 = flags & (1 << (8 + 1));
ImmLow = flags & (1 << (8 + 2));
ImmHigh = flags & (1 << (8 + 3));
Prefix = flags & (1 << (8 + 4));
// 5 bit is clear
// 6 bit is clear
Irq = flags & (1 << (8 + 7));
}
};
struct GsuPixelCache

View file

@ -586,3 +586,82 @@ void NecDsp::Serialize(Serializer &s)
s.StreamArray<uint16_t>(_stack, _stackSize);
}
void NecDsp::SetReg(NecDspRegister reg, uint16_t value)
{
switch (reg)
{
case NecDspRegister::NecDspRegA:
{
_state.A = value;
} break;
case NecDspRegister::NecDspRegFlagsA:
{
_state.FlagsA.SetFlags(value & 0xFF);
} break;
case NecDspRegister::NecDspRegB:
{
_state.B = value;
} break;
case NecDspRegister::NecDspRegFlagsB:
{
_state.FlagsB.SetFlags(value & 0xFF);
} break;
case NecDspRegister::NecDspRegTR:
{
_state.TR = value;
} break;
case NecDspRegister::NecDspRegTRB:
{
_state.TRB = value;
} break;
case NecDspRegister::NecDspRegPC:
{
_state.PC = value;
} break;
case NecDspRegister::NecDspRegRP:
{
_state.RP = value;
} break;
case NecDspRegister::NecDspRegDP:
{
_state.DP = value;
} break;
case NecDspRegister::NecDspRegDR:
{
_state.DR = value;
} break;
case NecDspRegister::NecDspRegSR:
{
_state.SR = value;
} break;
case NecDspRegister::NecDspRegK:
{
_state.K = value;
} break;
case NecDspRegister::NecDspRegL:
{
_state.L = value;
} break;
case NecDspRegister::NecDspRegM:
{
_state.M = value;
} break;
case NecDspRegister::NecDspRegN:
{
_state.N = value;
} break;
case NecDspRegister::NecDspRegSerialOut:
{
_state.SerialOut = value;
} break;
case NecDspRegister::NecDspRegSerialIn:
{
_state.SerialIn = value;
} break;
case NecDspRegister::NecDspRegSP:
{
_state.SP = value & 0xFF;
} break;
}
}

View file

@ -82,4 +82,6 @@ public:
NecDspState GetState();
void Serialize(Serializer &s) override;
void SetReg(NecDspRegister reg, uint16_t value);
};

View file

@ -9,6 +9,16 @@ struct NecDspAccFlags
bool Overflow1;
bool Sign0;
bool Sign1;
void SetFlags(uint8_t flags)
{
Carry = flags & (1 << 0);
Zero = flags & (1 << 1);
Overflow0 = flags & (1 << 2);
Overflow1 = flags & (1 << 3);
Sign0 = flags & (1 << 4);
Sign1 = flags & (1 << 5);
}
};
namespace NecDspStatusFlags

View file

@ -1723,7 +1723,7 @@ uint8_t Ppu::Read(uint16_t addr)
if(_regs->GetIoPortOutput() & 0x80) {
_locationLatched = false;
//"The high/low selector is reset to <EFBFBD>elow<EFBFBD>f when $213F is read" (the selector is NOT reset when the counter is latched)
//"The high/low selector is reset to ?elow?f when $213F is read" (the selector is NOT reset when the counter is latched)
_horizontalLocToggle = false;
_verticalLocationToggle = false;
}
@ -1832,7 +1832,7 @@ void Ppu::Write(uint32_t addr, uint8_t value)
_state.MosaicSize = ((value & 0xF0) >> 4) + 1;
uint8_t mosaicEnabled = value & 0x0F;
if(!_state.MosaicEnabled && mosaicEnabled) {
//"If this register is set during the frame, the <EFBFBD>starting scanline is the current scanline, otherwise it is the first visible scanline of the frame."
//"If this register is set during the frame, the ?starting scanline is the current scanline, otherwise it is the first visible scanline of the frame."
//This is only done when mosaic is turned on from an off state (FF6 mosaic effect looks wrong otherwise)
//FF6's mosaic effect is broken on some screens without this.
_mosaicScanlineCounter = _state.MosaicSize + 1;
@ -2317,4 +2317,4 @@ void Ppu::RenderTilemapMode7()
} else {
RenderTilemapMode7<layerIndex, normalPriority, highPriority, applyMosaic, false>();
}
}
}

View file

@ -863,4 +863,9 @@ void Sa1::Serialize(Serializer &s)
UpdateSaveRamMappings();
ProcessInterrupts();
}
}
}
void Sa1::SetReg(CpuRegister reg, uint16_t value)
{
_cpu->SetReg(reg, value);
}

View file

@ -95,4 +95,6 @@ public:
MemoryMappings* GetMemoryMappings();
void LoadBattery() override;
void SaveBattery() override;
void SetReg(CpuRegister reg, uint16_t value);
};

View file

@ -142,4 +142,46 @@ uint16_t Sa1Cpu::GetResetVector()
void Sa1Cpu::IncreaseCycleCount(uint64_t cycleCount)
{
_state.CycleCount += cycleCount;
}
}
void Sa1Cpu::SetReg(CpuRegister reg, uint16_t value)
{
switch (reg) {
case CpuRegister::CpuRegA:
{
_state.A = value;
} break;
case CpuRegister::CpuRegX:
{
_state.X = value;
} break;
case CpuRegister::CpuRegY:
{
_state.Y = value;
} break;
case CpuRegister::CpuRegSP:
{
_state.SP = value;
} break;
case CpuRegister::CpuRegD:
{
_state.D = value;
} break;
case CpuRegister::CpuRegPC:
{
_state.PC = value;
} break;
case CpuRegister::CpuRegK:
{
_state.K = value & 0xFF;
} break;
case CpuRegister::CpuRegDBR:
{
_state.DBR = value & 0xFF;
} break;
case CpuRegister::CpuRegPS:
{
_state.PS = value & 0xFF;
} break;
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "stdafx.h"
#include "CpuTypes.h"
#include "DebugTypes.h"
#include "../Utilities/ISerializable.h"
class Sa1;
@ -333,6 +334,8 @@ public:
// Inherited via ISerializable
void Serialize(Serializer &s) override;
void SetReg(CpuRegister reg, uint16_t value);
};
template<uint64_t count>

View file

@ -582,4 +582,35 @@ void Spc::LoadSpcFile(SpcFileData* data)
_state.Timer0.SetOutput(data->TimerOutput[0]);
_state.Timer1.SetOutput(data->TimerOutput[0]);
_state.Timer2.SetOutput(data->TimerOutput[0]);
}
}
void Spc::SetReg(SpcRegister reg, uint16_t value)
{
switch (reg)
{
case SpcRegister::SpcRegPC:
{
_state.PC = value;
} break;
case SpcRegister::SpcRegA:
{
_state.A = value & 0xFF;
} break;
case SpcRegister::SpcRegX:
{
_state.X = value & 0xFF;
} break;
case SpcRegister::SpcRegY:
{
_state.Y = value & 0xFF;
} break;
case SpcRegister::SpcRegSP:
{
_state.SP = value & 0xFF;
} break;
case SpcRegister::SpcRegPS:
{
_state.PS = value & 0xFF;
} break;
}
}

View file

@ -8,6 +8,7 @@
#include "stdafx.h"
#include "SpcTypes.h"
#include "CpuTypes.h"
#include "DebugTypes.h"
#include "SpcTimer.h"
#include "../Utilities/ISerializable.h"
@ -317,6 +318,8 @@ public:
void Serialize(Serializer &s) override;
void SetReg(SpcRegister reg, uint16_t value);
#ifdef DUMMYSPC
private:
uint32_t _writeCounter = 0;

View file

@ -67,7 +67,15 @@ extern "C"
DllExport void __stdcall ResetProfiler(CpuType cpuType) { GetDebugger()->GetCallstackManager(cpuType)->GetProfiler()->Reset(); }
DllExport void __stdcall GetState(DebugState& state) { GetDebugger()->GetState(state, false); }
DllExport void __stdcall SetCpuRegister(CpuRegister reg, uint16_t value) { GetDebugger()->SetCpuRegister(reg, value); }
DllExport void __stdcall SetSpcRegister(SpcRegister reg, uint32_t value) { GetDebugger()->SetSpcRegister(reg, value); }
DllExport void __stdcall SetNecDspRegister(NecDspRegister reg, uint32_t value) { GetDebugger()->SetNecDspRegister(reg, value); }
DllExport void __stdcall SetSa1Register(CpuRegister reg, uint32_t value) { GetDebugger()->SetSa1Register(reg, value); }
DllExport void __stdcall SetGsuRegister(GsuRegister reg, uint32_t value) { GetDebugger()->SetGsuRegister(reg, value); }
DllExport void __stdcall SetCx4Register(Cx4Register reg, uint32_t value) { GetDebugger()->SetCx4Register(reg, value); }
DllExport void __stdcall SetGameboyRegister(GbRegister reg, uint32_t value) { GetDebugger()->SetGameboyRegister(reg, value); }
DllExport const char* __stdcall GetDebuggerLog()
{
_logString = GetDebugger()->GetLog();