summaryrefslogtreecommitdiff
path: root/lib/nes/ppu.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nes/ppu.cc')
-rw-r--r--lib/nes/ppu.cc99
1 files changed, 39 insertions, 60 deletions
diff --git a/lib/nes/ppu.cc b/lib/nes/ppu.cc
index 0f56c96..7e3428c 100644
--- a/lib/nes/ppu.cc
+++ b/lib/nes/ppu.cc
@@ -27,7 +27,7 @@ namespace nes
// See https://www.nesdev.org/wiki/PPU_rendering
// Based on: https://github.com/fogleman/nes/blob/master/nes/ppu.go
- auto const enable_rendering = mask_.enable_background || mask_.enable_sprites;
+ auto const enable_rendering = mask_.get_enable_background() || mask_.get_enable_sprites();
current_cycles_ += cycle_count::from_ppu(1);
scanline_cycle_ += 1;
@@ -130,14 +130,14 @@ namespace nes
if (scanline_ == 241 && scanline_cycle_ == 1)
{
display_.switch_buffers();
- status_.vblank = true;
- if (control_.vblank_nmi) { cpu_.trigger_nmi(); }
+ status_.set_vblank(true);
+ if (control_.get_vblank_nmi()) { cpu_.trigger_nmi(); }
}
if (pre_line && scanline_cycle_ == 1)
{
- status_.vblank = false;
- status_.sprite_zero_hit = false;
- status_.sprite_overflow = false;
+ status_.set_vblank(false);
+ status_.set_sprite_zero_hit(false);
+ status_.set_sprite_overflow(false);
}
}
@@ -147,16 +147,16 @@ namespace nes
auto const y = scanline_;
auto background_color = color_index{ 0 };
- if (mask_.enable_background)
+ if (mask_.get_enable_background())
{
auto const tile_data = static_cast<std::uint32_t>(tile_data_ >> 32);
background_color = color_index{ static_cast<std::uint8_t>((tile_data >> ((7 - internal_.x) * 4)) & 0xF) };
- background_color.role = role::background;
+ background_color.set_role(role::background);
}
auto foreground = sprite{};
auto foreground_color = color_index{ 0 };
- if (mask_.enable_sprites)
+ if (mask_.get_enable_sprites())
{
for (auto i = unsigned{ 0 }; i < sprite_count_; ++i)
{
@@ -164,20 +164,20 @@ namespace nes
auto const offset = static_cast<int>(x) - static_cast<int>(s.position);
if (offset < 0 || offset > 7) { continue; }
auto const color = color_index{ static_cast<std::uint8_t>((s.pattern >> ((7 - offset) * 4)) & 0xF) };
- if (color.color == 0) { continue; }
+ if (color.get_color() == 0) { continue; }
foreground = s;
foreground_color = color;
- foreground_color.role = role::sprite;
+ foreground_color.set_role(role::sprite);
break;
}
}
- auto has_background = background_color.color != 0;
- auto has_foreground = foreground_color.color != 0;
+ auto has_background = background_color.get_color() != 0;
+ auto has_foreground = foreground_color.get_color() != 0;
- if (x < 8 && !mask_.show_background_start) { has_background = false; }
- if (x < 8 && !mask_.show_sprites_start) { has_foreground = false; }
+ if (x < 8 && !mask_.get_show_background_start()) { has_background = false; }
+ if (x < 8 && !mask_.get_show_sprites_start()) { has_foreground = false; }
auto color = color_index{ 0 };
if (!has_background && has_foreground)
@@ -192,7 +192,7 @@ namespace nes
{
if (foreground.is_sprite_zero && x < 255)
{
- status_.sprite_zero_hit = true;
+ status_.set_sprite_zero_hit(true);
}
color = foreground.is_in_front ? foreground_color : background_color;
@@ -217,8 +217,8 @@ namespace nes
auto ppu::fetch_low_tile_byte() -> void
{
- auto const fine_y = (internal_.v >> 12) & 7;
- auto const table = control_.background_pattern_table;
+ auto const fine_y = (internal_.v >> 12) & 7u;
+ auto const table = control_.get_background_pattern_table();
auto const tile = name_table_byte_;
auto const addr = static_cast<std::uint16_t>(0x1000 * table + 16 * tile + fine_y);
low_tile_byte_ = read8(address{ addr });
@@ -226,8 +226,8 @@ namespace nes
auto ppu::fetch_high_tile_byte() -> void
{
- auto const fine_y = (internal_.v >> 12) & 7;
- auto const table = control_.background_pattern_table;
+ auto const fine_y = (internal_.v >> 12) & 7u;
+ auto const table = control_.get_background_pattern_table();
auto const tile = name_table_byte_;
auto const addr = static_cast<std::uint16_t>(0x1000 * table + 16 * tile + fine_y);
high_tile_byte_ = read8(address{ addr } + 8);
@@ -340,7 +340,7 @@ namespace nes
}
else
{
- status_.sprite_overflow = true;
+ status_.set_sprite_overflow(true);
break;
}
}
@@ -353,26 +353,21 @@ namespace nes
auto const flip_vertical = (attributes & 0x80) == 0x80;
if (flip_vertical) { row = sprite_height() - 1 - row; }
auto addr = address{};
- switch (control_.sprite_size)
+ if (control_.get_large_sprites())
{
- case sprite_size::_8x8:
+ auto const table = tile & 1u;
+ tile &= 0xFE;
+ if (row > 7)
{
- auto const table = control_.sprite_pattern_table;
- addr = address{ static_cast<std::uint16_t>(0x1000u * table + 16u * tile + row) };
- break;
- }
- case sprite_size::_8x16:
- {
- auto const table = tile & 1u;
- tile &= 0xFE;
- if (row > 7)
- {
- tile += 1;
- row -= 8;
- }
- addr = address{ static_cast<std::uint16_t>(0x1000u * table + 16u * tile + row) };
- break;
+ tile += 1;
+ row -= 8;
}
+ addr = address{ static_cast<std::uint16_t>(0x1000u * table + 16u * tile + row) };
+ }
+ else
+ {
+ auto const table = control_.get_sprite_pattern_table();
+ addr = address{ static_cast<std::uint16_t>(0x1000u * table + 16u * tile + row) };
}
auto const a = (attributes & 3u) << 2;
@@ -461,7 +456,7 @@ namespace nes
auto const res = static_cast<std::uint8_t>(base | (status_.value & status_mask));
NES_DEBUG_LOG(ppu, "PPUSTATUS -> {:#2x}", res);
- status_.vblank = false;
+ status_.set_vblank(false);
internal_.w = false;
write_latch(res);
@@ -514,7 +509,7 @@ namespace nes
NES_DEBUG_LOG(ppu, "PPUCTRL <- {:#2x}", value);
control_.value = value;
internal_.t = static_cast<std::uint16_t>((internal_.t & 0xF3FF) | ((value & 0x03) << 10));
- if (control_.vblank_nmi && status_.vblank) { cpu_.trigger_nmi(); }
+ if (control_.get_vblank_nmi() && status_.get_vblank()) { cpu_.trigger_nmi(); }
}
}
@@ -617,38 +612,22 @@ namespace nes
auto ppu::sprite_height() -> unsigned
{
- switch (control_.sprite_size)
- {
- case sprite_size::_8x8:
- return 8;
- case sprite_size::_8x16:
- return 16;
- }
-
- return 8;
+ return control_.get_large_sprites() ? 16 : 8;
}
auto ppu::increment_vram() -> void
{
- switch (control_.vram_increment)
- {
- case vram_increment::add_1_across:
- internal_.v += 1;
- break;
- case vram_increment::add_32_down:
- internal_.v += 32;
- break;
- }
+ internal_.v += control_.get_vram_row_increment() ? 32 : 1;
}
auto ppu::get_color(color_index index) -> color&
{
// See https://www.nesdev.org/wiki/PPU_palettes
index.value = index.value % 0x20;
- if (index.color == 0)
+ if (index.get_color() == 0)
{
// The first color is mirrored between background and foreground palettes.
- index.role = role::background;
+ index.set_role(role::background);
}
return palette_buffer_[index.value];
}