GB: Pause OAM DMA when CPU is halted + return $FF during sprite evaluation while OAM DMA is active
Both of these together make the naughtyemu test display a blank screen as expected
This commit is contained in:
parent
43b43a6397
commit
8d43594d7c
6 changed files with 28 additions and 11 deletions
|
@ -118,12 +118,13 @@ void Gameboy::PowerOn()
|
|||
_apu.reset(new GbApu(_console, this));
|
||||
_memoryManager.reset(new GbMemoryManager());
|
||||
_timer.reset(new GbTimer(_memoryManager.get(), _apu.get()));
|
||||
_dmaController.reset(new GbDmaController(_memoryManager.get(), _ppu.get()));
|
||||
_dmaController.reset(new GbDmaController());
|
||||
_cart->Init(this, _memoryManager.get());
|
||||
_memoryManager->Init(_console, this, _cart.get(), _ppu.get(), _apu.get(), _timer.get(), _dmaController.get());
|
||||
|
||||
_cpu.reset(new GbCpu(_console, this, _memoryManager.get()));
|
||||
_ppu->Init(_console, this, _memoryManager.get(), _dmaController.get(), _videoRam, _spriteRam);
|
||||
_dmaController->Init(_memoryManager.get(), _ppu.get(), _cpu.get());
|
||||
}
|
||||
|
||||
void Gameboy::Exec()
|
||||
|
|
|
@ -39,6 +39,11 @@ GbCpuState GbCpu::GetState()
|
|||
return _state;
|
||||
}
|
||||
|
||||
bool GbCpu::IsHalted()
|
||||
{
|
||||
return _state.Halted;
|
||||
}
|
||||
|
||||
void GbCpu::Exec()
|
||||
{
|
||||
uint8_t irqVector = _memoryManager->ProcessIrqRequests();
|
||||
|
|
16
Core/GbCpu.h
16
Core/GbCpu.h
|
@ -20,13 +20,6 @@ private:
|
|||
Console* _console;
|
||||
Gameboy* _gameboy;
|
||||
|
||||
public:
|
||||
GbCpu(Console* console, Gameboy* gameboy, GbMemoryManager* memoryManager);
|
||||
virtual ~GbCpu();
|
||||
|
||||
GbCpuState GetState();
|
||||
|
||||
void Exec();
|
||||
void ExecOpCode(uint8_t opCode);
|
||||
|
||||
__forceinline void IncCycleCount();
|
||||
|
@ -146,5 +139,14 @@ public:
|
|||
void DI();
|
||||
void PREFIX();
|
||||
|
||||
public:
|
||||
GbCpu(Console* console, Gameboy* gameboy, GbMemoryManager* memoryManager);
|
||||
virtual ~GbCpu();
|
||||
|
||||
GbCpuState GetState();
|
||||
bool IsHalted();
|
||||
|
||||
void Exec();
|
||||
|
||||
void Serialize(Serializer& s) override;
|
||||
};
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
#include "GbDmaController.h"
|
||||
#include "GbMemoryManager.h"
|
||||
#include "GbPpu.h"
|
||||
#include "GbCpu.h"
|
||||
|
||||
GbDmaController::GbDmaController(GbMemoryManager* memoryManager, GbPpu* ppu)
|
||||
void GbDmaController::Init(GbMemoryManager* memoryManager, GbPpu* ppu, GbCpu* cpu)
|
||||
{
|
||||
_memoryManager = memoryManager;
|
||||
_ppu = ppu;
|
||||
_cpu = cpu;
|
||||
_state = {};
|
||||
}
|
||||
|
||||
|
@ -17,6 +19,11 @@ GbDmaControllerState GbDmaController::GetState()
|
|||
|
||||
void GbDmaController::Exec()
|
||||
{
|
||||
if(_cpu->IsHalted()) {
|
||||
//OAM DMA is halted while the CPU is in halt mode, and resumes when the CPU resumes
|
||||
return;
|
||||
}
|
||||
|
||||
if(_state.DmaCounter > 0) {
|
||||
if(_state.DmaCounter <= 160) {
|
||||
_memoryManager->WriteDma(0xFE00 + (160 - _state.DmaCounter), _state.DmaReadBuffer);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
class GbMemoryManager;
|
||||
class GbPpu;
|
||||
class GbCpu;
|
||||
|
||||
class GbDmaController final : public ISerializable
|
||||
{
|
||||
|
@ -12,11 +13,12 @@ private:
|
|||
GbDmaControllerState _state;
|
||||
GbMemoryManager* _memoryManager;
|
||||
GbPpu* _ppu;
|
||||
GbCpu* _cpu;
|
||||
|
||||
void ProcessDmaBlock();
|
||||
|
||||
public:
|
||||
GbDmaController(GbMemoryManager* memoryManager, GbPpu* ppu);
|
||||
void Init(GbMemoryManager* memoryManager, GbPpu* ppu, GbCpu* cpu);
|
||||
|
||||
GbDmaControllerState GetState();
|
||||
|
||||
|
|
|
@ -400,7 +400,7 @@ void GbPpu::RunSpriteEvaluation()
|
|||
if(_state.Cycle & 0x01) {
|
||||
if(_spriteCount < 10) {
|
||||
uint8_t spriteIndex = ((_state.Cycle - 4) >> 1) * 4;
|
||||
int16_t sprY = (int16_t)_oam[spriteIndex] - 16;
|
||||
int16_t sprY = _dmaController->IsOamDmaRunning() ? 0xFF : ((int16_t)_oam[spriteIndex] - 16);
|
||||
if(_state.Scanline >= sprY && _state.Scanline < sprY + (_state.LargeSprites ? 16 : 8)) {
|
||||
_spriteX[_spriteCount] = _oam[spriteIndex + 1];
|
||||
_spriteIndexes[_spriteCount] = spriteIndex;
|
||||
|
|
Loading…
Add table
Reference in a new issue