SA-1: Fixed SA-1 vector logic
Reads done by the code should return the values at the read address, rather than returning the vector register value (fixes Gradius/Contra 3 SA-1 romhacks that are known to work on hardware)
This commit is contained in:
parent
806523055f
commit
1d6253d2e5
8 changed files with 50 additions and 37 deletions
|
@ -475,7 +475,7 @@ void Cpu::ProcessInterrupt(uint16_t vector, bool forHardwareInterrupt)
|
|||
ClearFlags(ProcFlags::Decimal);
|
||||
|
||||
_state.K = 0;
|
||||
_state.PC = ReadDataWord(vector);
|
||||
_state.PC = ReadVector(vector);
|
||||
} else {
|
||||
PushByte(_state.K);
|
||||
PushWord(_state.PC);
|
||||
|
@ -485,7 +485,7 @@ void Cpu::ProcessInterrupt(uint16_t vector, bool forHardwareInterrupt)
|
|||
ClearFlags(ProcFlags::Decimal);
|
||||
|
||||
_state.K = 0;
|
||||
_state.PC = ReadDataWord(vector);
|
||||
_state.PC = ReadVector(vector);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
Core/Cpu.cpp
16
Core/Cpu.cpp
|
@ -88,6 +88,17 @@ void Cpu::ProcessCpuCycle()
|
|||
_state.IrqLock = _dmaController->ProcessPendingTransfers();
|
||||
}
|
||||
|
||||
uint16_t Cpu::ReadVector(uint16_t vector)
|
||||
{
|
||||
//Overridden in SA-1 to return the correct value directly, rather than loading from ROM
|
||||
return ReadDataWord(vector);
|
||||
}
|
||||
|
||||
uint16_t Cpu::GetResetVector()
|
||||
{
|
||||
return _memoryManager->PeekWord(Cpu::ResetVector);
|
||||
}
|
||||
|
||||
#ifndef DUMMYCPU
|
||||
uint8_t Cpu::Read(uint32_t addr, MemoryOperationType type)
|
||||
{
|
||||
|
@ -106,8 +117,3 @@ void Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
|||
UpdateIrqNmiFlags();
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t Cpu::GetResetVector()
|
||||
{
|
||||
return _memoryManager->PeekWord(Cpu::ResetVector);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,8 @@ private:
|
|||
uint16_t ReadOperandWord();
|
||||
uint32_t ReadOperandLong();
|
||||
|
||||
uint16_t ReadVector(uint16_t vector);
|
||||
|
||||
uint8_t Read(uint32_t addr, MemoryOperationType type);
|
||||
|
||||
void SetSP(uint16_t sp);
|
||||
|
|
18
Core/Sa1.cpp
18
Core/Sa1.cpp
|
@ -603,9 +603,7 @@ void Sa1::UpdatePrgRomMappings()
|
|||
void Sa1::UpdateVectorMappings()
|
||||
{
|
||||
MemoryMappings* cpuMappings = _memoryManager->GetMemoryMappings();
|
||||
_sa1VectorHandler.reset(new Sa1VectorHandler(cpuMappings->GetHandler(0xF000), &_state, false));
|
||||
_cpuVectorHandler.reset(new Sa1VectorHandler(cpuMappings->GetHandler(0xF000), &_state, true));
|
||||
_mappings.RegisterHandler(0x00, 0x00, 0xF000, 0xFFFF, _sa1VectorHandler.get());
|
||||
_cpuVectorHandler.reset(new Sa1VectorHandler(cpuMappings->GetHandler(0xF000), &_state));
|
||||
cpuMappings->RegisterHandler(0x00, 0x00, 0xF000, 0xFFFF, _cpuVectorHandler.get());
|
||||
}
|
||||
|
||||
|
@ -785,6 +783,20 @@ CpuState Sa1::GetCpuState()
|
|||
return _cpu->GetState();
|
||||
}
|
||||
|
||||
uint16_t Sa1::ReadVector(uint16_t vector)
|
||||
{
|
||||
switch(vector) {
|
||||
case Sa1Cpu::NmiVector: return _state.Sa1NmiVector;
|
||||
case Sa1Cpu::ResetVector: return _state.Sa1ResetVector;
|
||||
case Sa1Cpu::IrqVector: return _state.Sa1IrqVector;
|
||||
}
|
||||
|
||||
//BRK/COP vectors are taken from ROM
|
||||
uint8_t low = ReadSa1(vector);
|
||||
uint8_t high = ReadSa1(vector + 1);
|
||||
return (high << 8) | low;
|
||||
}
|
||||
|
||||
MemoryMappings* Sa1::GetMemoryMappings()
|
||||
{
|
||||
return &_mappings;
|
||||
|
|
|
@ -32,7 +32,6 @@ private:
|
|||
|
||||
unique_ptr<IMemoryHandler> _iRamHandler;
|
||||
unique_ptr<IMemoryHandler> _bwRamHandler;
|
||||
unique_ptr<IMemoryHandler> _sa1VectorHandler;
|
||||
unique_ptr<IMemoryHandler> _cpuVectorHandler;
|
||||
|
||||
vector<unique_ptr<IMemoryHandler>> _cpuBwRamHandlers;
|
||||
|
@ -90,5 +89,6 @@ public:
|
|||
uint32_t DebugGetInternalRamSize();
|
||||
|
||||
CpuState GetCpuState();
|
||||
uint16_t ReadVector(uint16_t vector);
|
||||
MemoryMappings* GetMemoryMappings();
|
||||
};
|
||||
|
|
|
@ -129,9 +129,14 @@ void Sa1Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
|
|||
_sa1->WriteSa1(addr, value, type);
|
||||
}
|
||||
|
||||
uint16_t Sa1Cpu::ReadVector(uint16_t vector)
|
||||
{
|
||||
return _sa1->ReadVector(vector);
|
||||
}
|
||||
|
||||
uint16_t Sa1Cpu::GetResetVector()
|
||||
{
|
||||
return _sa1->ReadSa1(Sa1Cpu::ResetVector) | (_sa1->ReadSa1(Sa1Cpu::ResetVector+1) << 8);
|
||||
return _sa1->ReadVector(Sa1Cpu::ResetVector);
|
||||
}
|
||||
|
||||
void Sa1Cpu::IncreaseCycleCount(uint64_t cycleCount)
|
||||
|
|
|
@ -40,6 +40,7 @@ private:
|
|||
|
||||
uint8_t GetOpCode();
|
||||
|
||||
uint16_t ReadVector(uint16_t vector);
|
||||
uint16_t GetResetVector();
|
||||
|
||||
void ProcessCpuCycle(uint32_t addr);
|
||||
|
|
|
@ -9,43 +9,30 @@ class Sa1VectorHandler : public IMemoryHandler
|
|||
private:
|
||||
IMemoryHandler * _handler;
|
||||
Sa1State* _state;
|
||||
bool _forSnesCpu;
|
||||
|
||||
public:
|
||||
Sa1VectorHandler(IMemoryHandler* handler, Sa1State* state, bool forSnesCpu)
|
||||
Sa1VectorHandler(IMemoryHandler* handler, Sa1State* state)
|
||||
{
|
||||
_handler = handler;
|
||||
_state = state;
|
||||
_forSnesCpu = forSnesCpu;
|
||||
}
|
||||
|
||||
uint8_t Read(uint32_t addr) override
|
||||
{
|
||||
if(addr >= Sa1Cpu::NmiVector && addr <= Sa1Cpu::ResetVector + 1) {
|
||||
//Override the regular handlers
|
||||
if(_forSnesCpu) {
|
||||
if(_state->UseCpuNmiVector) {
|
||||
if(addr == Sa1Cpu::NmiVector) {
|
||||
return (uint8_t)_state->CpuNmiVector;
|
||||
} else if(addr == Sa1Cpu::NmiVector + 1) {
|
||||
return (uint8_t)(_state->CpuNmiVector >> 8);
|
||||
}
|
||||
if(_state->UseCpuNmiVector) {
|
||||
if(addr == Sa1Cpu::NmiVector) {
|
||||
return (uint8_t)_state->CpuNmiVector;
|
||||
} else if(addr == Sa1Cpu::NmiVector + 1) {
|
||||
return (uint8_t)(_state->CpuNmiVector >> 8);
|
||||
}
|
||||
if(_state->UseCpuIrqVector) {
|
||||
if(addr == Sa1Cpu::IrqVector) {
|
||||
return (uint8_t)_state->CpuIrqVector;
|
||||
} else if(addr == Sa1Cpu::IrqVector + 1) {
|
||||
return (uint8_t)(_state->CpuIrqVector >> 8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch(addr) {
|
||||
case Sa1Cpu::NmiVector: return (uint8_t)_state->Sa1NmiVector;
|
||||
case Sa1Cpu::NmiVector + 1: return (uint8_t)(_state->Sa1NmiVector >> 8);
|
||||
case Sa1Cpu::ResetVector: return (uint8_t)_state->Sa1ResetVector;
|
||||
case Sa1Cpu::ResetVector + 1: return (uint8_t)(_state->Sa1ResetVector >> 8);
|
||||
case Sa1Cpu::IrqVector: return (uint8_t)_state->Sa1IrqVector;
|
||||
case Sa1Cpu::IrqVector + 1: return (uint8_t)(_state->Sa1IrqVector >> 8);
|
||||
}
|
||||
if(_state->UseCpuIrqVector) {
|
||||
if(addr == Sa1Cpu::IrqVector) {
|
||||
return (uint8_t)_state->CpuIrqVector;
|
||||
} else if(addr == Sa1Cpu::IrqVector + 1) {
|
||||
return (uint8_t)(_state->CpuIrqVector >> 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue