Skip to content

Commit

Permalink
GB: Fixed stack overflow crash when 2 halt instructions are executed …
Browse files Browse the repository at this point in the history
…in a row with halt bug
  • Loading branch information
SourMesen committed Jul 9, 2023
1 parent 3e36c39 commit 4cb89a2
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 14 deletions.
1 change: 1 addition & 0 deletions Core/Gameboy/Debugger/DummyGbCpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ void DummyGbCpu::SetDummyState(GbCpuState& state)
_memOpCounter = 0;
_state = state;
_state.HaltCounter = 0;
_state.HaltBug = false;
}

uint32_t DummyGbCpu::GetOperationCount()
Expand Down
45 changes: 32 additions & 13 deletions Core/Gameboy/GbCpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void GbCpu::Exec()
{
#ifndef DUMMYCPU
uint8_t irqVector = _memoryManager->ProcessIrqRequests();
if(irqVector) {
if(irqVector && !_state.HaltBug) {
if(_state.IME) {
uint16_t oldPc = _state.PC;
IncCycleCount();
Expand Down Expand Up @@ -81,14 +81,17 @@ void GbCpu::Exec()
#endif

if(_state.HaltCounter) {
if(_state.HaltBug) {
ProcessHaltBug();
} else {
#ifndef DUMMYCPU
_emu->ProcessHaltedCpu<CpuType::Gameboy>();
IncCycleCount();

if(_state.HaltCounter > 1) {
ProcessCgbSpeedSwitch();
}
_emu->ProcessHaltedCpu<CpuType::Gameboy>();
IncCycleCount();
if(_state.HaltCounter > 1) {
ProcessCgbSpeedSwitch();
}
#endif
}
return;
}

Expand All @@ -103,6 +106,25 @@ void GbCpu::Exec()
ExecOpCode(ReadOpCode());
}

void GbCpu::ProcessHaltBug()
{
if(_state.EiPending) {
_state.EiPending = false;
_state.IME = true;
}

#ifndef DUMMYCPU
_emu->ProcessInstruction<CpuType::Gameboy>();
#endif

//HALT bug, execution continues, but PC isn't incremented for the first byte
uint8_t opCode = ReadOpCode();
_state.PC--;
_state.HaltCounter = 0;
_state.HaltBug = false;
ExecOpCode(opCode);
}

void GbCpu::ExecOpCode(uint8_t opCode)
{
switch(opCode) {
Expand Down Expand Up @@ -805,12 +827,8 @@ void GbCpu::HALT()
_state.HaltCounter = 1;
} else {
//HALT bug, execution continues, but PC isn't incremented for the first byte
#ifndef DUMMYCPU
HalfCycle();
uint8_t opCode = ReadMemory<MemoryOperationType::ExecOpCode, GbOamCorruptionType::Read>(_state.PC);
HalfCycle();
ExecOpCode(opCode);
#endif
_state.HaltCounter = 1;
_state.HaltBug = true;
}
}

Expand Down Expand Up @@ -1463,4 +1481,5 @@ void GbCpu::Serialize(Serializer& s)
SV(_state.C); SV(_state.D); SV(_state.E); SV(_state.H); SV(_state.L); SV(_state.IME); SV(_state.HaltCounter);
SV(_state.EiPending);
SV(_state.CycleCount);
SV(_state.HaltBug);
}
3 changes: 2 additions & 1 deletion Core/Gameboy/GbCpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class GbCpu : public ISerializable
void ExecOpCode(uint8_t opCode);

void ProcessCgbSpeedSwitch();
__noinline void ProcessHaltBug();

__forceinline void IncCycleCount();
__forceinline void HalfCycle();
Expand Down Expand Up @@ -166,7 +167,7 @@ class GbCpu : public ISerializable
uint64_t GetCycleCount() { return _state.CycleCount; }

void Exec();

void Serialize(Serializer& s) override;

#ifdef DUMMYCPU
Expand Down
1 change: 1 addition & 0 deletions Core/Gameboy/GbTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct GbCpuState : BaseState

bool EiPending;
bool IME;
bool HaltBug;
};

namespace GbCpuFlags
Expand Down
1 change: 1 addition & 0 deletions UI/Interop/DebugState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ public struct GbCpuState : BaseState

[MarshalAs(UnmanagedType.I1)] public bool EiPending;
[MarshalAs(UnmanagedType.I1)] public bool IME;
[MarshalAs(UnmanagedType.I1)] public bool HaltBug;
}

public enum PpuMode
Expand Down

0 comments on commit 4cb89a2

Please sign in to comment.