diff options
| author | Hannes Schulze <haschu0103@outlook.de> | 2025-01-18 19:35:42 +0100 |
|---|---|---|
| committer | Hannes Schulze <haschu0103@outlook.de> | 2025-01-18 19:35:42 +0100 |
| commit | 67672d06776e38b06f31f6599678767c60eed58a (patch) | |
| tree | 4846c762815b887036b10a7aadd849dd8fdd4420 /src/nes/ppu.hh | |
| parent | fe7243fdd14f6ef57033f9e70141aba970dba7ea (diff) | |
implement ppu io registers
Diffstat (limited to 'src/nes/ppu.hh')
| -rw-r--r-- | src/nes/ppu.hh | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/nes/ppu.hh b/src/nes/ppu.hh index 8f116c7..1d08614 100644 --- a/src/nes/ppu.hh +++ b/src/nes/ppu.hh @@ -4,17 +4,129 @@ namespace nes { + class address; class cpu; class mapper; + class rgb; class ppu { static constexpr auto vram_size = std::size_t{ 0x800 }; + static constexpr auto oam_size = std::size_t{ 0x100 }; + static constexpr auto palette_buffer_size = std::size_t{ 0x20 }; + static constexpr auto status_mask = std::uint8_t{ 0b11100000 }; + // Writes to some registers are ignored until this clock cycle. + static constexpr auto boot_up_cycles = cycle_count::from_ppu(29658); + + enum class vram_increment + { + add_1_across = 0, + add_32_down = 1, + }; + + enum class sprite_size + { + _8x8 = 0, + _8x16 = 1, + }; + + enum class role + { + background = 0, + sprite = 1, + }; + + enum class color : std::uint8_t + { + }; + + union color_index + { + struct + { + unsigned color : 2; + unsigned palette : 2; + role role : 1; + }; + unsigned value; + + explicit color_index(unsigned const value) + : value{ value } + { + } + }; cycle_count current_cycles_; cpu& cpu_; mapper& mapper_; std::uint8_t vram_[vram_size]{}; + std::uint8_t oam_[oam_size]{}; + color palette_buffer_[palette_buffer_size] + { + color{ 0x09 }, color{ 0x01 }, color{ 0x00 }, color{ 0x01 }, + color{ 0x00 }, color{ 0x02 }, color{ 0x02 }, color{ 0x0D }, + color{ 0x08 }, color{ 0x10 }, color{ 0x08 }, color{ 0x24 }, + color{ 0x00 }, color{ 0x00 }, color{ 0x04 }, color{ 0x2C }, + color{ 0x09 }, color{ 0x01 }, color{ 0x34 }, color{ 0x03 }, + color{ 0x00 }, color{ 0x04 }, color{ 0x00 }, color{ 0x14 }, + color{ 0x08 }, color{ 0x3A }, color{ 0x00 }, color{ 0x02 }, + color{ 0x00 }, color{ 0x20 }, color{ 0x2C }, color{ 0x08 }, + }; + std::uint8_t latch_{}; // The last read/written IO register value, returned when reading write-only registers. + union + { + struct + { + bool : 1; + bool : 1; + bool : 1; + bool : 1; + bool : 1; + bool sprite_overflow : 1; + bool sprite_0_hit : 1; + bool vblank : 1; + }; + std::uint8_t value{ 0b00000000 }; + } status_{}; + union + { + struct + { + std::uint8_t base_name_table : 2; // Base nametable address. + vram_increment vram_increment : 1; // VRAM increment per CPU read/write of PPUDATA. + std::uint8_t sprite_pattern_table : 1; // Sprite pattern table address for 8x8 sprites. + std::uint8_t background_pattern_table : 1; // Background pattern table address. + sprite_size sprite_size : 1; // Sprite size. + bool enable_ext_pin : 1; // PPU master/slave select. + bool vblank_nmi : 1; // Enable/disable Vblank NMI + }; + std::uint8_t value{ 0b00000000 }; + } control_{}; + union + { + struct + { + bool grayscale : 1; // Enable/disable grayscale. + bool show_background_start : 1; // Show background in leftmost 8 pixels of screen. + bool show_sprites_start : 1; // Show sprites in leftmost 8 pixels of screen. + bool enable_background : 1; // Enable background rendering. + bool enable_sprites : 1; // Enable sprite rendering. + bool emphasize_red : 1; // Emphasize red. + bool emphasize_green : 1; // Emphasize green. + bool emphasize_blue : 1; // Emphasize blue. + }; + std::uint8_t value{ 0b00000000 }; + } mask_{}; + struct + { + // See https://www.nesdev.org/wiki/PPU_scrolling#PPU_internal_registers + std::uint16_t v{}; // Current VRAM address (15 bits) + std::uint16_t t{}; // Temporary VRAM address (15 bits) + std::uint8_t x{}; // Fine X scroll (3 bits) + bool w{}; // Second write toggle (1 bit) + } internal_{}; + std::uint8_t oamaddr_{}; // Address accessed by IO registers + std::uint8_t ppudata_read_buffer_{}; // Delays PPUDATA reads by one. public: explicit ppu(cpu& cpu, mapper& mapper); @@ -25,5 +137,36 @@ namespace nes auto operator=(ppu&&) -> ppu& = delete; auto step_to(cycle_count) -> void; + + // Memory access + + auto read8(address) -> std::uint8_t; + auto write8(address, std::uint8_t) -> void; + + // IO registers + + auto read_latch() -> std::uint8_t; + auto read_ppustatus() -> std::uint8_t; + auto read_oamdata() -> std::uint8_t; + auto read_ppudata() -> std::uint8_t; + + auto write_latch(std::uint8_t) -> void; + auto write_ppuctrl(std::uint8_t) -> void; + auto write_ppuscroll(std::uint8_t) -> void; + auto write_ppumask(std::uint8_t) -> void; + auto write_ppuaddr(std::uint8_t) -> void; + auto write_ppudata(std::uint8_t) -> void; + auto write_oamaddr(std::uint8_t) -> void; + auto write_oamdata(std::uint8_t) -> void; + auto write_oamdma(std::uint8_t) -> void; + + private: + auto step() -> void; + + // Helpers + + auto increment_vram() -> void; + auto get_color(color_index) -> color&; + auto resolve_color(color) -> rgb; }; } // namespace nes
\ No newline at end of file |
