diff --git a/Cartridge.cpp b/Cartridge.cpp index 574aaf8..51b4c44 100644 --- a/Cartridge.cpp +++ b/Cartridge.cpp @@ -54,7 +54,7 @@ bool Cartridge::TryLoad( const char* romFile ) bool Cartridge::TryLoadHeader() { - static constexpr ui64 ROM_CONSTANT_HEADER = 0x4E45531A; + static constexpr u64 ROM_CONSTANT_HEADER = 0x4E45531A; if ( rom == nullptr ) { @@ -67,7 +67,7 @@ bool Cartridge::TryLoadHeader() return false; } - ui64 constant = 0; + u64 constant = 0; for ( byte i = 0x00; i <= 0x03; ++i ) { constant <<= 8; @@ -79,8 +79,8 @@ bool Cartridge::TryLoadHeader() return false; } - header.prgRomSizeKB = static_cast( rom[ 0x04 ] ) * 16; - header.chrRomSizeKB = static_cast( rom[ 0x05 ] ) * 8; + header.prgRomSizeKB = static_cast< u32 >( rom[ 0x04 ] ) * 16; + header.chrRomSizeKB = static_cast< u32 >( rom[ 0x05 ] ) * 8; /* Flags 6 */ header.mirroringType = MirroringType( rom[ 0x06 ] & 0b0000'0001 ); @@ -108,7 +108,17 @@ void Cartridge::PrintDetails() const << "Contains PRG RAM: " << header.hasPRGRam << "\n" << "Contains 512B trainer: " << header.has512BTrainer << "\n" << "Ignores Mirroring: " << header.ignoreMirroring << "\n" - << "Mapper: " << static_cast< ui32 >( header.mapper ); + << "Mapper: " << static_cast< u32 >( header.mapper ); std::cout << std::endl; } + +const Cartridge::Header& Cartridge::GetHeader() const +{ + return header; +} + +const byte* const Cartridge::GetRom() const +{ + return rom; +} \ No newline at end of file diff --git a/Cartridge.h b/Cartridge.h index dc31067..78e76e5 100644 --- a/Cartridge.h +++ b/Cartridge.h @@ -25,8 +25,8 @@ class Cartridge struct Header { - ui32 prgRomSizeKB; - ui32 chrRomSizeKB; + u32 prgRomSizeKB; + u32 chrRomSizeKB; Cartridge::MirroringType mirroringType; bool hasPersistentMemory; bool hasPRGRam; @@ -53,10 +53,12 @@ class Cartridge void PrintDetails() const; bool IsLoaded() const; + const Header& GetHeader() const; + const byte * const GetRom() const; private: - ui32 cartridgeSize; + u32 cartridgeSize; const char* romFileName; byte* rom; bool isLoaded; diff --git a/Cpu.cpp b/Cpu.cpp index c748118..d5495d8 100644 --- a/Cpu.cpp +++ b/Cpu.cpp @@ -2,8 +2,33 @@ #include "Cpu.h" +#include "Memory.h" + +Cpu::Cpu( Memory *memory ) + : memory( memory ) +{ + Reset(); +} + +void Cpu::Reset() +{ + /* Load the reset vector into the PC register */ + PC.low = memory->Read( 0xFFFC ); + PC.hi = memory->Read( 0xFFFD ); + + /* Power up state of registers */ + stackPointer = 0xFD; + pRegister = 0x34; + accumulator = 0x00; + xRegisterIndex = 0x00; + yRegisterIndex = 0x00; +} + word Cpu::Update() { + const byte opcode = GetNextOpcode(); + const byte instruction = ( ( ( opcode & 0b1110'0000 ) >> 3 ) | ( opcode & 0b0000'0011 ) ); + const byte addressingMode = ( opcode & 0b0001'1100 ) >> 2; return 0; } @@ -28,3 +53,7 @@ word Cpu::GetAbsoluteStackAddress() const return 0x0100 + stackPointer; } +byte Cpu::GetNextOpcode() const +{ + return memory->Read( PC.value ); +} \ No newline at end of file diff --git a/Cpu.h b/Cpu.h index f14c775..1499094 100644 --- a/Cpu.h +++ b/Cpu.h @@ -2,6 +2,9 @@ #include "Types.h" + +class Memory; + class Cpu { public: @@ -20,7 +23,9 @@ class Cpu }; - Cpu() = default; + Cpu( Memory *memory ); + + void Reset(); word Update(); @@ -38,8 +43,12 @@ class Cpu byte xRegisterIndex; byte yRegisterIndex; + /* Systems */ + Memory *memory; /* Stack operations */ word GetAbsoluteStackAddress() const; + /* Opcode handling */ + byte GetNextOpcode() const; }; \ No newline at end of file diff --git a/Memory.cpp b/Memory.cpp new file mode 100644 index 0000000..148ec7e --- /dev/null +++ b/Memory.cpp @@ -0,0 +1,48 @@ +#pragma once + +#include "Memory.h" + +#include +#include "Cartridge.h" + + +Memory::Memory( Cartridge *cartridge ) +{ + map = new byte[ 0x10000 ]; + memset( map, 0, 0x10000 ); + + MapCartridge( cartridge ); +} + +Memory::~Memory() +{ + delete map; +} + +byte Memory::Read( word address ) const +{ + return map[ address ]; +} + +void Memory::Write( word address, byte data ) +{ + map[ address ] = data; +} + +void Memory::MapCartridge( Cartridge *cartridge ) +{ + 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 ); + +} diff --git a/Memory.h b/Memory.h new file mode 100644 index 0000000..d16321f --- /dev/null +++ b/Memory.h @@ -0,0 +1,38 @@ +#pragma once + +#include "Types.h" + + +/* + * MEMORY MAP + * + * 0x0000 - 0x07FF ( 2KB internal RAM ) + * 0x0800 - 0x0FFF ( Mirrors of RAM ) + * 0x1000 - 0x17FF ( Mirrors of RAM ) + * 0x1800 - 0x1FFF ( Mirrors of RAM ) + * 0x2000 - 0x2007 ( NES PPU registers ) + * 0x2008 - 0x3FFF ( Mirrors of PPU registers, repeat every 8 bytes ) + * 0x4000 - 0x4017 ( NES APU & IO registers ) + * 0x4018 - 0x401F ( APU and UI Functionality that is usually disabled ) + * 0x4020 - 0xFFFF ( Cartridge and mapper registers ) + */ + + +class Cartridge; + +class Memory +{ +public: + + Memory( Cartridge *cartridge ); + ~Memory(); + + byte Read( word address ) const; + void Write( word address, byte data ); + +private: + + byte *map; + + void MapCartridge( Cartridge *cartridge ); +}; \ No newline at end of file diff --git a/Types.h b/Types.h index ce3af92..f3a9f30 100644 --- a/Types.h +++ b/Types.h @@ -3,10 +3,10 @@ using byte = unsigned char; using word = unsigned short; -using ui64 = unsigned long long; +using u64 = unsigned long long; using i64 = long long; -using ui32 = unsigned int; +using u32 = unsigned int; using i32 = int; union Register @@ -18,3 +18,14 @@ union Register }; word value; }; + + +namespace +{ + +u64 operator"" _KB( u64 size ) +{ + return size * 1024; +} + +} \ No newline at end of file diff --git a/main.cpp b/main.cpp index c3bc9e0..1e2b376 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,8 @@ #include #include "Cartridge.h" +#include "Memory.h" +#include "Cpu.h" int main(int argc, char** argv) { @@ -13,6 +15,9 @@ int main(int argc, char** argv) Cartridge cartridge( argv[1] ); if ( cartridge.IsLoaded() ) { + Memory memory( &cartridge ); + Cpu cpu( &memory ); + cpu.Update(); cartridge.PrintDetails(); return 0; }