summaryrefslogtreecommitdiff
path: root/lib/nes
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nes')
-rw-r--r--lib/nes/app/application.hh5
-rw-r--r--lib/nes/app/graphics/color.hh4
-rw-r--r--lib/nes/app/graphics/image-view.hh14
-rw-r--r--lib/nes/app/graphics/mask-tile.hh4
-rw-r--r--lib/nes/app/graphics/renderer.cc24
-rw-r--r--lib/nes/app/graphics/renderer.hh24
-rw-r--r--lib/nes/app/input/input-manager.cc4
-rw-r--r--lib/nes/app/input/input-manager.hh3
-rw-r--r--lib/nes/common/CMakeLists.txt1
-rw-r--r--lib/nes/common/box.hh4
-rw-r--r--lib/nes/common/display.hh9
-rw-r--r--lib/nes/common/rgb.hh12
-rw-r--r--lib/nes/common/types.hh26
-rw-r--r--lib/nes/sys/cartridge.cc32
-rw-r--r--lib/nes/sys/cartridge.hh66
-rw-r--r--lib/nes/sys/controller.cc6
-rw-r--r--lib/nes/sys/controller.hh7
-rw-r--r--lib/nes/sys/cpu.cc88
-rw-r--r--lib/nes/sys/cpu.hh71
-rw-r--r--lib/nes/sys/mapper.cc20
-rw-r--r--lib/nes/sys/mapper.hh11
-rw-r--r--lib/nes/sys/nes.cc4
-rw-r--r--lib/nes/sys/nes.hh3
-rw-r--r--lib/nes/sys/ppu.cc70
-rw-r--r--lib/nes/sys/ppu.hh135
-rw-r--r--lib/nes/sys/types/address.hh36
-rw-r--r--lib/nes/sys/types/button-mask.hh10
-rw-r--r--lib/nes/sys/types/cycle-count.hh33
-rw-r--r--lib/nes/sys/types/snapshot.hh22
29 files changed, 398 insertions, 350 deletions
diff --git a/lib/nes/app/application.hh b/lib/nes/app/application.hh
index 1fc1c6b..91ab35f 100644
--- a/lib/nes/app/application.hh
+++ b/lib/nes/app/application.hh
@@ -5,6 +5,7 @@
#include "nes/sys/nes.hh"
#include "nes/common/box.hh"
#include "nes/common/display.hh"
+#include "nes/common/types.hh"
#include <chrono>
namespace nes::app
@@ -32,8 +33,8 @@ namespace nes::app
{
}
- auto get(unsigned const x, unsigned const y) const -> rgb override { return base.get(x, y); }
- auto set(unsigned const x, unsigned const y, rgb const value) -> void override { base.set(x, y, value); }
+ auto get(u32 const x, u32 const y) const -> rgb override { return base.get(x, y); }
+ auto set(u32 const x, u32 const y, rgb const value) -> void override { base.set(x, y, value); }
auto switch_buffers() -> void override;
};
diff --git a/lib/nes/app/graphics/color.hh b/lib/nes/app/graphics/color.hh
index 572ac25..ae9a1c2 100644
--- a/lib/nes/app/graphics/color.hh
+++ b/lib/nes/app/graphics/color.hh
@@ -1,11 +1,11 @@
#pragma once
-#include <cstdint>
+#include "nes/common/types.hh"
namespace nes::app
{
/// One of the predefined colors in the color palette used for the UI.
- enum class color : std::uint8_t
+ enum class color : u8
{
transparent, ///< No color.
background_primary, ///< The primary background color.
diff --git a/lib/nes/app/graphics/image-view.hh b/lib/nes/app/graphics/image-view.hh
index a9b8e94..cde4989 100644
--- a/lib/nes/app/graphics/image-view.hh
+++ b/lib/nes/app/graphics/image-view.hh
@@ -1,5 +1,7 @@
#pragma once
+#include "nes/common/types.hh"
+
namespace nes::app
{
struct image_tile;
@@ -10,13 +12,13 @@ namespace nes::app
class image_view
{
image_tile const* data_{ nullptr };
- unsigned width_{ 0 };
- unsigned height_{ 0 };
+ u32 width_{ 0 };
+ u32 height_{ 0 };
public:
explicit image_view() = default;
- explicit image_view(image_tile const* data, unsigned const width, unsigned const height)
+ explicit image_view(image_tile const* data, u32 const width, u32 const height)
: data_{ data }
, width_{ width }
, height_{ height }
@@ -24,8 +26,8 @@ namespace nes::app
}
auto get_data() const -> image_tile const* { return data_; }
- auto get_width() const -> unsigned { return width_; }
- auto get_height() const -> unsigned { return height_; }
- auto get(unsigned const x, unsigned const y) const -> image_tile const& { return data_[y * height_ + x]; }
+ auto get_width() const -> u32 { return width_; }
+ auto get_height() const -> u32 { return height_; }
+ auto get(u32 const x, u32 const y) const -> image_tile const& { return data_[y * height_ + x]; }
};
} // namespace nes::app \ No newline at end of file
diff --git a/lib/nes/app/graphics/mask-tile.hh b/lib/nes/app/graphics/mask-tile.hh
index c811003..deb750a 100644
--- a/lib/nes/app/graphics/mask-tile.hh
+++ b/lib/nes/app/graphics/mask-tile.hh
@@ -1,6 +1,6 @@
#pragma once
-#include <cstdint>
+#include "nes/common/types.hh"
namespace nes::app
{
@@ -10,7 +10,7 @@ namespace nes::app
/// integer's row.
struct mask_tile
{
- std::uint8_t data[8]{};
+ u8 data[8]{};
};
namespace tiles
diff --git a/lib/nes/app/graphics/renderer.cc b/lib/nes/app/graphics/renderer.cc
index 8d1a168..1a4dc4d 100644
--- a/lib/nes/app/graphics/renderer.cc
+++ b/lib/nes/app/graphics/renderer.cc
@@ -12,13 +12,13 @@ namespace nes::app
{
}
- auto renderer::render_image_tile(unsigned const x, unsigned const y, image_tile const tile) -> void
+ auto renderer::render_image_tile(u32 const x, u32 const y, image_tile const& tile) -> void
{
if (x >= width || y >= height) { return; }
- for (auto y_px = unsigned{ 0 }; y_px < 8; ++y_px)
+ for (auto y_px = u32{ 0 }; y_px < 8; ++y_px)
{
- for (auto x_px = unsigned{ 0 }; x_px < 8; ++x_px)
+ for (auto x_px = u32{ 0 }; x_px < 8; ++x_px)
{
auto const c = tile.data[y_px * 8 + x_px];
if (c != color::transparent)
@@ -29,16 +29,16 @@ namespace nes::app
}
}
- auto renderer::render_mask_tile(unsigned const x, unsigned const y, mask_tile const tile, color const c) -> void
+ auto renderer::render_mask_tile(u32 const x, u32 const y, mask_tile const tile, color const c) -> void
{
if (c == color::transparent) { return; }
if (x >= width || y >= height) { return; }
auto const resolved = resolve_color(c);
- for (auto y_px = unsigned{ 0 }; y_px < 8; ++y_px)
+ for (auto y_px = u32{ 0 }; y_px < 8; ++y_px)
{
auto row = tile.data[y_px];
- for (auto x_px = unsigned{ 0 }; x_px < 8; ++x_px)
+ for (auto x_px = u32{ 0 }; x_px < 8; ++x_px)
{
if (row & 0b10000000)
{
@@ -49,11 +49,11 @@ namespace nes::app
}
}
- auto renderer::render_image(unsigned const x, unsigned const y, image_view const image) -> void
+ auto renderer::render_image(u32 const x, u32 const y, image_view const image) -> void
{
- for (auto y_img = unsigned{ 0 }; y_img < image.get_height(); ++y_img)
+ for (auto y_img = u32{ 0 }; y_img < image.get_height(); ++y_img)
{
- for (auto x_img = unsigned{ 0 }; x_img < image.get_width(); ++x_img)
+ for (auto x_img = u32{ 0 }; x_img < image.get_width(); ++x_img)
{
render_image_tile(x + x_img, y + y_img, image.get(x, y));
}
@@ -61,7 +61,7 @@ namespace nes::app
}
auto renderer::render_rect(
- unsigned const x, unsigned const y, unsigned const width, unsigned const height, color const c) -> void
+ u32 const x, u32 const y, u32 const width, u32 const height, color const c) -> void
{
if (c == color::transparent) { return; }
if (x >= width || y >= height) { return; }
@@ -69,9 +69,9 @@ namespace nes::app
auto const resolved = resolve_color(c);
auto const x_stop = std::min(x + width, renderer::width);
auto const y_stop = std::min(y + height, renderer::height);
- for (auto y_px = unsigned{ y * 8 }; y_px < y_stop * 8; ++y_px)
+ for (auto y_px = u32{ y * 8 }; y_px < y_stop * 8; ++y_px)
{
- for (auto x_px = unsigned{ x * 8 }; x_px < x_stop * 8; ++x_px)
+ for (auto x_px = u32{ x * 8 }; x_px < x_stop * 8; ++x_px)
{
display_.set(x_px, y_px, resolved);
}
diff --git a/lib/nes/app/graphics/renderer.hh b/lib/nes/app/graphics/renderer.hh
index 7b46461..5de3dcd 100644
--- a/lib/nes/app/graphics/renderer.hh
+++ b/lib/nes/app/graphics/renderer.hh
@@ -1,7 +1,7 @@
#pragma once
+#include "nes/common/types.hh"
#include <string_view>
-#include <cstdint>
namespace nes
{
@@ -14,7 +14,7 @@ namespace nes::app
struct image_tile;
struct mask_tile;
class image_view;
- enum class color : std::uint8_t;
+ enum class color : u8;
/// Renders tiles and other primitive shapes onto a display.
///
@@ -25,8 +25,8 @@ namespace nes::app
display& display_;
public:
- static constexpr auto width = unsigned{ 32 };
- static constexpr auto height = unsigned{ 30 };
+ static constexpr auto width = u32{ 32 };
+ static constexpr auto height = u32{ 30 };
explicit renderer(display&);
@@ -36,23 +36,23 @@ namespace nes::app
auto operator=(renderer&&) -> renderer& = delete;
/// If set, add a drop shadow behind newly drawn opaque elements.
- auto set_shadow(unsigned x_px, unsigned y_px, color) -> void;
+ auto set_shadow(u32 x_px, u32 y_px, color) -> void;
/// If set, add an inner border inside newly drawn opaque elements.
- auto set_border(unsigned px, color) -> void;
+ auto set_border(u32 px, color) -> void;
/// Render a colored tile at the given tile coordinates.
- auto render_image_tile(unsigned x, unsigned y, image_tile) -> void;
+ auto render_image_tile(u32 x, u32 y, image_tile const&) -> void;
/// Render an alpha-only tile at the given tile coordinates with the given color.
- auto render_mask_tile(unsigned x, unsigned y, mask_tile, color) -> void;
+ auto render_mask_tile(u32 x, u32 y, mask_tile, color) -> void;
/// Render an image at the given tile coordinates.
- auto render_image(unsigned x, unsigned y, image_view) -> void;
+ auto render_image(u32 x, u32 y, image_view) -> void;
/// Render a string of text at the given tile coordinates (one tile per character).
- auto render_text(unsigned x, unsigned y, std::string_view, color) -> void;
+ auto render_text(u32 x, u32 y, std::string_view, color) -> void;
/// Render a string of text at the given tile coordinates, limiting its length to the given width and
/// ellipsizing afterward.
- auto render_text(unsigned x, unsigned y, std::string_view, unsigned width, color) -> void;
+ auto render_text(u32 x, u32 y, std::string_view, u32 width, color) -> void;
/// Render a rectangle at the given tile coordinates with a given size (measured in tiles).
- auto render_rect(unsigned x, unsigned y, unsigned width, unsigned height, color) -> void;
+ auto render_rect(u32 x, u32 y, u32 width, u32 height, color) -> void;
/// Completely fill the screen.
auto render_fill(color) -> void;
diff --git a/lib/nes/app/input/input-manager.cc b/lib/nes/app/input/input-manager.cc
index dec899a..8131283 100644
--- a/lib/nes/app/input/input-manager.cc
+++ b/lib/nes/app/input/input-manager.cc
@@ -42,7 +42,7 @@ namespace nes::app
{
// This controller was previously used and assigned an index -> replace the current device with this
// (known) controller.
- auto const i = static_cast<std::size_t>(index);
+ auto const i = static_cast<u32>(index);
if (inputs_[i].controller)
{
inputs_[i].controller->set_index(input_device_controller::index::unused);
@@ -68,7 +68,7 @@ namespace nes::app
auto it = controllers_.begin();
input_device* fallback = keyboard_;
- for (auto i = std::size_t{ 0 }; i < input_count; ++i)
+ for (auto i = u32{ 0 }; i < input_count; ++i)
{
if (inputs_[i].controller != nullptr) { continue; }
diff --git a/lib/nes/app/input/input-manager.hh b/lib/nes/app/input/input-manager.hh
index 525debc..8bc75b8 100644
--- a/lib/nes/app/input/input-manager.hh
+++ b/lib/nes/app/input/input-manager.hh
@@ -3,6 +3,7 @@
#include "nes/app/input/input-device-keyboard.hh"
#include "nes/app/input/input-device-controller.hh"
#include "nes/common/list.hh"
+#include "nes/common/types.hh"
namespace nes::app
{
@@ -12,7 +13,7 @@ namespace nes::app
/// back to the keyboard if needed.
class input_manager
{
- static constexpr auto input_count = std::size_t{ 2 };
+ static constexpr auto input_count = u32{ 2 };
input_device_keyboard* keyboard_;
list<input_device_controller> controllers_;
diff --git a/lib/nes/common/CMakeLists.txt b/lib/nes/common/CMakeLists.txt
index 1a66929..bd83a57 100644
--- a/lib/nes/common/CMakeLists.txt
+++ b/lib/nes/common/CMakeLists.txt
@@ -1,6 +1,7 @@
target_sources(
nes
PRIVATE
+ types.hh
debug.hh
rgb.hh
list.hh
diff --git a/lib/nes/common/box.hh b/lib/nes/common/box.hh
index 442d60f..3a65613 100644
--- a/lib/nes/common/box.hh
+++ b/lib/nes/common/box.hh
@@ -1,5 +1,7 @@
#pragma once
+#include "nes/common/types.hh"
+
namespace nes
{
/// Wrapper around an object, allowing for it to be uninitialized or reassigned even if the object type doesn't
@@ -10,7 +12,7 @@ namespace nes
class box
{
bool initialized_{ false };
- alignas(T) unsigned char buffer_[sizeof(T)];
+ alignas(T) u8 buffer_[sizeof(T)];
public:
/// Create an empty box.
diff --git a/lib/nes/common/display.hh b/lib/nes/common/display.hh
index 85af915..eb35366 100644
--- a/lib/nes/common/display.hh
+++ b/lib/nes/common/display.hh
@@ -1,6 +1,7 @@
#pragma once
#include "nes/common/rgb.hh"
+#include "nes/common/types.hh"
namespace nes
{
@@ -10,8 +11,8 @@ namespace nes
class display
{
public:
- static constexpr auto width = unsigned{ 256 };
- static constexpr auto height = unsigned{ 240 };
+ static constexpr auto width = u32{ 256 };
+ static constexpr auto height = u32{ 240 };
virtual ~display() = default;
@@ -23,9 +24,9 @@ namespace nes
/// Switch between front and back buffers.
virtual auto switch_buffers() -> void = 0;
/// Update the pixel at the given position in the back buffer.
- virtual auto set(unsigned x, unsigned y, rgb value) -> void = 0;
+ virtual auto set(u32 x, u32 y, rgb value) -> void = 0;
/// Load the pixel value at the given position in the back buffer.
- virtual auto get(unsigned x, unsigned y) const -> rgb = 0;
+ virtual auto get(u32 x, u32 y) const -> rgb = 0;
protected:
explicit display() = default;
diff --git a/lib/nes/common/rgb.hh b/lib/nes/common/rgb.hh
index d62c70c..0b8ec1c 100644
--- a/lib/nes/common/rgb.hh
+++ b/lib/nes/common/rgb.hh
@@ -1,6 +1,6 @@
#pragma once
-#include <cstdint>
+#include "nes/common/types.hh"
namespace nes
{
@@ -10,14 +10,14 @@ namespace nes
public:
explicit rgb() = default;
- explicit rgb(std::uint8_t const r, std::uint8_t const g, std::uint8_t const b)
+ explicit rgb(u8 const r, u8 const g, u8 const b)
: r{ r }
, g{ g }
, b{ b }
{
}
- static auto from_hex(std::uint32_t const hex) -> rgb
+ static auto from_hex(u32 const hex) -> rgb
{
auto res = rgb{};
res.r = (hex & 0x00FF0000) >> 16;
@@ -26,8 +26,8 @@ namespace nes
return res;
}
- std::uint8_t r{ 0 };
- std::uint8_t g{ 0 };
- std::uint8_t b{ 0 };
+ u8 r{ 0 };
+ u8 g{ 0 };
+ u8 b{ 0 };
};
} // namespace nes \ No newline at end of file
diff --git a/lib/nes/common/types.hh b/lib/nes/common/types.hh
new file mode 100644
index 0000000..1b768cf
--- /dev/null
+++ b/lib/nes/common/types.hh
@@ -0,0 +1,26 @@
+#pragma once
+
+namespace nes
+{
+ // Some saner type definitions for common integer types.
+
+ using u8 = unsigned char;
+ using u16 = unsigned short;
+ using u32 = unsigned int;
+ using u64 = unsigned long long;
+
+ using i8 = signed char;
+ using i16 = signed short;
+ using i32 = signed int;
+ using i64 = signed long long;
+
+ static_assert(sizeof(u8) == 1);
+ static_assert(sizeof(u16) == 2);
+ static_assert(sizeof(u32) == 4);
+ static_assert(sizeof(u64) == 8);
+
+ static_assert(sizeof(i8) == 1);
+ static_assert(sizeof(i16) == 2);
+ static_assert(sizeof(i32) == 4);
+ static_assert(sizeof(i64) == 8);
+} // namespace nes \ No newline at end of file
diff --git a/lib/nes/sys/cartridge.cc b/lib/nes/sys/cartridge.cc
index 9697185..43f9430 100644
--- a/lib/nes/sys/cartridge.cc
+++ b/lib/nes/sys/cartridge.cc
@@ -1,6 +1,7 @@
#include "nes/sys/cartridge.hh"
#include "nes/sys/types/status.hh"
#include <fstream>
+#include <algorithm>
namespace nes::sys
{
@@ -9,11 +10,11 @@ namespace nes::sys
{
}
- auto cartridge::from_data(void const* data, std::size_t const length) -> cartridge
+ auto cartridge::from_data(void const* data, u32 const length) -> cartridge
{
// See: https://www.nesdev.org/wiki/INES
- auto const bytes = static_cast<std::uint8_t const*>(data);
+ auto const bytes = static_cast<u8 const*>(data);
auto res = cartridge{ status::success };
// Parse header.
@@ -23,26 +24,29 @@ namespace nes::sys
{
return cartridge{ status::error_invalid_ines_data };
}
- auto const mapper_number = static_cast<std::uint8_t>((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0));
+ auto const mapper_number = static_cast<u8>((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0));
res.mapper_ = &mapper::get(mapper_number);
res.name_table_arrangement_ = h.get_name_table_arrangement();
// Load program data.
- auto offset = std::size_t{ 16 };
+ auto offset = u32{ 16 };
if (h.get_has_trainer()) { offset += 512; }
- 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]);
+ res.prg_rom_size_ = h.get_prg_rom_banks() * prg_rom_bank_size;
+ if (length < offset + res.prg_rom_size_) { return cartridge{ status::error_invalid_ines_data }; }
+ if (res.prg_rom_size_ > max_prg_rom_size) { return cartridge{ status::error_invalid_ines_data }; }
+ std::copy_n(&bytes[offset], res.prg_rom_size_, res.prg_rom_);
- offset += prg_rom_size;
+ offset += res.prg_rom_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.chr_rom_size_ = h.get_chr_rom_banks() * chr_rom_bank_size;
+ if (length < offset + res.chr_rom_size_) { return cartridge{ status::error_invalid_ines_data }; }
+ if (res.chr_rom_size_ > max_chr_rom_size) { return cartridge{ status::error_invalid_ines_data }; }
+ std::copy_n(&bytes[offset], res.chr_rom_size_, res.chr_rom_);
- res.ram_ = std::vector(std::max(h.get_ram_banks(), 1u) * ram_bank_size, std::uint8_t{ 0 });
+ res.ram_size_ = std::max(h.get_ram_banks(), 1u) * ram_bank_size;
+ if (res.ram_size_ > max_ram_size) { return cartridge{ status::error_invalid_ines_data }; }
if (auto const status = res.get_mapper().validate(res); status != status::success)
{
@@ -60,9 +64,9 @@ namespace nes::sys
stream.seekg(0, std::ios::end);
auto const length = stream.tellg();
stream.seekg(0, std::ios::beg);
- auto data = std::vector<std::uint8_t>(static_cast<std::size_t>(length));
+ auto data = std::vector<u8>(static_cast<u32>(length));
stream.read(reinterpret_cast<char*>(data.data()), length);
- return from_data(data.data(), data.size());
+ return from_data(data.data(), static_cast<u32>(length));
}
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/cartridge.hh b/lib/nes/sys/cartridge.hh
index d82af84..f8c3c3b 100644
--- a/lib/nes/sys/cartridge.hh
+++ b/lib/nes/sys/cartridge.hh
@@ -2,7 +2,7 @@
#include "nes/sys/types/status.hh"
#include "nes/sys/mapper.hh"
-#include <cstddef>
+#include "nes/common/types.hh"
#include <vector>
#include <string_view>
@@ -16,32 +16,35 @@ namespace nes::sys
class cartridge
{
- 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 };
+ static constexpr auto prg_rom_bank_size = u32{ 16 * 1024 };
+ static constexpr auto chr_rom_bank_size = u32{ 8 * 1024 };
+ static constexpr auto ram_bank_size = u32{ 8 * 1024 };
+ static constexpr auto max_prg_rom_size = u32{ 4 * prg_rom_bank_size };
+ static constexpr auto max_chr_rom_size = u32{ 4 * chr_rom_bank_size };
+ static constexpr auto max_ram_size = u32{ 4 * ram_bank_size };
+ static constexpr auto header_length = u32{ 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_magic_0() const -> u8 { return value[0]; }
+ auto get_magic_1() const -> u8 { return value[1]; }
+ auto get_magic_2() const -> u8 { return value[2]; }
+ auto get_magic_3() const -> u8 { return value[3]; }
+ auto get_prg_rom_banks() const -> u32 { return value[4]; }
+ auto get_chr_rom_banks() const -> u32 { return value[5]; }
+ auto get_control_1() const -> u8 { return value[6]; }
+ auto get_control_2() const -> u8 { return value[7]; }
+ auto get_ram_banks() const -> u32 { 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_mapper_low() const -> u32 { return (get_control_1() & 0b11110000) >> 4; }
+ auto get_mapper_high() const -> u32 { 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]{};
+ u8 value[header_length]{};
- explicit header(std::uint8_t const* v)
+ explicit header(u8 const* v)
{
- for (auto i = std::size_t{ 0 }; i < header_length; ++i)
+ for (auto i = u32{ 0 }; i < header_length; ++i)
{
value[i] = v[i];
}
@@ -49,26 +52,29 @@ namespace nes::sys
};
status status_{ status::error_uninitialized };
- std::vector<std::uint8_t> prg_rom_;
- std::vector<std::uint8_t> chr_rom_;
- std::vector<std::uint8_t> ram_;
+ u8 prg_rom_[max_prg_rom_size]{};
+ u8 chr_rom_[max_chr_rom_size]{};
+ u8 ram_[max_ram_size]{};
+ u32 prg_rom_size_{};
+ u32 chr_rom_size_{};
+ u32 ram_size_{};
name_table_arrangement name_table_arrangement_{};
mapper* mapper_{ &mapper::invalid() };
public:
explicit cartridge() = default;
- static auto from_data(void const* data, std::size_t length) -> cartridge;
+ static auto from_data(void const* data, u32 length) -> cartridge;
static auto from_file(std::string_view path) -> cartridge;
auto get_status() const -> status { return status_; }
- auto get_prg_rom() const -> std::uint8_t const* { return prg_rom_.data(); }
- auto get_prg_rom_length() const -> std::size_t { return prg_rom_.size(); }
- auto get_chr_rom() const -> std::uint8_t const* { return chr_rom_.data(); }
- auto get_chr_rom_length() const -> std::size_t { return chr_rom_.size(); }
- auto get_ram() const -> std::uint8_t const* { return ram_.data(); }
- auto get_ram_mut() -> std::uint8_t* { return ram_.data(); }
- auto get_ram_length() const -> std::size_t { return ram_.size(); }
+ auto get_prg_rom() const -> u8 const* { return prg_rom_; }
+ auto get_prg_rom_length() const -> u32 { return prg_rom_size_; }
+ auto get_chr_rom() const -> u8 const* { return chr_rom_; }
+ auto get_chr_rom_length() const -> u32 { return chr_rom_size_; }
+ auto get_ram() const -> u8 const* { return ram_; }
+ auto get_ram_mut() -> u8* { return ram_; }
+ auto get_ram_length() const -> u32 { return ram_size_; }
auto get_mapper() const -> mapper& { return *mapper_; }
auto get_name_table_arrangement() const -> name_table_arrangement { return name_table_arrangement_; }
diff --git a/lib/nes/sys/controller.cc b/lib/nes/sys/controller.cc
index 92dd897..d653f44 100644
--- a/lib/nes/sys/controller.cc
+++ b/lib/nes/sys/controller.cc
@@ -2,15 +2,15 @@
namespace nes::sys
{
- auto controller::read() -> std::uint8_t
+ auto controller::read() -> u8
{
auto const res = index_ < 8 ? (pressed_.get_raw_value() >> index_) & 1 : 0;
index_ += 1;
if (strobing_) { index_ = 0; }
- return static_cast<std::uint8_t>(res);
+ return static_cast<u8>(res);
}
- auto controller::write(std::uint8_t const value) -> void
+ auto controller::write(u8 const value) -> void
{
strobing_ = value & 1;
if (strobing_) { index_ = 0; }
diff --git a/lib/nes/sys/controller.hh b/lib/nes/sys/controller.hh
index d3a32fd..c330365 100644
--- a/lib/nes/sys/controller.hh
+++ b/lib/nes/sys/controller.hh
@@ -1,13 +1,14 @@
#pragma once
#include "nes/sys/types/button-mask.hh"
+#include "nes/common/types.hh"
namespace nes::sys
{
class controller
{
button_mask pressed_;
- unsigned index_{ 0 };
+ u32 index_{ 0 };
bool strobing_{ false };
public:
@@ -24,7 +25,7 @@ namespace nes::sys
// IO register
- auto read() -> std::uint8_t;
- auto write(std::uint8_t) -> void;
+ auto read() -> u8;
+ auto write(u8) -> void;
};
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/cpu.cc b/lib/nes/sys/cpu.cc
index 8b05f66..09e2094 100644
--- a/lib/nes/sys/cpu.cc
+++ b/lib/nes/sys/cpu.cc
@@ -541,7 +541,7 @@ namespace nes::sys
// LSR: Logical Shift Right
auto operand = fetch_operand<Mode>();
auto const old_val = operand.read();
- auto const new_val = static_cast<std::uint8_t>(old_val >> 1);
+ auto const new_val = static_cast<u8>(old_val >> 1);
operand.write(new_val);
registers_.p.set_c((old_val & 0x1) != 0);
update_zn(new_val);
@@ -692,7 +692,7 @@ namespace nes::sys
{
// SAX: AND A X
auto operand = fetch_operand<Mode>();
- auto const result = static_cast<std::uint8_t>(registers_.a & registers_.x);
+ auto const result = static_cast<u8>(registers_.a & registers_.x);
operand.write(result);
current_cycles_ += operand.get_cycles();
return status::success;
@@ -921,7 +921,7 @@ namespace nes::sys
{
// DCP: DEC + CMP
auto operand = fetch_operand<Mode>(force_page_crossing::yes);
- auto const tmp = static_cast<std::uint8_t>(operand.read() - 1);
+ auto const tmp = static_cast<u8>(operand.read() - 1);
operand.write(tmp);
eval_cmp(registers_.a, tmp);
current_cycles_ += operand.get_cycles() + cycle_count::from_cpu(2);
@@ -934,7 +934,7 @@ namespace nes::sys
// DEC: Decrement Memory
auto operand = fetch_operand<Mode>();
auto const old_val = read8(operand.get_address());
- auto const new_val = static_cast<std::uint8_t>(old_val - 1);
+ auto const new_val = static_cast<u8>(old_val - 1);
write8(operand.get_address(), new_val);
update_zn(new_val);
current_cycles_ += inc_dec_cycle_count<Mode>();
@@ -1000,7 +1000,7 @@ namespace nes::sys
{
// ISC: INC + SBC
auto operand = fetch_operand<Mode>(force_page_crossing::yes);
- auto const tmp = static_cast<std::uint8_t>(operand.read() + 1);
+ auto const tmp = static_cast<u8>(operand.read() + 1);
operand.write(tmp);
eval_adc(~tmp);
current_cycles_ += operand.get_cycles() + cycle_count::from_cpu(2);
@@ -1013,7 +1013,7 @@ namespace nes::sys
// INC: Increment Memory
auto operand = fetch_operand<Mode>();
auto const old_val = read8(operand.get_address());
- auto const new_val = static_cast<std::uint8_t>(old_val + 1);
+ auto const new_val = static_cast<u8>(old_val + 1);
write8(operand.get_address(), new_val);
update_zn(new_val);
current_cycles_ += inc_dec_cycle_count<Mode>();
@@ -1049,48 +1049,48 @@ namespace nes::sys
// Helpers
// -----------------------------------------------------------------------------------------------------------------
- auto cpu::advance_pc8() -> std::uint8_t
+ auto cpu::advance_pc8() -> u8
{
auto const val = read8(address{ registers_.pc });
registers_.pc += 1;
return val;
}
- auto cpu::advance_pc16() -> std::uint16_t
+ auto cpu::advance_pc16() -> u16
{
auto const val = read16(address{ registers_.pc });
registers_.pc += 2;
return val;
}
- auto cpu::push_stack8(std::uint8_t const value) -> void
+ auto cpu::push_stack8(u8 const value) -> void
{
write8(stack_offset + registers_.sp, value);
registers_.sp -= 1;
}
- auto cpu::push_stack16(std::uint16_t const value) -> void
+ auto cpu::push_stack16(u16 const value) -> void
{
- auto const low = static_cast<std::uint8_t>(value >> 0 & 0xFF);
- auto const high = static_cast<std::uint8_t>(value >> 8 & 0xFF);
+ auto const low = static_cast<u8>(value >> 0 & 0xFF);
+ auto const high = static_cast<u8>(value >> 8 & 0xFF);
push_stack8(high);
push_stack8(low);
}
- auto cpu::pop_stack8() -> std::uint8_t
+ auto cpu::pop_stack8() -> u8
{
registers_.sp += 1;
return read8(stack_offset + registers_.sp);
}
- auto cpu::pop_stack16() -> std::uint16_t
+ auto cpu::pop_stack16() -> u16
{
auto const low = pop_stack8();
auto const high = pop_stack8();
- return static_cast<std::uint16_t>((high << 8) | (low << 0));
+ return static_cast<u16>((high << 8) | (low << 0));
}
- auto cpu::update_zn(std::uint8_t const value) -> void
+ auto cpu::update_zn(u8 const value) -> void
{
registers_.p.set_z(value == 0);
registers_.p.set_n((value & 0x80) != 0);
@@ -1122,43 +1122,43 @@ namespace nes::sys
current_cycles_ += cycle_count::from_cpu(7);
}
- auto cpu::eval_ror(std::uint8_t const arg) -> std::uint8_t
+ auto cpu::eval_ror(u8 const arg) -> u8
{
- auto const res = static_cast<std::uint8_t>(((registers_.p.get_c() ? 1 :0) << 7) | (arg >> 1));
+ auto const res = static_cast<u8>(((registers_.p.get_c() ? 1 :0) << 7) | (arg >> 1));
registers_.p.set_c((arg & 0x1) != 0);
update_zn(res);
return res;
}
- auto cpu::eval_rol(std::uint8_t const arg) -> std::uint8_t
+ auto cpu::eval_rol(u8 const arg) -> u8
{
- auto const res = static_cast<std::uint8_t>((arg << 1) | (registers_.p.get_c() ? 1 : 0));
+ auto const res = static_cast<u8>((arg << 1) | (registers_.p.get_c() ? 1 : 0));
registers_.p.set_c((arg & 0x80) != 0);
update_zn(res);
return res;
}
- auto cpu::eval_asl(std::uint8_t const arg) -> std::uint8_t
+ auto cpu::eval_asl(u8 const arg) -> u8
{
- auto const new_val = static_cast<std::uint8_t>(arg << 1);
+ auto const new_val = static_cast<u8>(arg << 1);
registers_.p.set_c((arg & 0x80) != 0);
update_zn(new_val);
return new_val;
}
- auto cpu::eval_lsr(std::uint8_t const arg) -> std::uint8_t
+ auto cpu::eval_lsr(u8 const arg) -> u8
{
- auto const new_val = static_cast<std::uint8_t>(arg >> 1);
+ auto const new_val = static_cast<u8>(arg >> 1);
registers_.p.set_c((arg & 0x01) != 0);
update_zn(new_val);
return new_val;
}
- auto cpu::eval_adc(std::uint8_t const arg) -> void
+ auto cpu::eval_adc(u8 const arg) -> void
{
auto const old_val = registers_.a;
auto const tmp = old_val + arg + (registers_.p.get_c() ? 1 : 0);
- auto const new_val = static_cast<std::uint8_t>(tmp);
+ auto const new_val = static_cast<u8>(tmp);
registers_.a = new_val;
registers_.p.set_c(tmp > 0xFF);
@@ -1166,25 +1166,25 @@ namespace nes::sys
update_zn(registers_.a);
}
- auto cpu::eval_and(std::uint8_t const arg) -> void
+ auto cpu::eval_and(u8 const arg) -> void
{
registers_.a &= arg;
update_zn(registers_.a);
}
- auto cpu::eval_ora(std::uint8_t const arg) -> void
+ auto cpu::eval_ora(u8 const arg) -> void
{
registers_.a |= arg;
update_zn(registers_.a);
}
- auto cpu::eval_eor(std::uint8_t const arg) -> void
+ auto cpu::eval_eor(u8 const arg) -> void
{
registers_.a ^= arg;
update_zn(registers_.a);
}
- auto cpu::eval_cmp(std::uint8_t const a, std::uint8_t const b) -> void
+ auto cpu::eval_cmp(u8 const a, u8 const b) -> void
{
update_zn(a - b);
registers_.p.set_c(a >= b);
@@ -1238,7 +1238,7 @@ namespace nes::sys
{
auto const offset = static_cast<std::int8_t>(advance_pc8());
auto const base = address{ registers_.pc };
- addr = address{ static_cast<std::uint16_t>(registers_.pc + offset) };
+ addr = address{ static_cast<u16>(registers_.pc + offset) };
auto const page_crossing =
base.get_page() != addr.get_page() || force_page_crossing == force_page_crossing::yes;
cycles = cycle_count::from_cpu(page_crossing ? 4 : 3);
@@ -1257,14 +1257,14 @@ namespace nes::sys
case addressing_mode::zero_page_indexed_x:
{
// PEEK((arg + X) % 256)
- addr = address{ 0x00, static_cast<std::uint8_t>(advance_pc8() + registers_.x) };
+ addr = address{ 0x00, static_cast<u8>(advance_pc8() + registers_.x) };
cycles = cycle_count::from_cpu(4);
break;
}
case addressing_mode::zero_page_indexed_y:
{
// PEEK((arg + Y) % 256)
- addr = address{ 0x00, static_cast<std::uint8_t>(advance_pc8() + registers_.y) };
+ addr = address{ 0x00, static_cast<u8>(advance_pc8() + registers_.y) };
cycles = cycle_count::from_cpu(4);
break;
}
@@ -1292,8 +1292,8 @@ namespace nes::sys
{
// PEEK(PEEK((arg + X) % 256) + PEEK((arg + X + 1) % 256) * 256)
auto const arg = advance_pc8();
- auto const page = read8(address{ 0x00, static_cast<std::uint8_t>(arg + registers_.x + 1) });
- auto const offset = read8(address{ 0x00, static_cast<std::uint8_t>(arg + registers_.x) });
+ auto const page = read8(address{ 0x00, static_cast<u8>(arg + registers_.x + 1) });
+ auto const offset = read8(address{ 0x00, static_cast<u8>(arg + registers_.x) });
addr = address{ page, offset };
cycles = cycle_count::from_cpu(6);
break;
@@ -1302,8 +1302,8 @@ namespace nes::sys
{
// PEEK(PEEK(arg) + PEEK((arg + 1) % 256) * 256 + Y)
auto const arg = advance_pc8();
- auto const page = read8(address{ 0x00, static_cast<std::uint8_t>(arg + 1) });
- auto const offset = read8(address{ 0x00, static_cast<std::uint8_t>(arg) });
+ auto const page = read8(address{ 0x00, static_cast<u8>(arg + 1) });
+ auto const offset = read8(address{ 0x00, static_cast<u8>(arg) });
auto const base = address{ page, offset };
addr = base + registers_.y;
auto const page_crossing =
@@ -1338,7 +1338,7 @@ namespace nes::sys
// See: https://www.nesdev.org/wiki/CPU_memory_map
//
- auto cpu::read8(address const addr) -> std::uint8_t
+ auto cpu::read8(address const addr) -> u8
{
if (addr <= address{ 0x1FFF }) { return ram_[addr.get_absolute() % ram_size]; }
if (addr <= address{ 0x3FFF })
@@ -1373,14 +1373,14 @@ namespace nes::sys
return cartridge_.get_mapper().read_cpu(addr, cartridge_);
}
- auto cpu::read16(address const addr) -> std::uint16_t
+ auto cpu::read16(address const addr) -> u16
{
auto const low = read8(addr + 0);
auto const high = read8(addr + 1);
- return static_cast<std::uint16_t>((high << 8) | (low << 0));
+ return static_cast<u16>((high << 8) | (low << 0));
}
- auto cpu::write8(address const addr, std::uint8_t const value) -> void
+ auto cpu::write8(address const addr, u8 const value) -> void
{
if (addr <= address{ 0x1FFF }) { ram_[addr.get_absolute() % ram_size] = value; return; }
if (addr <= address{ 0x3FFF })
@@ -1415,10 +1415,10 @@ namespace nes::sys
cartridge_.get_mapper().write_cpu(addr, value, cartridge_);
}
- auto cpu::write16(address const addr, std::uint16_t const value) -> void
+ auto cpu::write16(address const addr, u16 const value) -> void
{
- auto const low = static_cast<std::uint8_t>(value >> 0 & 0xFF);
- auto const high = static_cast<std::uint8_t>(value >> 8 & 0xFF);
+ auto const low = static_cast<u8>(value >> 0 & 0xFF);
+ auto const high = static_cast<u8>(value >> 8 & 0xFF);
write8(addr + 0, low);
write8(addr + 1, high);
}
diff --git a/lib/nes/sys/cpu.hh b/lib/nes/sys/cpu.hh
index 2702c20..5d6466f 100644
--- a/lib/nes/sys/cpu.hh
+++ b/lib/nes/sys/cpu.hh
@@ -3,6 +3,7 @@
#include "nes/sys/types/cycle-count.hh"
#include "nes/sys/types/address.hh"
#include "nes/sys/types/status.hh"
+#include "nes/common/types.hh"
namespace nes::sys
{
@@ -13,7 +14,7 @@ namespace nes::sys
class cpu
{
- static constexpr auto ram_size = std::size_t{ 0x800 };
+ static constexpr auto ram_size = u32{ 0x800 };
static constexpr auto stack_offset = address{ 0x100 };
cycle_count current_cycles_;
@@ -21,17 +22,17 @@ namespace nes::sys
cartridge& cartridge_;
controller& controller_1_;
controller& controller_2_;
- std::uint8_t ram_[ram_size]{};
+ u8 ram_[ram_size]{};
bool nmi_pending_{ false };
// Registers
struct
{
- std::uint16_t pc{ 0 };
- std::uint8_t sp{ 0xFD };
- std::uint8_t a{ 0 };
- std::uint8_t x{ 0 };
- std::uint8_t y{ 0 };
+ u16 pc{ 0 };
+ u8 sp{ 0xFD };
+ u8 a{ 0 };
+ u8 x{ 0 };
+ u8 y{ 0 };
struct
{
auto get_c() const -> bool { return value & 0b00000001; } // carry
@@ -50,7 +51,7 @@ namespace nes::sys
auto set_v(bool const v) -> void { value = (value & ~0b01000000) | (v ? 0b01000000 : 0); }
auto set_n(bool const v) -> void { value = (value & ~0b10000000) | (v ? 0b10000000 : 0); }
- std::uint8_t value{ 0b00100100 };
+ u8 value{ 0b00100100 };
} p{};
} registers_{};
@@ -91,8 +92,8 @@ namespace nes::sys
{
}
- auto read() -> std::uint8_t { return cpu_.read8(address_); }
- auto write(std::uint8_t const value) -> void { cpu_.write8(address_, value); }
+ auto read() -> u8 { return cpu_.read8(address_); }
+ auto write(u8 const value) -> void { cpu_.write8(address_, value); }
auto get_address() -> address { return address_; }
auto get_cycles() -> cycle_count { return cycles_; }
};
@@ -108,23 +109,23 @@ namespace nes::sys
{
}
- auto read() -> std::uint8_t { return cpu_.registers_.a; }
- auto write(std::uint8_t const value) -> void { cpu_.registers_.a = value; }
+ auto read() -> u8 { return cpu_.registers_.a; }
+ auto write(u8 const value) -> void { cpu_.registers_.a = value; }
auto get_cycles() -> cycle_count { return cycle_count::from_cpu(2); }
};
template<>
class operand<addressing_mode::immediate>
{
- std::uint8_t value_{ 0 };
+ u8 value_{ 0 };
public:
- explicit operand(std::uint8_t const value)
+ explicit operand(u8 const value)
: value_{ value }
{
}
- auto read() -> std::uint8_t { return value_; }
+ auto read() -> u8 { return value_; }
auto get_cycles() -> cycle_count { return cycle_count::from_cpu(2); }
};
@@ -145,10 +146,10 @@ namespace nes::sys
// Memory access
- auto read8(address) -> std::uint8_t;
- auto read16(address) -> std::uint16_t;
- auto write8(address, std::uint8_t) -> void;
- auto write16(address, std::uint16_t) -> void;
+ auto read8(address) -> u8;
+ auto read16(address) -> u16;
+ auto write8(address, u8) -> void;
+ auto write16(address, u16) -> void;
private:
// Instructions
@@ -240,26 +241,26 @@ namespace nes::sys
// Helpers
- auto advance_pc8() -> std::uint8_t;
- auto advance_pc16() -> std::uint16_t;
- auto push_stack8(std::uint8_t) -> void;
- auto push_stack16(std::uint16_t) -> void;
- auto pop_stack8() -> std::uint8_t;
- auto pop_stack16() -> std::uint16_t;
- auto update_zn(std::uint8_t value) -> void;
+ auto advance_pc8() -> u8;
+ auto advance_pc16() -> u16;
+ auto push_stack8(u8) -> void;
+ auto push_stack16(u16) -> void;
+ auto pop_stack8() -> u8;
+ auto pop_stack16() -> u16;
+ auto update_zn(u8 value) -> void;
template<addressing_mode Mode>
auto branch(bool condition) -> void;
auto execute_interrupt(address) -> void;
- auto eval_ror(std::uint8_t arg) -> std::uint8_t;
- auto eval_rol(std::uint8_t arg) -> std::uint8_t;
- auto eval_asl(std::uint8_t arg) -> std::uint8_t;
- auto eval_lsr(std::uint8_t arg) -> std::uint8_t;
- auto eval_adc(std::uint8_t arg) -> void;
- auto eval_and(std::uint8_t arg) -> void;
- auto eval_ora(std::uint8_t arg) -> void;
- auto eval_eor(std::uint8_t arg) -> void;
- auto eval_cmp(std::uint8_t a, std::uint8_t b) -> void;
+ auto eval_ror(u8 arg) -> u8;
+ auto eval_rol(u8 arg) -> u8;
+ auto eval_asl(u8 arg) -> u8;
+ auto eval_lsr(u8 arg) -> u8;
+ auto eval_adc(u8 arg) -> void;
+ auto eval_and(u8 arg) -> void;
+ auto eval_ora(u8 arg) -> void;
+ auto eval_eor(u8 arg) -> void;
+ auto eval_cmp(u8 a, u8 b) -> void;
auto eval_plp() -> void;
auto eval_php() -> void;
diff --git a/lib/nes/sys/mapper.cc b/lib/nes/sys/mapper.cc
index fc6ec6c..d779076 100644
--- a/lib/nes/sys/mapper.cc
+++ b/lib/nes/sys/mapper.cc
@@ -34,7 +34,7 @@ namespace nes::sys
return status::success;
}
- auto read_cpu(address const addr, cartridge& cartridge) -> std::uint8_t override
+ auto read_cpu(address const addr, cartridge& cartridge) -> u8 override
{
if (addr <= address{ 0x5FFF })
{
@@ -59,7 +59,7 @@ namespace nes::sys
return 0x0;
}
- auto write_cpu(address const addr, std::uint8_t const value, cartridge& cartridge) -> void override
+ auto write_cpu(address const addr, u8 const value, cartridge& cartridge) -> void override
{
if (addr <= address{ 0x5FFF })
{
@@ -72,7 +72,7 @@ namespace nes::sys
}
}
- auto read_ppu(address const addr, cartridge& cartridge, std::uint8_t const* vram) -> std::uint8_t override
+ auto read_ppu(address const addr, cartridge& cartridge, u8 const* vram) -> u8 override
{
if (addr <= address{ 0x1FFF })
{
@@ -87,7 +87,7 @@ namespace nes::sys
return 0x0;
}
- auto write_ppu(address const addr, std::uint8_t const value, cartridge& cartridge, std::uint8_t* vram) -> void override
+ auto write_ppu(address const addr, u8 const value, cartridge& cartridge, u8* vram) -> void override
{
if (addr <= address{ 0x1FFF })
{
@@ -101,7 +101,7 @@ namespace nes::sys
}
private:
- static auto mirrored_vram_address(address const addr, cartridge const& cartridge) -> unsigned
+ static auto mirrored_vram_address(address const addr, cartridge const& cartridge) -> u32
{
auto const rel = addr.get_absolute() % 0x1000u;
@@ -137,10 +137,10 @@ namespace nes::sys
explicit mapper_invalid() = default;
auto validate(cartridge&) -> status override { return status::error_unsupported_mapper; }
- auto read_cpu(address, cartridge&) -> std::uint8_t override { return 0; }
- auto write_cpu(address, std::uint8_t, cartridge&) -> void override {}
- auto read_ppu(address, cartridge&, std::uint8_t const*) -> std::uint8_t override { return 0; }
- auto write_ppu(address, std::uint8_t, cartridge&, std::uint8_t*) -> void override {}
+ auto read_cpu(address, cartridge&) -> u8 override { return 0; }
+ auto write_cpu(address, u8, cartridge&) -> void override {}
+ auto read_ppu(address, cartridge&, u8 const*) -> u8 override { return 0; }
+ auto write_ppu(address, u8, cartridge&, u8*) -> void override {}
};
} // namespace
@@ -154,7 +154,7 @@ namespace nes::sys
return instance;
}
- auto mapper::get(std::uint8_t const number) -> mapper&
+ auto mapper::get(u8 const number) -> mapper&
{
switch (number)
{
diff --git a/lib/nes/sys/mapper.hh b/lib/nes/sys/mapper.hh
index 5db198b..c7c9784 100644
--- a/lib/nes/sys/mapper.hh
+++ b/lib/nes/sys/mapper.hh
@@ -2,6 +2,7 @@
#include "nes/sys/types/address.hh"
#include "nes/sys/types/status.hh"
+#include "nes/common/types.hh"
namespace nes::sys
{
@@ -11,7 +12,7 @@ namespace nes::sys
{
public:
static auto invalid() -> mapper&;
- static auto get(std::uint8_t number) -> mapper&;
+ static auto get(u8 number) -> mapper&;
virtual ~mapper() = default;
@@ -21,10 +22,10 @@ namespace nes::sys
auto operator=(mapper&&) -> mapper& = delete;
virtual auto validate(cartridge&) -> status = 0;
- virtual auto read_cpu(address, cartridge&) -> std::uint8_t = 0;
- virtual auto write_cpu(address, std::uint8_t, cartridge&) -> void = 0;
- virtual auto read_ppu(address, cartridge&, std::uint8_t const* vram) -> std::uint8_t = 0;
- virtual auto write_ppu(address, std::uint8_t, cartridge&, std::uint8_t* vram) -> void = 0;
+ virtual auto read_cpu(address, cartridge&) -> u8 = 0;
+ virtual auto write_cpu(address, u8, cartridge&) -> void = 0;
+ virtual auto read_ppu(address, cartridge&, u8 const* vram) -> u8 = 0;
+ virtual auto write_ppu(address, u8, cartridge&, u8* vram) -> void = 0;
protected:
explicit mapper() = default;
diff --git a/lib/nes/sys/nes.cc b/lib/nes/sys/nes.cc
index 6caf6de..a711f06 100644
--- a/lib/nes/sys/nes.cc
+++ b/lib/nes/sys/nes.cc
@@ -1,11 +1,9 @@
#include "nes/sys/nes.hh"
#include "nes/sys/types/snapshot.hh"
-#include "nes/common/display.hh"
-#include "nes/common/rgb.hh"
namespace nes::sys
{
- nes::nes(cartridge cartridge, display& display)
+ nes::nes(cartridge const& cartridge, display& display)
: cartridge_{ std::move(cartridge) }
, display_{ display }
, ppu_{ cpu_, cartridge_, display_ }
diff --git a/lib/nes/sys/nes.hh b/lib/nes/sys/nes.hh
index 4e0fd63..4150935 100644
--- a/lib/nes/sys/nes.hh
+++ b/lib/nes/sys/nes.hh
@@ -28,7 +28,8 @@ namespace nes::sys
status status_{ status::success };
public:
- explicit nes(cartridge, display&);
+ // TODO: Don't copy cartridge
+ explicit nes(cartridge const&, display&);
nes(nes const&) = delete;
nes(nes&&) = delete;
diff --git a/lib/nes/sys/ppu.cc b/lib/nes/sys/ppu.cc
index 00cddbe..c9e6f11 100644
--- a/lib/nes/sys/ppu.cc
+++ b/lib/nes/sys/ppu.cc
@@ -79,7 +79,7 @@ namespace nes::sys
// Load the tile palette for the background from the attribute table.
auto const addr =
address{ 0x23C0 } +
- (static_cast<unsigned>(internal_.v.get_name_table()) * 0x400u) +
+ (static_cast<u32>(internal_.v.get_name_table()) * 0x400u) +
((internal_.v.get_coarse_y() & 0b11100u) << 1) +
((internal_.v.get_coarse_x() & 0b11100u) >> 2);
auto const shift =
@@ -190,11 +190,11 @@ namespace nes::sys
auto foreground_color = color_index{ 0 };
if (mask_.get_enable_sprites())
{
- for (auto i = unsigned{ 0 }; i < sprite_count_; ++i)
+ for (auto i = u32{ 0 }; i < sprite_count_; ++i)
{
auto const s = sprites_[i];
auto const offset = static_cast<int>(x) - static_cast<int>(s.x);
- if (offset < 0 || static_cast<unsigned>(offset) >= tile_size) { continue; }
+ if (offset < 0 || static_cast<u32>(offset) >= tile_size) { continue; }
auto const color = s.pattern.colors[offset];
if (color.get_color() == palette_color::_0) { continue; }
@@ -237,15 +237,15 @@ namespace nes::sys
{
auto const height = get_sprite_height();
sprite_count_ = 0;
- for (auto i = unsigned{ 0 }; i < sprite_max_count; ++i)
+ for (auto i = u32{ 0 }; i < sprite_max_count; ++i)
{
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 (row < 0 || static_cast<u32>(row) >= height) { continue; }
if (sprite_count_ < 8)
{
- sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast<unsigned>(row));
+ sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast<u32>(row));
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;
@@ -259,7 +259,7 @@ namespace nes::sys
}
}
- auto ppu::fetch_sprite_pattern(sprite const s, unsigned row) -> tile_row
+ auto ppu::fetch_sprite_pattern(sprite const s, u32 row) -> tile_row
{
if (s.get_flip_vertical()) { row = get_sprite_height() - 1 - row; }
tile tile;
@@ -289,7 +289,7 @@ namespace nes::sys
if (s.get_flip_horizontal())
{
- for (auto i = unsigned{ 0 }; i < tile_size / 2; ++i)
+ for (auto i = u32{ 0 }; i < tile_size / 2; ++i)
{
std::swap(res.colors[i], res.colors[tile_size - 1 - i]);
}
@@ -306,21 +306,21 @@ namespace nes::sys
// See: https://www.nesdev.org/wiki/PPU_memory_map
//
- auto ppu::read8(address addr) -> std::uint8_t
+ auto ppu::read8(address addr) -> u8
{
addr = addr % 0x4000; // PPU only has 16 KiB addresses.
if (addr <= address{ 0x3EFF }) { return cartridge_.get_mapper().read_ppu(addr, cartridge_, vram_); }
if (addr <= address{ 0x3FFF })
{
- auto const index = color_index{ static_cast<std::uint8_t>(addr.get_absolute() % 0x20) };
+ auto const index = color_index{ static_cast<u8>(addr.get_absolute() % 0x20) };
auto const color = ref_color(index);
- return static_cast<std::uint8_t>(color);
+ return static_cast<u8>(color);
}
return 0x0;
}
- auto ppu::write8(address addr, std::uint8_t const value) -> void
+ auto ppu::write8(address addr, u8 const value) -> void
{
addr = addr % 0x4000; // PPU only has 16 KiB addresses.
if (addr <= address{ 0x3EFF })
@@ -330,7 +330,7 @@ namespace nes::sys
}
if (addr <= address{ 0x3FFF })
{
- auto const index = color_index{ static_cast<std::uint8_t>(addr.get_absolute() % 0x20) };
+ auto const index = color_index{ static_cast<u8>(addr.get_absolute() % 0x20) };
ref_color(index) = color{ value };
return;
}
@@ -344,12 +344,12 @@ namespace nes::sys
// See: https://www.nesdev.org/wiki/PPU_registers
//
- auto ppu::read_latch() -> std::uint8_t
+ auto ppu::read_latch() -> u8
{
return latch_;
}
- auto ppu::read_ppustatus() -> std::uint8_t
+ auto ppu::read_ppustatus() -> u8
{
auto res = status_;
res.set_remaining(latch_);
@@ -362,7 +362,7 @@ namespace nes::sys
return res.value;
}
- auto ppu::read_oamdata() -> std::uint8_t
+ auto ppu::read_oamdata() -> u8
{
auto res = oam_[oamaddr_];
if ((oamaddr_ & 0x3) == 0x2)
@@ -374,7 +374,7 @@ namespace nes::sys
return res;
}
- auto ppu::read_ppudata() -> std::uint8_t
+ auto ppu::read_ppudata() -> u8
{
auto const addr = address{ internal_.v.value };
auto res = read8(addr);
@@ -395,12 +395,12 @@ namespace nes::sys
return res;
}
- auto ppu::write_latch(std::uint8_t const value) -> void
+ auto ppu::write_latch(u8 const value) -> void
{
latch_ = value;
}
- auto ppu::write_ppuctrl(std::uint8_t const value) -> void
+ auto ppu::write_ppuctrl(u8 const value) -> void
{
write_latch(value);
if (current_cycles_ > boot_up_cycles)
@@ -412,7 +412,7 @@ namespace nes::sys
}
}
- auto ppu::write_ppuscroll(std::uint8_t const value) -> void
+ auto ppu::write_ppuscroll(u8 const value) -> void
{
write_latch(value);
if (current_cycles_ > boot_up_cycles)
@@ -435,7 +435,7 @@ namespace nes::sys
}
}
- auto ppu::write_ppumask(std::uint8_t const value) -> void
+ auto ppu::write_ppumask(u8 const value) -> void
{
write_latch(value);
if (current_cycles_ > boot_up_cycles)
@@ -445,7 +445,7 @@ namespace nes::sys
}
}
- auto ppu::write_ppuaddr(std::uint8_t const value) -> void
+ auto ppu::write_ppuaddr(u8 const value) -> void
{
write_latch(value);
if (current_cycles_ > boot_up_cycles)
@@ -467,7 +467,7 @@ namespace nes::sys
}
}
- auto ppu::write_ppudata(std::uint8_t const value) -> void
+ auto ppu::write_ppudata(u8 const value) -> void
{
NES_DEBUG_LOG(ppu, "PPUDATA <- {:#2x} (address: {:#4x})", value, internal_.v);
write_latch(value);
@@ -475,14 +475,14 @@ namespace nes::sys
increment_vram();
}
- auto ppu::write_oamaddr(std::uint8_t const value) -> void
+ auto ppu::write_oamaddr(u8 const value) -> void
{
NES_DEBUG_LOG(ppu, "OAMADDR <- {:#2x}", value);
write_latch(value);
oamaddr_ = value;
}
- auto ppu::write_oamdata(std::uint8_t const value) -> void
+ auto ppu::write_oamdata(u8 const value) -> void
{
NES_DEBUG_LOG(ppu, "OAMDATA <- {:#2x}", value);
write_latch(value);
@@ -490,11 +490,11 @@ namespace nes::sys
oamaddr_ += 1;
}
- auto ppu::write_oamdma(std::uint8_t const value) -> void
+ auto ppu::write_oamdma(u8 const value) -> void
{
NES_DEBUG_LOG(ppu, "OAMDMA <- {:#2x}", value);
auto addr = address{ value, 0x00 };
- for (auto i = unsigned{ 0 }; i < 256; ++i)
+ for (auto i = u32{ 0 }; i < 256; ++i)
{
oam_[oamaddr_] = cpu_.read8(addr);
oamaddr_ += 1;
@@ -574,7 +574,7 @@ namespace nes::sys
internal_.v.set_vertical_name_table(internal_.t.get_vertical_name_table());
}
- auto ppu::get_sprite_height() const -> unsigned
+ auto ppu::get_sprite_height() const -> u32
{
switch (control_.get_sprite_size())
{
@@ -588,17 +588,17 @@ namespace nes::sys
}
auto ppu::get_tile_bitplane(
- pattern_table const pattern_table, tile const tile, unsigned const row, bitplane const bitplane) -> std::uint8_t
+ pattern_table const pattern_table, tile const tile, u32 const row, bitplane const bitplane) -> u8
{
- auto const addr = static_cast<std::uint16_t>(
- 0x1000 * static_cast<unsigned>(pattern_table) + 0x10 * static_cast<unsigned>(tile) + row);
- return read8(address{ addr } + (static_cast<unsigned>(bitplane) * 8u));
+ auto const addr = static_cast<u16>(
+ 0x1000 * static_cast<u32>(pattern_table) + 0x10 * static_cast<u32>(tile) + row);
+ return read8(address{ addr } + (static_cast<u32>(bitplane) * 8u));
}
- auto ppu::get_tile_row(palette const palette, std::uint8_t bitplane_0, std::uint8_t bitplane_1) const -> tile_row
+ auto ppu::get_tile_row(palette const palette, u8 bitplane_0, u8 bitplane_1) const -> tile_row
{
auto res = tile_row{};
- for (auto i = unsigned{ 0 }; i < tile_size; ++i)
+ for (auto i = u32{ 0 }; i < tile_size; ++i)
{
auto const bit_0 = (bitplane_0 & 0b10000000u) >> 7;
auto const bit_1 = (bitplane_1 & 0b10000000u) >> 7;
@@ -624,7 +624,7 @@ namespace nes::sys
auto ppu::resolve_color(color const color) const -> rgb
{
- auto const index = static_cast<std::uint8_t>(color);
+ auto const index = static_cast<u8>(color);
switch (index & 0x3F)
{
case 0x00: return rgb::from_hex(0x666666);
diff --git a/lib/nes/sys/ppu.hh b/lib/nes/sys/ppu.hh
index cdca0ae..013546a 100644
--- a/lib/nes/sys/ppu.hh
+++ b/lib/nes/sys/ppu.hh
@@ -1,6 +1,7 @@
#pragma once
#include "nes/sys/types/cycle-count.hh"
+#include "nes/common/types.hh"
namespace nes
{
@@ -17,40 +18,40 @@ namespace nes::sys
class ppu
{
- static constexpr auto sprite_max_count = unsigned{ 64 };
- static constexpr auto vram_size = std::size_t{ 0x800 };
- static constexpr auto oam_size = std::size_t{ sprite_max_count * 4 };
- static constexpr auto palette_buffer_size = std::size_t{ 0x20 };
- static constexpr auto tile_size = unsigned{ 8 };
+ static constexpr auto sprite_max_count = u32{ 64 };
+ static constexpr auto vram_size = u32{ 0x800 };
+ static constexpr auto oam_size = u32{ sprite_max_count * 4 };
+ static constexpr auto palette_buffer_size = u32{ 0x20 };
+ static constexpr auto tile_size = u32{ 8 };
// Writes to some registers are ignored until this clock cycle.
static constexpr auto boot_up_cycles = cycle_count::from_ppu(29658);
- enum class bitplane : unsigned { _0, _1 };
- enum class palette : unsigned { _0, _1, _2, _3 };
- enum class palette_color : unsigned { _0, _1, _2, _3 };
- enum class name_table : unsigned { _0, _1, _2, _3 };
- enum class role : unsigned { background, foreground };
- enum class pattern_table : unsigned { _0, _1 };
- enum class vram_increment : unsigned { forward, downward };
- enum class sprite_size : unsigned { single_height, double_height };
- enum class tile : std::uint8_t {};
- enum class color : std::uint8_t {};
+ enum class bitplane : u32 { _0, _1 };
+ enum class palette : u32 { _0, _1, _2, _3 };
+ enum class palette_color : u32 { _0, _1, _2, _3 };
+ enum class name_table : u32 { _0, _1, _2, _3 };
+ enum class role : u32 { background, foreground };
+ enum class pattern_table : u32 { _0, _1 };
+ enum class vram_increment : u32 { forward, downward };
+ enum class sprite_size : u32 { single_height, double_height };
+ enum class tile : u8 {};
+ enum class color : u8 {};
#define BITFIELD_VALIDATE(mask, offset_from_right) \
static_assert((mask & (1 << offset_from_right)) != 0); \
static_assert(offset_from_right == 0 || (mask & (1 << (offset_from_right - 1))) == 0);
#define BITFIELD_VALUE(name, base, mask, offset_from_right) \
BITFIELD_VALIDATE(mask, offset_from_right) \
- auto get_##name() const -> unsigned { return (base & mask) >> offset_from_right; } \
- auto set_##name(unsigned const v) -> void { base = (base & ~mask) | ((v << offset_from_right) & mask); }
+ auto get_##name() const -> u32 { return (base & mask) >> offset_from_right; } \
+ auto set_##name(u32 const v) -> void { base = (base & ~mask) | ((v << offset_from_right) & mask); }
#define BITFIELD_ENUM(name, type, base, mask, offset_from_right) \
BITFIELD_VALIDATE(mask, offset_from_right) \
auto get_##name() const -> type { return static_cast<type>((base & mask) >> offset_from_right); } \
- auto set_##name(type const v) -> void { base = (base & ~mask) | ((static_cast<unsigned>(v) << offset_from_right) & mask); }
+ auto set_##name(type const v) -> void { base = (base & ~mask) | ((static_cast<u32>(v) << offset_from_right) & mask); }
#define BITFIELD_FLAG(name, base, mask, offset_from_right) \
BITFIELD_VALIDATE(mask, offset_from_right) \
auto get_##name() const -> bool { return base & mask; } \
- auto set_##name(unsigned const v) -> void { base = (base & ~mask) | (v ? mask : 0); }
+ auto set_##name(u32 const v) -> void { base = (base & ~mask) | (v ? mask : 0); }
struct color_index
{
@@ -58,11 +59,11 @@ namespace nes::sys
BITFIELD_ENUM(palette, palette, value, 0b00001100, 2)
BITFIELD_ENUM(role, role, value, 0b00010000, 4)
- std::uint8_t value{};
+ u8 value{};
color_index() = default;
- explicit color_index(std::uint8_t const value)
+ explicit color_index(u8 const value)
: value{ value }
{
}
@@ -81,21 +82,21 @@ namespace nes::sys
BITFIELD_FLAG(flip_horizontal, value[2], 0b01000000, 6)
BITFIELD_FLAG(flip_vertical, value[2], 0b10000000, 7)
- 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 get_y() const -> u8 { return value[0]; }
+ auto get_tile_index() const -> u8 { return value[1]; }
+ auto get_attributes() const -> u8 { return value[2]; }
+ auto get_x() const -> u8 { 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; }
+ auto set_y(u8 const v) -> void { value[0] = v; }
+ auto set_tile_index(u8 const v) -> void { value[1] = v; }
+ auto set_attributes(u8 const v) -> void { value[2] = v; }
+ auto set_x(u8 const v) -> void { value[3] = v; }
- std::uint8_t value[4]{};
+ u8 value[4]{};
explicit sprite() = default;
- explicit sprite(std::uint8_t const* data)
+ explicit sprite(u8 const* data)
: value{ data[0], data[1], data[2], data[3] }
{
}
@@ -109,7 +110,7 @@ namespace nes::sys
struct evaluated_sprite
{
tile_row pattern;
- std::uint8_t x{ 0 };
+ u8 x{ 0 };
bool is_in_front{ false };
bool is_sprite_zero{ false };
};
@@ -118,8 +119,8 @@ namespace nes::sys
cpu& cpu_;
cartridge& cartridge_;
display& display_;
- std::uint8_t vram_[vram_size]{};
- std::uint8_t oam_[oam_size]{};
+ u8 vram_[vram_size]{};
+ u8 oam_[oam_size]{};
color palette_buffer_[palette_buffer_size]
{
color{ 0x09 }, color{ 0x01 }, color{ 0x00 }, color{ 0x01 },
@@ -131,7 +132,7 @@ namespace nes::sys
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.
+ u8 latch_{}; // The last read/written IO register value, returned when reading write-only registers.
struct
{
BITFIELD_FLAG(sprite_overflow, value, 0b00100000, 5)
@@ -139,9 +140,9 @@ namespace nes::sys
BITFIELD_FLAG(vblank, value, 0b10000000, 7)
// Set the remaining (unused) bits based on the given value.
- auto set_remaining(std::uint8_t const v) -> void { value = (value & ~0b00011111) | (v & 0b00011111); }
+ auto set_remaining(u8 const v) -> void { value = (value & ~0b00011111) | (v & 0b00011111); }
- std::uint8_t value{ 0b00000000 };
+ u8 value{ 0b00000000 };
} status_{};
struct
{
@@ -160,7 +161,7 @@ namespace nes::sys
// Enable/disable vblank NMI.
BITFIELD_FLAG(vblank_nmi, value, 0b10000000, 7)
- std::uint8_t value{ 0b00000000 };
+ u8 value{ 0b00000000 };
} control_{};
struct
{
@@ -181,7 +182,7 @@ namespace nes::sys
// Emphasize blue.
BITFIELD_FLAG(emphasize_blue, value, 0b10000000, 7)
- std::uint8_t value{ 0b00000000 };
+ u8 value{ 0b00000000 };
} mask_{};
struct
{
@@ -201,15 +202,15 @@ namespace nes::sys
BITFIELD_VALUE(address_low, value, 0b0000000011111111, 0)
BITFIELD_VALUE(address_high, value, 0b0111111100000000, 8)
- std::uint16_t value{};
+ u16 value{};
} v{}, t{}; // Current and temporary VRAM address and scroll position (15 bits)
- std::uint8_t x{}; // Fine X scroll (3 bits)
+ u8 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.
- unsigned scanline_{ 240 };
- unsigned scanline_cycle_{ 340 };
+ u8 oamaddr_{}; // Address accessed by IO registers
+ u8 ppudata_read_buffer_{}; // Delays PPUDATA reads by one.
+ u32 scanline_{ 240 };
+ u32 scanline_cycle_{ 340 };
bool even_frame_{ true };
tile_row current_background_{};
tile_row next_background_{};
@@ -217,11 +218,11 @@ namespace nes::sys
{
tile tile{ 0 };
palette palette{ 0 };
- std::uint8_t bitplane_0{ 0 };
- std::uint8_t bitplane_1{ 0 };
+ u8 bitplane_0{ 0 };
+ u8 bitplane_1{ 0 };
} fetch_cycle_{}; // Data populated during the fetch cycle.
evaluated_sprite sprites_[8]{}; // Evaluated sprites.
- unsigned sprite_count_{ 0 }; // Number of evaluated sprites in sprites_.
+ u32 sprite_count_{ 0 }; // Number of evaluated sprites in sprites_.
#undef BITFIELD_VALIDATE
#undef BITFIELD_VALUE
@@ -242,30 +243,30 @@ namespace nes::sys
// Memory access
- auto read8(address) -> std::uint8_t;
- auto write8(address, std::uint8_t) -> void;
+ auto read8(address) -> u8;
+ auto write8(address, u8) -> 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 read_latch() -> u8;
+ auto read_ppustatus() -> u8;
+ auto read_oamdata() -> u8;
+ auto read_ppudata() -> u8;
- 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;
+ auto write_latch(u8) -> void;
+ auto write_ppuctrl(u8) -> void;
+ auto write_ppuscroll(u8) -> void;
+ auto write_ppumask(u8) -> void;
+ auto write_ppuaddr(u8) -> void;
+ auto write_ppudata(u8) -> void;
+ auto write_oamaddr(u8) -> void;
+ auto write_oamdata(u8) -> void;
+ auto write_oamdma(u8) -> void;
private:
auto render_pixel() -> void;
auto evaluate_sprites() -> void;
- auto fetch_sprite_pattern(sprite, unsigned row) -> tile_row;
+ auto fetch_sprite_pattern(sprite, u32 row) -> tile_row;
// Helpers
@@ -274,9 +275,9 @@ namespace nes::sys
auto increment_y() -> void;
auto copy_x() -> void;
auto copy_y() -> void;
- auto get_sprite_height() const -> unsigned;
- 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 get_sprite_height() const -> u32;
+ auto get_tile_bitplane(pattern_table, tile, u32 row, bitplane) -> u8;
+ auto get_tile_row(palette, u8 bitplane_0, u8 bitplane_1) const -> tile_row;
auto ref_color(color_index) -> color&;
auto resolve_color(color) const -> rgb;
};
diff --git a/lib/nes/sys/types/address.hh b/lib/nes/sys/types/address.hh
index dde9c94..d8b857b 100644
--- a/lib/nes/sys/types/address.hh
+++ b/lib/nes/sys/types/address.hh
@@ -1,6 +1,6 @@
#pragma once
-#include <cstdint>
+#include "nes/common/types.hh"
namespace nes::sys
{
@@ -8,40 +8,40 @@ namespace nes::sys
/// 14 bit addresses).
class address
{
- std::uint16_t absolute_{ 0 };
+ u16 absolute_{ 0 };
public:
/// Create a zero address.
constexpr explicit address() = default;
/// Create an address from its absolute value.
- constexpr explicit address(std::uint16_t const absolute)
+ constexpr explicit address(u16 const absolute)
: absolute_{ absolute }
{
}
/// Create an address from its page and offset combination.
- constexpr explicit address(std::uint8_t const page, std::uint8_t const offset)
- : address{ static_cast<std::uint16_t>((page << 8) | (offset << 0)) }
+ constexpr explicit address(u8 const page, u8 const offset)
+ : address{ static_cast<u16>((page << 8) | (offset << 0)) }
{
}
/// Get the absolute address value.
- constexpr auto get_absolute() const -> std::uint16_t
+ constexpr auto get_absolute() const -> u16
{
return absolute_;
}
/// Get the address page (the first 8 bits).
- constexpr auto get_page() const -> std::uint8_t
+ constexpr auto get_page() const -> u8
{
- return static_cast<std::uint8_t>((get_absolute() & 0xFF00) >> 8);
+ return static_cast<u8>((get_absolute() & 0xFF00) >> 8);
}
/// Get the offset within the page (the last 8 bits).
- constexpr auto get_offset() const -> std::uint8_t
+ constexpr auto get_offset() const -> u8
{
- return static_cast<std::uint8_t>((get_absolute() & 0x00FF) >> 0);
+ return static_cast<u8>((get_absolute() & 0x00FF) >> 0);
}
};
@@ -52,23 +52,23 @@ namespace nes::sys
constexpr auto operator<=(address const a, address const b) -> bool { return a.get_absolute() <= b.get_absolute(); }
constexpr auto operator>=(address const a, address const b) -> bool { return a.get_absolute() >= b.get_absolute(); }
- constexpr auto operator+(address const a, unsigned const b) -> address
+ constexpr auto operator+(address const a, u32 const b) -> address
{
- return address{ static_cast<std::uint16_t>(a.get_absolute() + b) };
+ return address{ static_cast<u16>(a.get_absolute() + b) };
}
- constexpr auto operator+(unsigned const a, address const b) -> address
+ constexpr auto operator+(u32 const a, address const b) -> address
{
- return address{ static_cast<std::uint16_t>(a + b.get_absolute()) };
+ return address{ static_cast<u16>(a + b.get_absolute()) };
}
- constexpr auto operator-(address const a, unsigned const b) -> address
+ constexpr auto operator-(address const a, u32 const b) -> address
{
- return address{ static_cast<std::uint16_t>(a.get_absolute() - b) };
+ return address{ static_cast<u16>(a.get_absolute() - b) };
}
- constexpr auto operator%(address const a, unsigned const b) -> address
+ constexpr auto operator%(address const a, u32 const b) -> address
{
- return address{ static_cast<std::uint16_t>(a.get_absolute() % b) };
+ return address{ static_cast<u16>(a.get_absolute() % b) };
}
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/types/button-mask.hh b/lib/nes/sys/types/button-mask.hh
index 64be0b6..4a44530 100644
--- a/lib/nes/sys/types/button-mask.hh
+++ b/lib/nes/sys/types/button-mask.hh
@@ -1,18 +1,18 @@
#pragma once
-#include <cstdint>
+#include "nes/common/types.hh"
namespace nes::sys
{
/// Buttons pressed on a controller.
class button_mask
{
- std::uint8_t raw_value_{ 0 };
+ u8 raw_value_{ 0 };
public:
constexpr explicit button_mask() = default;
- static constexpr auto from_raw_value(std::uint8_t const raw_value) -> button_mask
+ static constexpr auto from_raw_value(u8 const raw_value) -> button_mask
{
return button_mask{ raw_value };
}
@@ -21,10 +21,10 @@ namespace nes::sys
constexpr auto remove(button_mask const other) -> void { raw_value_ ^= other.raw_value_; }
constexpr auto contains(button_mask const other) const -> bool { return (raw_value_ & other.raw_value_) == other.raw_value_; }
constexpr auto is_empty() const -> bool { return raw_value_ == 0; }
- constexpr auto get_raw_value() const -> std::uint8_t { return raw_value_; }
+ constexpr auto get_raw_value() const -> u8 { return raw_value_; }
private:
- constexpr explicit button_mask(std::uint8_t const raw_value)
+ constexpr explicit button_mask(u8 const raw_value)
: raw_value_{ raw_value }
{
}
diff --git a/lib/nes/sys/types/cycle-count.hh b/lib/nes/sys/types/cycle-count.hh
index 95ce9e5..c977d1d 100644
--- a/lib/nes/sys/types/cycle-count.hh
+++ b/lib/nes/sys/types/cycle-count.hh
@@ -1,5 +1,6 @@
#pragma once
+#include "nes/common/types.hh"
#include <chrono>
namespace nes::sys
@@ -12,11 +13,11 @@ namespace nes::sys
{
friend constexpr auto operator+(cycle_count, cycle_count) -> cycle_count;
friend constexpr auto operator-(cycle_count, cycle_count) -> cycle_count;
- friend constexpr auto operator*(std::uint64_t, cycle_count) -> cycle_count;
- friend constexpr auto operator*(cycle_count, std::uint64_t) -> cycle_count;
- friend constexpr auto operator/(cycle_count, cycle_count) -> std::uint64_t;
+ friend constexpr auto operator*(u64, cycle_count) -> cycle_count;
+ friend constexpr auto operator*(cycle_count, u64) -> cycle_count;
+ friend constexpr auto operator/(cycle_count, cycle_count) -> u64;
- std::uint64_t units_{ 0 }; // The most fine-granular cycle count (here: PPU cycles).
+ u64 units_{ 0 }; // The most fine-granular cycle count (here: PPU cycles).
static constexpr auto ppu_cycle() -> cycle_count { return cycle_count{ 1 }; }
static constexpr auto cpu_cycle() -> cycle_count { return cycle_count{ 3 }; }
@@ -26,48 +27,48 @@ namespace nes::sys
constexpr explicit cycle_count() = default;
constexpr auto operator+=(cycle_count const other) -> cycle_count& { return *this = *this + other; }
- constexpr auto operator*=(std::uint64_t const other) -> cycle_count& { return *this = *this * other; }
+ constexpr auto operator*=(u64 const other) -> cycle_count& { return *this = *this * other; }
- static constexpr auto from_units(std::uint64_t const units) -> cycle_count
+ static constexpr auto from_units(u64 const units) -> cycle_count
{
return cycle_count{ units };
}
static constexpr auto from_duration(std::chrono::microseconds const duration) -> cycle_count
{
- return from_units(static_cast<std::uint64_t>(duration.count()) * second().get_units() / (1000 * 1000));
+ return from_units(static_cast<u64>(duration.count()) * second().get_units() / (1000 * 1000));
}
- static constexpr auto from_cpu(std::uint64_t const cpu_cycles) -> cycle_count
+ static constexpr auto from_cpu(u64 const cpu_cycles) -> cycle_count
{
return cpu_cycles * cpu_cycle();
}
- static constexpr auto from_ppu(std::uint64_t const ppu_cycles) -> cycle_count
+ static constexpr auto from_ppu(u64 const ppu_cycles) -> cycle_count
{
return ppu_cycles * ppu_cycle();
}
/// Value in implementation-defined units.
- constexpr auto get_units() const -> std::uint64_t { return units_; }
+ constexpr auto get_units() const -> u64 { return units_; }
constexpr auto to_duration() const -> std::chrono::microseconds
{
return std::chrono::microseconds{ get_units() * 1000 * 1000 / second().get_units() };
}
- constexpr auto to_cpu() const -> std::uint64_t
+ constexpr auto to_cpu() const -> u64
{
return *this / cpu_cycle();
}
- constexpr auto to_ppu() const -> std::uint64_t
+ constexpr auto to_ppu() const -> u64
{
return *this / ppu_cycle();
}
private:
- constexpr explicit cycle_count(std::uint64_t const units)
+ constexpr explicit cycle_count(u64 const units)
: units_{ units }
{
}
@@ -81,7 +82,7 @@ namespace nes::sys
constexpr auto operator>=(cycle_count const a, cycle_count const b) -> bool { return a.get_units() >= b.get_units(); }
constexpr auto operator+(cycle_count const a, cycle_count const b) -> cycle_count { return cycle_count{ a.get_units() + b.get_units() }; }
constexpr auto operator-(cycle_count const a, cycle_count const b) -> cycle_count { return cycle_count{ a.get_units() - b.get_units() }; }
- constexpr auto operator*(std::uint64_t const a, cycle_count const b) -> cycle_count { return cycle_count{ a * b.get_units() }; }
- constexpr auto operator*(cycle_count const a, std::uint64_t const b) -> cycle_count { return cycle_count{ a.get_units() * b }; }
- constexpr auto operator/(cycle_count const a, cycle_count const b) -> std::uint64_t { return a.get_units() / b.get_units(); }
+ constexpr auto operator*(u64 const a, cycle_count const b) -> cycle_count { return cycle_count{ a * b.get_units() }; }
+ constexpr auto operator*(cycle_count const a, u64 const b) -> cycle_count { return cycle_count{ a.get_units() * b }; }
+ constexpr auto operator/(cycle_count const a, cycle_count const b) -> u64 { return a.get_units() / b.get_units(); }
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/types/snapshot.hh b/lib/nes/sys/types/snapshot.hh
index 3b1b3b4..c057aeb 100644
--- a/lib/nes/sys/types/snapshot.hh
+++ b/lib/nes/sys/types/snapshot.hh
@@ -1,8 +1,8 @@
#pragma once
#include "nes/sys/types/cycle-count.hh"
+#include "nes/common/types.hh"
#include <vector>
-#include <cstdint>
namespace nes::sys
{
@@ -13,18 +13,18 @@ namespace nes::sys
cycle_count cpu_cycle;
cycle_count ppu_cycle;
- std::vector<std::uint8_t> ram;
- std::vector<std::uint8_t> sram;
- std::vector<std::uint8_t> vram;
- std::vector<std::uint8_t> oam;
+ std::vector<u8> ram;
+ std::vector<u8> sram;
+ std::vector<u8> vram;
+ std::vector<u8> oam;
struct
{
- std::uint16_t pc{};
- std::uint8_t sp{};
- std::uint8_t a{};
- std::uint8_t x{};
- std::uint8_t y{};
- std::uint8_t p{};
+ u16 pc{};
+ u8 sp{};
+ u8 a{};
+ u8 x{};
+ u8 y{};
+ u8 p{};
bool c{};
bool z{};
bool i{};