From b5fe44a0379a025829cc28ef18bd5b32cbcac081 Mon Sep 17 00:00:00 2001 From: Sour Date: Tue, 19 Feb 2019 18:01:27 -0500 Subject: [PATCH] PPU: Implement basic sprite time/range over flags, forced vblank flag + Stub for IO port registers --- Core/InternalRegisters.cpp | 11 ++++++++++- Core/InternalRegisters.h | 2 ++ Core/Ppu.cpp | 40 +++++++++++++++++++++++++++++++++++--- Core/Ppu.h | 6 ++++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/Core/InternalRegisters.cpp b/Core/InternalRegisters.cpp index 7dad669..918a01a 100644 --- a/Core/InternalRegisters.cpp +++ b/Core/InternalRegisters.cpp @@ -73,6 +73,10 @@ uint8_t InternalRegisters::Read(uint16_t addr) ); } + case 0x4213: + //TODO RDIO - Programmable I/O port (in-port) + return 0; + case 0x4214: return (uint8_t)_divResult; case 0x4215: return (uint8_t)(_divResult >> 8); @@ -102,6 +106,11 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value) _enableAutoJoypadRead = (value & 0x01) != 0; break; + case 0x4201: + //TODO WRIO - Programmable I/O port (out-port) + _ioPortOutput = value; + break; + case 0x4202: _multOperand1 = value; break; case 0x4203: _multOperand2 = value; @@ -129,7 +138,7 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value) case 0x420A: _verticalTimer = (_verticalTimer & 0xFF) | ((value & 0x01) << 8); break; default: - MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr)); + MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value)); break; } } diff --git a/Core/InternalRegisters.h b/Core/InternalRegisters.h index 534266d..da2ff44 100644 --- a/Core/InternalRegisters.h +++ b/Core/InternalRegisters.h @@ -25,6 +25,8 @@ private: uint16_t _horizontalTimer = 0x1FF; uint16_t _verticalTimer = 0x1FF; + uint8_t _ioPortOutput = 0; + uint16_t _controllerData[4]; public: diff --git a/Core/Ppu.cpp b/Core/Ppu.cpp index 7eb52d8..62fbe49 100644 --- a/Core/Ppu.cpp +++ b/Core/Ppu.cpp @@ -63,6 +63,9 @@ void Ppu::Exec() if(_cycle == 340) { _cycle = -1; _scanline++; + + _rangeOver = false; + _timeOver = false; if(_scanline < 224) { RenderScanline(); } else if(_scanline == 225) { @@ -151,6 +154,11 @@ void Ppu::RenderScanline() memset(_filled, 0, sizeof(_filled)); memset(_subScreenFilled, 0, sizeof(_subScreenFilled)); + if(_forcedVblank) { + RenderBgColor(); + return; + } + switch(_bgMode) { case 0: DrawSprites<3, true>(); @@ -248,6 +256,8 @@ void Ppu::RenderScanline() memset(_spritePriority, 0xFF, sizeof(_spritePriority)); memset(_spritePixels, 0xFFFF, sizeof(_spritePixels)); _spriteCount = 0; + uint16_t totalWidth = 0; + for(int i = 0; i < 512; i += 4) { uint8_t y = _oamRam[i + 1]; @@ -322,13 +332,20 @@ void Ppu::RenderScanline() } } - _spriteCount++; + totalWidth += width; + if(totalWidth >= 34 * 8) { + _timeOver = true; + } + _spriteCount++; if(_spriteCount == 32) { + _rangeOver = true; + } + + if(_timeOver || _rangeOver) { break; } } - } template @@ -466,6 +483,14 @@ uint8_t* Ppu::GetSpriteRam() uint8_t Ppu::Read(uint16_t addr) { switch(addr) { + case 0x213E: + //TODO open bus on bit 4 + return ( + (_timeOver ? 0x80 : 0) | + (_rangeOver ? 0x40 : 0) | + 0x01 //PPU chip version + ); + default: MessageManager::DisplayMessage("Debug", "Unimplemented register read: " + HexUtilities::ToHex(addr)); break; @@ -477,6 +502,15 @@ uint8_t Ppu::Read(uint16_t addr) void Ppu::Write(uint32_t addr, uint8_t value) { switch(addr) { + case 0x2100: + _forcedVblank = (value & 0x80) != 0; + + //TODO Apply brightness + _screenBrightness = value & 0x0F; + + //TODO : Also, writing this register on the first line of V-Blank (225 or 240, depending on overscan) when force blank is currently active causes the OAM Address Reset to occur. + break; + case 0x2101: _oamMode = (value & 0xE0) >> 5; _oamBaseAddress = (value & 0x07) << 13; @@ -622,7 +656,7 @@ void Ppu::Write(uint32_t addr, uint8_t value) break; default: - MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr)); + MessageManager::DisplayMessage("Debug", "Unimplemented register write: " + HexUtilities::ToHex(addr) + " = " + HexUtilities::ToHex(value)); break; } } diff --git a/Core/Ppu.h b/Core/Ppu.h index d105c83..68e017a 100644 --- a/Core/Ppu.h +++ b/Core/Ppu.h @@ -27,6 +27,9 @@ private: shared_ptr _console; shared_ptr _regs; + bool _forcedVblank = false; + uint8_t _screenBrightness = 0; + uint16_t _cycle = 0; uint16_t _scanline = 0; uint32_t _frameCount = 0; @@ -65,6 +68,9 @@ private: uint16_t _internalOamAddress = 0; uint8_t _oamWriteBuffer = 0; + bool _timeOver = false; + bool _rangeOver = false; + bool _directColorMode = false; uint8_t _colorMathClipMode = 0;