PPU: Implemented VRAM/CGRAM reads + H/V offset data latches
+ Implemented work ram read register
This commit is contained in:
parent
6e32ebfffd
commit
68e7617c95
5 changed files with 96 additions and 3 deletions
|
@ -43,6 +43,11 @@ void InternalRegisters::ProcessAutoJoypadRead()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t InternalRegisters::GetIoPortOutput()
|
||||||
|
{
|
||||||
|
return _ioPortOutput;
|
||||||
|
}
|
||||||
|
|
||||||
void InternalRegisters::SetNmiFlag(bool nmiFlag)
|
void InternalRegisters::SetNmiFlag(bool nmiFlag)
|
||||||
{
|
{
|
||||||
_nmiFlag = nmiFlag;
|
_nmiFlag = nmiFlag;
|
||||||
|
@ -53,7 +58,11 @@ uint8_t InternalRegisters::Read(uint16_t addr)
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x4210: {
|
case 0x4210: {
|
||||||
//open bus implementation here is needed to pass CPUPHL test
|
//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;
|
_nmiFlag = false;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -106,8 +115,11 @@ void InternalRegisters::Write(uint16_t addr, uint8_t value)
|
||||||
_enableAutoJoypadRead = (value & 0x01) != 0;
|
_enableAutoJoypadRead = (value & 0x01) != 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x4201:
|
case 0x4201:
|
||||||
//TODO WRIO - Programmable I/O port (out-port)
|
//TODO WRIO - Programmable I/O port (out-port)
|
||||||
|
if((_ioPortOutput & 0x80) && !(value & 0x80)) {
|
||||||
|
_console->GetPpu()->LatchLocationValues();
|
||||||
|
}
|
||||||
_ioPortOutput = value;
|
_ioPortOutput = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ public:
|
||||||
InternalRegisters(shared_ptr<Console> console);
|
InternalRegisters(shared_ptr<Console> console);
|
||||||
|
|
||||||
void ProcessAutoJoypadRead();
|
void ProcessAutoJoypadRead();
|
||||||
|
uint8_t GetIoPortOutput();
|
||||||
void SetNmiFlag(bool nmiFlag);
|
void SetNmiFlag(bool nmiFlag);
|
||||||
|
|
||||||
bool IsVerticalIrqEnabled() { return _enableVerticalIrq; }
|
bool IsVerticalIrqEnabled() { return _enableVerticalIrq; }
|
||||||
|
|
|
@ -41,6 +41,8 @@ public:
|
||||||
addr &= 0xFFFF;
|
addr &= 0xFFFF;
|
||||||
if(addr >= 0x2140 && addr <= 0x217F) {
|
if(addr >= 0x2140 && addr <= 0x217F) {
|
||||||
return _spc->Read(addr & 0x03);
|
return _spc->Read(addr & 0x03);
|
||||||
|
} else if(addr == 0x2180) {
|
||||||
|
return _workRam[_wramPosition++];
|
||||||
} else if(addr == 0x4016 || addr == 0x4017) {
|
} else if(addr == 0x4016 || addr == 0x4017) {
|
||||||
return _controlManager->Read(addr);
|
return _controlManager->Read(addr);
|
||||||
} else if(addr < 0x4200) {
|
} else if(addr < 0x4200) {
|
||||||
|
|
71
Core/Ppu.cpp
71
Core/Ppu.cpp
|
@ -520,10 +520,23 @@ uint8_t* Ppu::GetSpriteRam()
|
||||||
return _oamRam;
|
return _oamRam;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ppu::LatchLocationValues()
|
||||||
|
{
|
||||||
|
_horizontalLocation = _cycle;
|
||||||
|
_verticalLocation = _scanline;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t Ppu::Read(uint16_t addr)
|
uint8_t Ppu::Read(uint16_t addr)
|
||||||
{
|
{
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
|
case 0x2137:
|
||||||
|
//SLHV - Software Latch for H/V Counter
|
||||||
|
//Latch values on read, and return open bus
|
||||||
|
LatchLocationValues();
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x2138: {
|
case 0x2138: {
|
||||||
|
//OAMDATAREAD - Data for OAM read
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
if(_internalOamAddress < 512) {
|
if(_internalOamAddress < 512) {
|
||||||
value = _oamRam[_internalOamAddress];
|
value = _oamRam[_internalOamAddress];
|
||||||
|
@ -534,8 +547,61 @@ uint8_t Ppu::Read(uint16_t addr)
|
||||||
return value;
|
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:
|
case 0x213E:
|
||||||
//TODO open bus on bit 4
|
//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 (
|
return (
|
||||||
(_timeOver ? 0x80 : 0) |
|
(_timeOver ? 0x80 : 0) |
|
||||||
(_rangeOver ? 0x40 : 0) |
|
(_rangeOver ? 0x40 : 0) |
|
||||||
|
@ -547,7 +613,7 @@ uint8_t Ppu::Read(uint16_t addr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return addr >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ppu::Write(uint32_t addr, uint8_t value)
|
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 2:
|
||||||
case 3: _vramIncrementValue = 128; break;
|
case 3: _vramIncrementValue = 128; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO : Remapping is not implemented yet
|
||||||
_vramAddressRemapping = (value & 0x0C) >> 2;
|
_vramAddressRemapping = (value & 0x0C) >> 2;
|
||||||
|
|
||||||
_vramAddrIncrementOnSecondReg = (value & 0x80) != 0;
|
_vramAddrIncrementOnSecondReg = (value & 0x80) != 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ private:
|
||||||
uint8_t _vramIncrementValue;
|
uint8_t _vramIncrementValue;
|
||||||
uint8_t _vramAddressRemapping;
|
uint8_t _vramAddressRemapping;
|
||||||
bool _vramAddrIncrementOnSecondReg;
|
bool _vramAddrIncrementOnSecondReg;
|
||||||
|
uint8_t _vramReadBuffer = 0;
|
||||||
|
|
||||||
uint16_t _cgramAddress;
|
uint16_t _cgramAddress;
|
||||||
uint8_t _cgram[Ppu::CgRamSize];
|
uint8_t _cgram[Ppu::CgRamSize];
|
||||||
|
@ -110,6 +111,12 @@ private:
|
||||||
uint8_t _hvScrollLatchValue = 0;
|
uint8_t _hvScrollLatchValue = 0;
|
||||||
uint8_t _hScrollLatchValue = 0;
|
uint8_t _hScrollLatchValue = 0;
|
||||||
|
|
||||||
|
uint16_t _horizontalLocation = 0;
|
||||||
|
bool _horizontalLocToggle = false;
|
||||||
|
|
||||||
|
uint16_t _verticalLocation = 0;
|
||||||
|
bool _verticalLocationToggle = false;
|
||||||
|
|
||||||
template<bool forMainScreen>
|
template<bool forMainScreen>
|
||||||
void RenderBgColor();
|
void RenderBgColor();
|
||||||
|
|
||||||
|
@ -136,6 +143,8 @@ public:
|
||||||
uint8_t* GetCgRam();
|
uint8_t* GetCgRam();
|
||||||
uint8_t* GetSpriteRam();
|
uint8_t* GetSpriteRam();
|
||||||
|
|
||||||
|
void LatchLocationValues();
|
||||||
|
|
||||||
uint8_t Read(uint16_t addr);
|
uint8_t Read(uint16_t addr);
|
||||||
void Write(uint32_t addr, uint8_t value);
|
void Write(uint32_t addr, uint8_t value);
|
||||||
};
|
};
|
Loading…
Add table
Reference in a new issue