PPU: Implemented VRAM/CGRAM reads + H/V offset data latches

+ Implemented work ram read register
This commit is contained in:
Sour 2019-02-21 07:27:47 -05:00
parent 6e32ebfffd
commit 68e7617c95
5 changed files with 96 additions and 3 deletions

View file

@ -43,6 +43,11 @@ void InternalRegisters::ProcessAutoJoypadRead()
}
}
uint8_t InternalRegisters::GetIoPortOutput()
{
return _ioPortOutput;
}
void InternalRegisters::SetNmiFlag(bool nmiFlag)
{
_nmiFlag = nmiFlag;
@ -53,7 +58,11 @@ uint8_t InternalRegisters::Read(uint16_t addr)
switch(addr) {
case 0x4210: {
//open bus implementation here is needed to pass CPUPHL test
uint8_t value = (_nmiFlag ? 0x80 : 0) | ((addr >> 8) & 0x70);
uint8_t value =
(_nmiFlag ? 0x80 : 0) |
((addr >> 8) & 0x70) |
0x2; //CPU revision
_nmiFlag = false;
return value;
}
@ -106,8 +115,11 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value)
_enableAutoJoypadRead = (value & 0x01) != 0;
break;
case 0x4201:
case 0x4201:
//TODO WRIO - Programmable I/O port (out-port)
if((_ioPortOutput & 0x80) && !(value & 0x80)) {
_console->GetPpu()->LatchLocationValues();
}
_ioPortOutput = value;
break;

View file

@ -33,6 +33,7 @@ public:
InternalRegisters(shared_ptr<Console> console);
void ProcessAutoJoypadRead();
uint8_t GetIoPortOutput();
void SetNmiFlag(bool nmiFlag);
bool IsVerticalIrqEnabled() { return _enableVerticalIrq; }

View file

@ -41,6 +41,8 @@ public:
addr &= 0xFFFF;
if(addr >= 0x2140 && addr <= 0x217F) {
return _spc->Read(addr & 0x03);
} else if(addr == 0x2180) {
return _workRam[_wramPosition++];
} else if(addr == 0x4016 || addr == 0x4017) {
return _controlManager->Read(addr);
} else if(addr < 0x4200) {

View file

@ -520,10 +520,23 @@ uint8_t* Ppu::GetSpriteRam()
return _oamRam;
}
void Ppu::LatchLocationValues()
{
_horizontalLocation = _cycle;
_verticalLocation = _scanline;
}
uint8_t Ppu::Read(uint16_t addr)
{
switch(addr) {
case 0x2137:
//SLHV - Software Latch for H/V Counter
//Latch values on read, and return open bus
LatchLocationValues();
break;
case 0x2138: {
//OAMDATAREAD - Data for OAM read
uint8_t value;
if(_internalOamAddress < 512) {
value = _oamRam[_internalOamAddress];
@ -534,8 +547,61 @@ uint8_t Ppu::Read(uint16_t addr)
return value;
}
case 0x2139: {
//VMDATALREAD - VRAM Data Read low byte
uint8_t returnValue = _vramReadBuffer;
_vramReadBuffer = _vram[_vramAddress << 1];
if(!_vramAddrIncrementOnSecondReg) {
_vramAddress = (_vramAddress + _vramIncrementValue) & 0x7FFF;
}
return returnValue;
}
case 0x213A: {
//VMDATAHREAD - VRAM Data Read high byte
uint8_t returnValue = _vramReadBuffer;
_vramReadBuffer = _vram[(_vramAddress << 1) + 1];
if(_vramAddrIncrementOnSecondReg) {
_vramAddress = (_vramAddress + _vramIncrementValue) & 0x7FFF;
}
return returnValue;
}
case 0x213B:{
//CGDATAREAD - CGRAM Data read
uint8_t value = _cgram[_cgramAddress];
_cgramAddress = (_cgramAddress + 1) & (Ppu::CgRamSize - 1);
return value;
}
case 0x213C:
//OPHCT - Horizontal Scanline Location
if(_horizontalLocToggle) {
//"Note that the value read is only 9 bits: bits 1-7 of the high byte are PPU2 Open Bus."
return ((_horizontalLocation & 0x100) >> 8) | ((addr >> 8) & 0xFE);
} else {
return _horizontalLocation & 0xFF;
}
break;
case 0x213D:
//OPVCT - Vertical Scanline Location
if(_verticalLocationToggle) {
//"Note that the value read is only 9 bits: bits 1-7 of the high byte are PPU2 Open Bus."
return ((_verticalLocation & 0x100) >> 8) | ((addr >> 8) & 0xFE);
} else {
return _verticalLocation & 0xFF;
}
break;
case 0x213E:
//TODO open bus on bit 4
//"The high/low selector is reset to <20>elow<6F>f when $213f is read"
_horizontalLocToggle = false;
_verticalLocationToggle = false;
return (
(_timeOver ? 0x80 : 0) |
(_rangeOver ? 0x40 : 0) |
@ -547,7 +613,7 @@ uint8_t Ppu::Read(uint16_t addr)
break;
}
return 0;
return addr >> 8;
}
void Ppu::Write(uint32_t addr, uint8_t value)
@ -654,7 +720,10 @@ void Ppu::Write(uint32_t addr, uint8_t value)
case 2:
case 3: _vramIncrementValue = 128; break;
}
//TODO : Remapping is not implemented yet
_vramAddressRemapping = (value & 0x0C) >> 2;
_vramAddrIncrementOnSecondReg = (value & 0x80) != 0;
break;

View file

@ -60,6 +60,7 @@ private:
uint8_t _vramIncrementValue;
uint8_t _vramAddressRemapping;
bool _vramAddrIncrementOnSecondReg;
uint8_t _vramReadBuffer = 0;
uint16_t _cgramAddress;
uint8_t _cgram[Ppu::CgRamSize];
@ -110,6 +111,12 @@ private:
uint8_t _hvScrollLatchValue = 0;
uint8_t _hScrollLatchValue = 0;
uint16_t _horizontalLocation = 0;
bool _horizontalLocToggle = false;
uint16_t _verticalLocation = 0;
bool _verticalLocationToggle = false;
template<bool forMainScreen>
void RenderBgColor();
@ -136,6 +143,8 @@ public:
uint8_t* GetCgRam();
uint8_t* GetSpriteRam();
void LatchLocationValues();
uint8_t Read(uint16_t addr);
void Write(uint32_t addr, uint8_t value);
};