diff --git a/Core/InternalRegisters.cpp b/Core/InternalRegisters.cpp index 918a01a..6d795eb 100644 --- a/Core/InternalRegisters.cpp +++ b/Core/InternalRegisters.cpp @@ -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; diff --git a/Core/InternalRegisters.h b/Core/InternalRegisters.h index da2ff44..7ad169d 100644 --- a/Core/InternalRegisters.h +++ b/Core/InternalRegisters.h @@ -33,6 +33,7 @@ public: InternalRegisters(shared_ptr console); void ProcessAutoJoypadRead(); + uint8_t GetIoPortOutput(); void SetNmiFlag(bool nmiFlag); bool IsVerticalIrqEnabled() { return _enableVerticalIrq; } diff --git a/Core/MemoryManager.h b/Core/MemoryManager.h index 3bb9f78..b17cf63 100644 --- a/Core/MemoryManager.h +++ b/Core/MemoryManager.h @@ -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) { diff --git a/Core/Ppu.cpp b/Core/Ppu.cpp index f482dc7..bfadc34 100644 --- a/Core/Ppu.cpp +++ b/Core/Ppu.cpp @@ -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 elow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; diff --git a/Core/Ppu.h b/Core/Ppu.h index a710348..4cda177 100644 --- a/Core/Ppu.h +++ b/Core/Ppu.h @@ -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 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); }; \ No newline at end of file