summaryrefslogtreecommitdiff
path: root/lib/nes
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nes')
-rw-r--r--lib/nes/cartridge.cc27
-rw-r--r--lib/nes/cartridge.hh28
-rw-r--r--lib/nes/mapper.cc2
-rw-r--r--lib/nes/ppu.cc11
-rw-r--r--lib/nes/ppu.hh37
5 files changed, 61 insertions, 44 deletions
diff --git a/lib/nes/cartridge.cc b/lib/nes/cartridge.cc
index 6a60741..bd8e7d3 100644
--- a/lib/nes/cartridge.cc
+++ b/lib/nes/cartridge.cc
@@ -17,41 +17,32 @@ namespace nes
auto res = cartridge{ status::success };
// Parse header.
- if (length < 16) { return cartridge{ status::error_invalid_ines_data }; }
- if (bytes[0] != 'N' || bytes[1] != 'E' || bytes[2] != 'S' || bytes[3] != 0x1A)
+ if (length < header_length) { return cartridge{ status::error_invalid_ines_data }; }
+ auto const h = header{ bytes };
+ if (h.get_magic_0() != 'N' || h.get_magic_1() != 'E' || h.get_magic_2() != 'S' || h.get_magic_3() != 0x1A)
{
return cartridge{ status::error_invalid_ines_data };
}
- auto const prg_rom_banks = bytes[4];
- auto const chr_rom_banks = bytes[5];
- auto const control_1 = bytes[6];
- auto const control_2 = bytes[7];
- auto const ram_banks = (bytes[8] != 0) ? bytes[8] : 1u;
- auto const has_trainer = (control_1 & 0b00000100) != 0;
- auto const mapper_number = static_cast<std::uint8_t>(
- (control_1 & 0b11110000) >> 4 |
- (control_2 & 0b11110000) >> 0);
+ auto const mapper_number = static_cast<std::uint8_t>((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0));
res.mapper_ = &mapper::get(mapper_number);
- res.name_table_arrangement_ = (control_1 & 0b00000001) != 0
- ? name_table_arrangement::vertical
- : name_table_arrangement::horizontal;
+ res.name_table_arrangement_ = h.get_name_table_arrangement();
// Load program data.
auto offset = std::size_t{ 16 };
- if (has_trainer) { offset += 512; }
+ if (h.get_has_trainer()) { offset += 512; }
- auto const prg_rom_size = prg_rom_banks * prg_rom_bank_size;
+ auto const prg_rom_size = h.get_prg_rom_banks() * prg_rom_bank_size;
if (length < offset + prg_rom_size) { return cartridge{ status::error_invalid_ines_data }; }
res.prg_rom_ = std::vector(&bytes[offset], &bytes[offset + prg_rom_size]);
offset += prg_rom_size;
- auto const chr_rom_size = chr_rom_banks * chr_rom_bank_size;
+ auto const chr_rom_size = h.get_chr_rom_banks() * chr_rom_bank_size;
if (length < offset + chr_rom_size) { return cartridge{ status::error_invalid_ines_data }; }
res.chr_rom_ = std::vector(&bytes[offset], &bytes[offset + chr_rom_size]);
- res.ram_ = std::vector(ram_banks * ram_bank_size, std::uint8_t{ 0 });
+ res.ram_ = std::vector(std::max(h.get_ram_banks(), 1u) * ram_bank_size, std::uint8_t{ 0 });
if (auto const status = res.get_mapper().validate(res); status != status::success)
{
diff --git a/lib/nes/cartridge.hh b/lib/nes/cartridge.hh
index 13c3594..fb75946 100644
--- a/lib/nes/cartridge.hh
+++ b/lib/nes/cartridge.hh
@@ -19,6 +19,34 @@ namespace nes
static constexpr auto prg_rom_bank_size = std::size_t{ 16 * 1024 };
static constexpr auto chr_rom_bank_size = std::size_t{ 8 * 1024 };
static constexpr auto ram_bank_size = std::size_t{ 8 * 1024 };
+ static constexpr auto header_length = std::size_t{ 16 };
+
+ struct header
+ {
+ auto get_magic_0() const -> std::uint8_t { return value[0]; }
+ auto get_magic_1() const -> std::uint8_t { return value[1]; }
+ auto get_magic_2() const -> std::uint8_t { return value[2]; }
+ auto get_magic_3() const -> std::uint8_t { return value[3]; }
+ auto get_prg_rom_banks() const -> unsigned { return value[4]; }
+ auto get_chr_rom_banks() const -> unsigned { return value[5]; }
+ auto get_control_1() const -> std::uint8_t { return value[6]; }
+ auto get_control_2() const -> std::uint8_t { return value[7]; }
+ auto get_ram_banks() const -> unsigned { return value[8]; }
+ auto get_has_trainer() const -> bool { return get_control_1() & 0b00000100; }
+ auto get_mapper_low() const -> unsigned { return (get_control_1() & 0b11110000) >> 4; }
+ auto get_mapper_high() const -> unsigned { return (get_control_2() & 0b11110000) >> 0; }
+ auto get_name_table_arrangement() const -> name_table_arrangement { return static_cast<name_table_arrangement>((get_control_1() & 0b00000001) >> 0); }
+
+ std::uint8_t value[header_length]{};
+
+ explicit header(std::uint8_t const* v)
+ {
+ for (auto i = std::size_t{ 0 }; i < header_length; ++i)
+ {
+ value[i] = v[i];
+ }
+ }
+ };
status status_{ status::error_uninitialized };
std::vector<std::uint8_t> prg_rom_;
diff --git a/lib/nes/mapper.cc b/lib/nes/mapper.cc
index 40d11f8..08af1ae 100644
--- a/lib/nes/mapper.cc
+++ b/lib/nes/mapper.cc
@@ -145,7 +145,7 @@ namespace nes
} // namespace
// -----------------------------------------------------------------------------------------------------------------
- // Selection
+ // Instances
// -----------------------------------------------------------------------------------------------------------------
auto mapper::invalid() -> mapper&
diff --git a/lib/nes/ppu.cc b/lib/nes/ppu.cc
index 7ac2155..815224f 100644
--- a/lib/nes/ppu.cc
+++ b/lib/nes/ppu.cc
@@ -239,14 +239,14 @@ namespace nes
sprite_count_ = 0;
for (auto i = unsigned{ 0 }; i < sprite_max_count; ++i)
{
- auto const s = get_sprite(i);
- auto const row = static_cast<int>(scanline_) - static_cast<int>(s.y);
+ auto const s = sprite{ &oam_[i * 4] };
+ auto const row = static_cast<int>(scanline_) - static_cast<int>(s.get_y());
if (row < 0 || static_cast<unsigned>(row) >= height) { continue; }
if (sprite_count_ < 8)
{
sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast<unsigned>(row));
- sprites_[sprite_count_].x = s.x;
+ sprites_[sprite_count_].x = s.get_x();
sprites_[sprite_count_].is_in_front = !s.get_behind_background();
sprites_[sprite_count_].is_sprite_zero = i == 0;
sprite_count_ += 1;
@@ -587,11 +587,6 @@ namespace nes
return tile_size;
}
- auto ppu::get_sprite(unsigned const i) const -> sprite
- {
- return sprite{ oam_[i * 4 + 0], oam_[i * 4 + 1], oam_[i * 4 + 2], oam_[i * 4 + 3] };
- }
-
auto ppu::get_tile_bitplane(
pattern_table const pattern_table, tile const tile, unsigned const row, bitplane const bitplane) -> std::uint8_t
{
diff --git a/lib/nes/ppu.hh b/lib/nes/ppu.hh
index 9fc5e39..afc295c 100644
--- a/lib/nes/ppu.hh
+++ b/lib/nes/ppu.hh
@@ -67,28 +67,32 @@ namespace nes
struct sprite
{
// Tile index (and pattern table) for sprites
- BITFIELD_ENUM(large_pattern_table, pattern_table, tile_index, 0b00000001, 0)
- BITFIELD_ENUM(large_top_tile, tile, tile_index, 0b11111110, 1)
- BITFIELD_ENUM(small_tile, tile, tile_index, 0b11111111, 0)
+ BITFIELD_ENUM(large_pattern_table, pattern_table, value[1], 0b00000001, 0)
+ BITFIELD_ENUM(large_top_tile, tile, value[1], 0b11111110, 1)
+ BITFIELD_ENUM(small_tile, tile, value[1], 0b11111111, 0)
// Attributes
- BITFIELD_ENUM(palette, palette, attributes, 0b00000011, 0)
- BITFIELD_FLAG(behind_background, attributes, 0b00100000, 5)
- BITFIELD_FLAG(flip_horizontal, attributes, 0b01000000, 6)
- BITFIELD_FLAG(flip_vertical, attributes, 0b10000000, 7)
+ BITFIELD_ENUM(palette, palette, value[2], 0b00000011, 0)
+ BITFIELD_FLAG(behind_background, value[2], 0b00100000, 5)
+ BITFIELD_FLAG(flip_horizontal, value[2], 0b01000000, 6)
+ BITFIELD_FLAG(flip_vertical, value[2], 0b10000000, 7)
- std::uint8_t y{};
- std::uint8_t tile_index{};
- std::uint8_t attributes{};
- std::uint8_t x{};
+ auto get_y() const -> std::uint8_t { return value[0]; }
+ auto get_tile_index() const -> std::uint8_t { return value[1]; }
+ auto get_attributes() const -> std::uint8_t { return value[2]; }
+ auto get_x() const -> std::uint8_t { return value[3]; }
+
+ auto set_y(std::uint8_t const v) -> void { value[0] = v; }
+ auto set_tile_index(std::uint8_t const v) -> void { value[1] = v; }
+ auto set_attributes(std::uint8_t const v) -> void { value[2] = v; }
+ auto set_x(std::uint8_t const v) -> void { value[3] = v; }
+
+ std::uint8_t value[4]{};
explicit sprite() = default;
- explicit sprite(std::uint8_t const y, std::uint8_t const tile_index, std::uint8_t const attributes, std::uint8_t const x)
- : y{ y }
- , tile_index{ tile_index }
- , attributes{ attributes }
- , x{ x }
+ explicit sprite(std::uint8_t const* data)
+ : value{ data[0], data[1], data[2], data[3] }
{
}
};
@@ -267,7 +271,6 @@ namespace nes
auto copy_x() -> void;
auto copy_y() -> void;
auto get_sprite_height() const -> unsigned;
- auto get_sprite(unsigned i) const -> sprite;
auto get_tile_bitplane(pattern_table, tile, unsigned row, bitplane) -> std::uint8_t;
auto get_tile_row(palette, std::uint8_t bitplane_0, std::uint8_t bitplane_1) const -> tile_row;
auto ref_color(color_index) -> color&;