PPU: Implement basic sprite time/range over flags, forced vblank flag

+ Stub for IO port registers
This commit is contained in:
Sour 2019-02-19 18:01:27 -05:00
parent 06a9babfd7
commit b5fe44a037
4 changed files with 55 additions and 4 deletions

View file

@ -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;
}
}

View file

@ -25,6 +25,8 @@ private:
uint16_t _horizontalTimer = 0x1FF;
uint16_t _verticalTimer = 0x1FF;
uint8_t _ioPortOutput = 0;
uint16_t _controllerData[4];
public:

View file

@ -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<true>();
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<bool forMainScreen>
@ -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;
}
}

View file

@ -27,6 +27,9 @@ private:
shared_ptr<Console> _console;
shared_ptr<InternalRegisters> _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;