PPU: Implement basic sprite time/range over flags, forced vblank flag
+ Stub for IO port registers
This commit is contained in:
parent
06a9babfd7
commit
b5fe44a037
4 changed files with 55 additions and 4 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ private:
|
|||
uint16_t _horizontalTimer = 0x1FF;
|
||||
uint16_t _verticalTimer = 0x1FF;
|
||||
|
||||
uint8_t _ioPortOutput = 0;
|
||||
|
||||
uint16_t _controllerData[4];
|
||||
|
||||
public:
|
||||
|
|
40
Core/Ppu.cpp
40
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<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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue