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:
Sour 2020-03-01 17:51:02 -05:00
parent 806523055f
commit 1d6253d2e5
8 changed files with 50 additions and 37 deletions

View file

@ -475,7 +475,7 @@ void Cpu::ProcessInterrupt(uint16_t vector, bool forHardwareInterrupt)
ClearFlags(ProcFlags::Decimal); ClearFlags(ProcFlags::Decimal);
_state.K = 0; _state.K = 0;
_state.PC = ReadDataWord(vector); _state.PC = ReadVector(vector);
} else { } else {
PushByte(_state.K); PushByte(_state.K);
PushWord(_state.PC); PushWord(_state.PC);
@ -485,7 +485,7 @@ void Cpu::ProcessInterrupt(uint16_t vector, bool forHardwareInterrupt)
ClearFlags(ProcFlags::Decimal); ClearFlags(ProcFlags::Decimal);
_state.K = 0; _state.K = 0;
_state.PC = ReadDataWord(vector); _state.PC = ReadVector(vector);
} }
} }

View file

@ -88,6 +88,17 @@ void Cpu::ProcessCpuCycle()
_state.IrqLock = _dmaController->ProcessPendingTransfers(); _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 #ifndef DUMMYCPU
uint8_t Cpu::Read(uint32_t addr, MemoryOperationType type) 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(); UpdateIrqNmiFlags();
} }
#endif #endif
uint16_t Cpu::GetResetVector()
{
return _memoryManager->PeekWord(Cpu::ResetVector);
}

View file

@ -63,6 +63,8 @@ private:
uint16_t ReadOperandWord(); uint16_t ReadOperandWord();
uint32_t ReadOperandLong(); uint32_t ReadOperandLong();
uint16_t ReadVector(uint16_t vector);
uint8_t Read(uint32_t addr, MemoryOperationType type); uint8_t Read(uint32_t addr, MemoryOperationType type);
void SetSP(uint16_t sp); void SetSP(uint16_t sp);

View file

@ -603,9 +603,7 @@ void Sa1::UpdatePrgRomMappings()
void Sa1::UpdateVectorMappings() void Sa1::UpdateVectorMappings()
{ {
MemoryMappings* cpuMappings = _memoryManager->GetMemoryMappings(); MemoryMappings* cpuMappings = _memoryManager->GetMemoryMappings();
_sa1VectorHandler.reset(new Sa1VectorHandler(cpuMappings->GetHandler(0xF000), &_state, false)); _cpuVectorHandler.reset(new Sa1VectorHandler(cpuMappings->GetHandler(0xF000), &_state));
_cpuVectorHandler.reset(new Sa1VectorHandler(cpuMappings->GetHandler(0xF000), &_state, true));
_mappings.RegisterHandler(0x00, 0x00, 0xF000, 0xFFFF, _sa1VectorHandler.get());
cpuMappings->RegisterHandler(0x00, 0x00, 0xF000, 0xFFFF, _cpuVectorHandler.get()); cpuMappings->RegisterHandler(0x00, 0x00, 0xF000, 0xFFFF, _cpuVectorHandler.get());
} }
@ -785,6 +783,20 @@ CpuState Sa1::GetCpuState()
return _cpu->GetState(); 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() MemoryMappings* Sa1::GetMemoryMappings()
{ {
return &_mappings; return &_mappings;

View file

@ -32,7 +32,6 @@ private:
unique_ptr<IMemoryHandler> _iRamHandler; unique_ptr<IMemoryHandler> _iRamHandler;
unique_ptr<IMemoryHandler> _bwRamHandler; unique_ptr<IMemoryHandler> _bwRamHandler;
unique_ptr<IMemoryHandler> _sa1VectorHandler;
unique_ptr<IMemoryHandler> _cpuVectorHandler; unique_ptr<IMemoryHandler> _cpuVectorHandler;
vector<unique_ptr<IMemoryHandler>> _cpuBwRamHandlers; vector<unique_ptr<IMemoryHandler>> _cpuBwRamHandlers;
@ -90,5 +89,6 @@ public:
uint32_t DebugGetInternalRamSize(); uint32_t DebugGetInternalRamSize();
CpuState GetCpuState(); CpuState GetCpuState();
uint16_t ReadVector(uint16_t vector);
MemoryMappings* GetMemoryMappings(); MemoryMappings* GetMemoryMappings();
}; };

View file

@ -129,9 +129,14 @@ void Sa1Cpu::Write(uint32_t addr, uint8_t value, MemoryOperationType type)
_sa1->WriteSa1(addr, value, type); _sa1->WriteSa1(addr, value, type);
} }
uint16_t Sa1Cpu::ReadVector(uint16_t vector)
{
return _sa1->ReadVector(vector);
}
uint16_t Sa1Cpu::GetResetVector() 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) void Sa1Cpu::IncreaseCycleCount(uint64_t cycleCount)

View file

@ -40,6 +40,7 @@ private:
uint8_t GetOpCode(); uint8_t GetOpCode();
uint16_t ReadVector(uint16_t vector);
uint16_t GetResetVector(); uint16_t GetResetVector();
void ProcessCpuCycle(uint32_t addr); void ProcessCpuCycle(uint32_t addr);

View file

@ -9,43 +9,30 @@ class Sa1VectorHandler : public IMemoryHandler
private: private:
IMemoryHandler * _handler; IMemoryHandler * _handler;
Sa1State* _state; Sa1State* _state;
bool _forSnesCpu;
public: public:
Sa1VectorHandler(IMemoryHandler* handler, Sa1State* state, bool forSnesCpu) Sa1VectorHandler(IMemoryHandler* handler, Sa1State* state)
{ {
_handler = handler; _handler = handler;
_state = state; _state = state;
_forSnesCpu = forSnesCpu;
} }
uint8_t Read(uint32_t addr) override uint8_t Read(uint32_t addr) override
{ {
if(addr >= Sa1Cpu::NmiVector && addr <= Sa1Cpu::ResetVector + 1) { if(addr >= Sa1Cpu::NmiVector && addr <= Sa1Cpu::ResetVector + 1) {
//Override the regular handlers //Override the regular handlers
if(_forSnesCpu) { if(_state->UseCpuNmiVector) {
if(_state->UseCpuNmiVector) { if(addr == Sa1Cpu::NmiVector) {
if(addr == Sa1Cpu::NmiVector) { return (uint8_t)_state->CpuNmiVector;
return (uint8_t)_state->CpuNmiVector; } else if(addr == Sa1Cpu::NmiVector + 1) {
} else if(addr == Sa1Cpu::NmiVector + 1) { return (uint8_t)(_state->CpuNmiVector >> 8);
return (uint8_t)(_state->CpuNmiVector >> 8);
}
} }
if(_state->UseCpuIrqVector) { }
if(addr == Sa1Cpu::IrqVector) { if(_state->UseCpuIrqVector) {
return (uint8_t)_state->CpuIrqVector; if(addr == Sa1Cpu::IrqVector) {
} else if(addr == Sa1Cpu::IrqVector + 1) { return (uint8_t)_state->CpuIrqVector;
return (uint8_t)(_state->CpuIrqVector >> 8); } 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);
} }
} }
} }