From b207b87cf6e66395d4e9ffe6562b464ed9aa3480 Mon Sep 17 00:00:00 2001 From: Jonathan Maldonado Contreras Date: Wed, 16 Oct 2019 22:22:37 +0100 Subject: [PATCH] Implement address latch and ppu data/address registers --- Memory.cpp | 85 +++++++++++++++++++++++++++++++++++++++++------------- Memory.h | 8 +++-- Video.cpp | 16 ++-------- Video.h | 4 +-- main.cpp | 4 +-- 5 files changed, 76 insertions(+), 41 deletions(-) diff --git a/Memory.cpp b/Memory.cpp index 7b424d2..2f8871f 100644 --- a/Memory.cpp +++ b/Memory.cpp @@ -7,8 +7,9 @@ #include "Video.h" -Memory::Memory( const Cartridge *cartridge ) +Memory::Memory( const Cartridge *cartridge, Video *video ) : cartridge( cartridge ) + , video ( video ) { map = new byte[ 64_KB ]; Reset(); @@ -24,14 +25,47 @@ void Memory::Reset() memset( map, 0x00, 64_KB ); MapCartridge(); + + map[ Video::PPUCTRL_REGISTER, 0x00 ]; + map[ Video::PPUMASK_REGISTER, 0x00 ]; + map[ Video::PPUSTATUS_REGISTER, 0b1010'0000 ]; + map[ Video::OAMA_REGISTER, 0x00 ]; + map[ Video::OAMADATA_REGISTER, 0x00 ]; + map[ Video::PPUSCROLL_REGISTER, 0x00 ]; + map[ Video::PPUDATA_ADDRESS, 0x00 ]; +} + +void Memory::MapCartridge() +{ + assert( cartridge != nullptr ); + + /* For now only support NROM with PRG ROM of 16KB and no ram */ + Cartridge::Header header = cartridge->GetHeader(); + assert( header.mapper == 0x00 && header.prgRomSizeKB == 16 && !header.hasPRGRam); + + const byte * const rom = cartridge->GetRom(); + + /* Map the PRG ROM to 0x8000 */ + memcpy(&map[0x8000], &rom[0x0010], 16_KB ); + + /* Mirror the PRG ROM in 0xC000 */ + memcpy(&map[0xC000], &rom[0x0010], 16_KB ); } -byte Memory::Read( word address ) const +byte Memory::Read( word address ) { if ( address >= 0x2000 && address <= 0x3FFF ) { - const word mirroredAddress = ( address % 8 ) + 0x2000; - return map[ mirroredAddress ]; + const word ppuRegister = ( address % 8 ) + 0x2000; + + if ( ppuRegister == Video::PPUSTATUS_REGISTER ) + { + ResetAddressLatch(); + const byte ppuStatus = map[ Video::PPUSTATUS_REGISTER ]; + byte newPpuStatus = ppuStatus ^ 0b1000'0000; + Write( Video::PPUSTATUS_REGISTER, newPpuStatus ); + } + return map[ ppuRegister ]; } else { @@ -43,8 +77,30 @@ void Memory::Write( word address, byte data ) { if ( address >= 0x2000 && address <= 0x3FFF ) { - const word mirroredAddress = ( address % 8 ) + 0x2000; - map[ mirroredAddress ] = data; + const word ppuRegister = ( address % 8 ) + 0x2000; + if ( ppuRegister == Video::PPUDATA_ADDRESS ) + { + const word address = map[ Video::PPUADDR_REGISTER ]; + + if ( IsAddressLatchClear ) + { + IsAddressLatchClear = false; + currentVRamAddress = ( data | currentVRamAddress ) << 8; + } + else + { + currentVRamAddress = data | currentVRamAddress; + } + map[ Video::PPUDATA_ADDRESS ] = data; + + const byte ppuControlRegister = map[ Video::PPUCTRL_REGISTER ]; + const byte incrementAmount = ( ppuControlRegister | 0b0000'0100 ) >> 2; + map[ Video::PPUADDR_REGISTER ] = incrementAmount; + } + else + { + map[ ppuRegister ] = data; + } } else { @@ -57,19 +113,8 @@ const byte *const Memory::GetMemoryMap() const return map; } -void Memory::MapCartridge() +void Memory::ResetAddressLatch() { - assert( cartridge != nullptr ); - - /* For now only support NROM with PRG ROM of 16KB and no ram */ - Cartridge::Header header = cartridge->GetHeader(); - assert( header.mapper == 0x00 && header.prgRomSizeKB == 16 && !header.hasPRGRam); - - const byte * const rom = cartridge->GetRom(); - - /* Map the PRG ROM to 0x8000 */ - memcpy(&map[0x8000], &rom[0x0010], 16_KB ); - - /* Mirror the PRG ROM in 0xC000 */ - memcpy(&map[0xC000], &rom[0x0010], 16_KB ); + IsAddressLatchClear = true; + currentVRamAddress = 0x00; } diff --git a/Memory.h b/Memory.h index 5c020cb..5221143 100644 --- a/Memory.h +++ b/Memory.h @@ -41,13 +41,13 @@ class Memory { public: - Memory( const Cartridge *cartridge ); + Memory( const Cartridge *cartridge, Video *video ); ~Memory(); void Reset(); /* Memory management */ - byte Read( word address ) const; + byte Read( word address ); void Write( word address, byte data ); const byte *const GetMemoryMap() const; @@ -56,10 +56,14 @@ class Memory /* Associated NES systems */ const Cartridge *cartridge; + Video *video; /* NES memory map */ byte *map; + bool IsAddressLatchClear; + word currentVRamAddress; void MapCartridge(); + void ResetAddressLatch(); }; \ No newline at end of file diff --git a/Video.cpp b/Video.cpp index 4cad3b1..be8a486 100644 --- a/Video.cpp +++ b/Video.cpp @@ -4,12 +4,10 @@ #include #include "Cartridge.h" -#include "Memory.h" -Video::Video( Cartridge *cartridge, Memory *cpuMemory ) +Video::Video( Cartridge *cartridge ) : cartridge( cartridge ) - , cpuMemory( cpuMemory ) { memory = new byte[ 16_KB ]; frameBuffer = new RGB[ NES_VIDEO_RESOLUTION ]; @@ -35,14 +33,6 @@ void Video::Reset() MapCartridgeCHRToPPU(); - cpuMemory->Write( PPUCTRL_REGISTER, 0x00 ); - cpuMemory->Write( PPUMASK_REGISTER, 0x00 ); - cpuMemory->Write( PPUSTATUS_REGISTER, 0b1010'0000 ); - cpuMemory->Write( OAMA_REGISTER, 0x00 ); - cpuMemory->Write( OAMADATA_REGISTER, 0x00 ); - cpuMemory->Write( PPUSCROLL_REGISTER, 0x00 ); - cpuMemory->Write( PPUADDR_REGISTER, 0x00 ); - cpuMemory->Write( PPUDATA_ADDRESS, 0x00 ); } void Video::MapCartridgeCHRToPPU() @@ -55,8 +45,6 @@ void Video::MapCartridgeCHRToPPU() const u32 offset = (header.prgRomSizeKB * 1_KB) + 0x0010; const u32 dataSize = header.chrRomSizeKB * 1_KB; memcpy( memory, &cartridgeRom[ offset ], dataSize ); - - memory[ PPUSTATUS_REGISTER ] = 0b1010'0000; } RGB* Video::GetFrameBuffer() const @@ -81,5 +69,5 @@ void Video::Write( word address, byte data ) void Video::Update( u32 cycles ) { - + // We do nothing here for now } diff --git a/Video.h b/Video.h index 9a2b2ae..5b01a25 100644 --- a/Video.h +++ b/Video.h @@ -43,7 +43,6 @@ class Cartridge; -class Memory; class Video { @@ -62,7 +61,7 @@ class Video static constexpr word PPUDATA_ADDRESS = 0x2007; - Video( Cartridge *cartridge, Memory *cpuMemory ); + Video( Cartridge *cartridge ); ~Video(); void Reset(); @@ -80,7 +79,6 @@ class Video private: /* Associated Systems */ Cartridge *cartridge; - Memory *cpuMemory; /* PPU memory layout */ byte *memory; diff --git a/main.cpp b/main.cpp index 2047917..1e7462b 100644 --- a/main.cpp +++ b/main.cpp @@ -28,8 +28,8 @@ int main(int argc, char** argv) cartridge.PrintDetails(); - Memory memory( &cartridge ); - Video video( &cartridge, &memory ); + Video video( &cartridge ); + Memory memory( &cartridge, &video ); Cpu cpu( &memory ); Debugger debugger( &cpu, &memory, &video );