From 9ca793417149cbaa7b5f4b7797bc929e6e191f28 Mon Sep 17 00:00:00 2001 From: Hannes Schulze Date: Sat, 1 Feb 2025 01:14:03 +0100 Subject: use custom integer types --- app/mac/scene.mm | 14 ++-- lib/nes/app/application.hh | 5 +- lib/nes/app/graphics/color.hh | 4 +- lib/nes/app/graphics/image-view.hh | 14 ++-- lib/nes/app/graphics/mask-tile.hh | 4 +- lib/nes/app/graphics/renderer.cc | 24 +++---- lib/nes/app/graphics/renderer.hh | 24 +++---- lib/nes/app/input/input-manager.cc | 4 +- lib/nes/app/input/input-manager.hh | 3 +- lib/nes/common/CMakeLists.txt | 1 + lib/nes/common/box.hh | 4 +- lib/nes/common/display.hh | 9 +-- lib/nes/common/rgb.hh | 12 ++-- lib/nes/common/types.hh | 26 +++++++ lib/nes/sys/cartridge.cc | 32 +++++---- lib/nes/sys/cartridge.hh | 66 ++++++++++-------- lib/nes/sys/controller.cc | 6 +- lib/nes/sys/controller.hh | 7 +- lib/nes/sys/cpu.cc | 88 ++++++++++++------------ lib/nes/sys/cpu.hh | 71 +++++++++---------- lib/nes/sys/mapper.cc | 20 +++--- lib/nes/sys/mapper.hh | 11 +-- lib/nes/sys/nes.cc | 4 +- lib/nes/sys/nes.hh | 3 +- lib/nes/sys/ppu.cc | 70 +++++++++---------- lib/nes/sys/ppu.hh | 137 +++++++++++++++++++------------------ lib/nes/sys/types/address.hh | 36 +++++----- lib/nes/sys/types/button-mask.hh | 10 +-- lib/nes/sys/types/cycle-count.hh | 33 ++++----- lib/nes/sys/types/snapshot.hh | 22 +++--- 30 files changed, 406 insertions(+), 358 deletions(-) create mode 100644 lib/nes/common/types.hh diff --git a/app/mac/scene.mm b/app/mac/scene.mm index aced63b..247a097 100644 --- a/app/mac/scene.mm +++ b/app/mac/scene.mm @@ -13,14 +13,14 @@ namespace SKSpriteNode* node_; NSMutableData* buffer_front_; NSMutableData* buffer_back_; - std::uint8_t* bytes_back_; + nes::u8* bytes_back_; public: explicit display_impl(SKSpriteNode* node) : node_{ node } , buffer_front_{ make_buffer() } , buffer_back_{ make_buffer() } - , bytes_back_{ static_cast([buffer_back_ mutableBytes]) } + , bytes_back_{ static_cast([buffer_back_ mutableBytes]) } { } @@ -31,14 +31,14 @@ namespace auto tmp = buffer_back_; buffer_back_ = buffer_front_; buffer_front_ = tmp; - bytes_back_ = static_cast([buffer_back_ mutableBytes]); + bytes_back_ = static_cast([buffer_back_ mutableBytes]); auto texture = [SKTexture textureWithData:buffer_front_ size:CGSizeMake(width, height) flipped:YES]; [texture setFilteringMode:SKTextureFilteringNearest]; [node_ setTexture:texture]; } - virtual auto set(unsigned x, unsigned y, nes::rgb value) -> void override + virtual auto set(nes::u32 x, nes::u32 y, nes::rgb value) -> void override { auto const offset = (y * width + x) * 4; bytes_back_[offset + 0] = value.r; @@ -47,7 +47,7 @@ namespace bytes_back_[offset + 3] = 255; } - virtual auto get(unsigned x, unsigned y) const -> nes::rgb override + virtual auto get(nes::u32 x, nes::u32 y) const -> nes::rgb override { auto const offset = (y * width + x) * 4; auto res = nes::rgb{}; @@ -216,8 +216,8 @@ namespace { auto const lastTimestamp = _lastTimestamp.value_or(currentTime); _lastTimestamp = currentTime; - auto deltaMicroseconds = static_cast((currentTime - lastTimestamp) * 1000. * 1000.); - deltaMicroseconds = std::min(deltaMicroseconds, std::uint64_t{ 50000 }); + auto deltaMicroseconds = static_cast((currentTime - lastTimestamp) * 1000. * 1000.); + deltaMicroseconds = std::min(deltaMicroseconds, nes::u64{ 50000 }); _app->frame(std::chrono::microseconds{ deltaMicroseconds }); } 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 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 +#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 +#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 -#include 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(index); + auto const i = static_cast(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 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 +#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 +#include 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(data); + auto const bytes = static_cast(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((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0)); + auto const mapper_number = static_cast((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(static_cast(length)); + auto data = std::vector(static_cast(length)); stream.read(reinterpret_cast(data.data()), length); - return from_data(data.data(), data.size()); + return from_data(data.data(), static_cast(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 +#include "nes/common/types.hh" #include #include @@ -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((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 prg_rom_; - std::vector chr_rom_; - std::vector 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(res); + return static_cast(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(); auto const old_val = operand.read(); - auto const new_val = static_cast(old_val >> 1); + auto const new_val = static_cast(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(); - auto const result = static_cast(registers_.a & registers_.x); + auto const result = static_cast(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(force_page_crossing::yes); - auto const tmp = static_cast(operand.read() - 1); + auto const tmp = static_cast(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(); auto const old_val = read8(operand.get_address()); - auto const new_val = static_cast(old_val - 1); + auto const new_val = static_cast(old_val - 1); write8(operand.get_address(), new_val); update_zn(new_val); current_cycles_ += inc_dec_cycle_count(); @@ -1000,7 +1000,7 @@ namespace nes::sys { // ISC: INC + SBC auto operand = fetch_operand(force_page_crossing::yes); - auto const tmp = static_cast(operand.read() + 1); + auto const tmp = static_cast(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(); auto const old_val = read8(operand.get_address()); - auto const new_val = static_cast(old_val + 1); + auto const new_val = static_cast(old_val + 1); write8(operand.get_address(), new_val); update_zn(new_val); current_cycles_ += inc_dec_cycle_count(); @@ -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(value >> 0 & 0xFF); - auto const high = static_cast(value >> 8 & 0xFF); + auto const low = static_cast(value >> 0 & 0xFF); + auto const high = static_cast(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((high << 8) | (low << 0)); + return static_cast((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(((registers_.p.get_c() ? 1 :0) << 7) | (arg >> 1)); + auto const res = static_cast(((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((arg << 1) | (registers_.p.get_c() ? 1 : 0)); + auto const res = static_cast((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(arg << 1); + auto const new_val = static_cast(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(arg >> 1); + auto const new_val = static_cast(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(tmp); + auto const new_val = static_cast(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(advance_pc8()); auto const base = address{ registers_.pc }; - addr = address{ static_cast(registers_.pc + offset) }; + addr = address{ static_cast(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(advance_pc8() + registers_.x) }; + addr = address{ 0x00, static_cast(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(advance_pc8() + registers_.y) }; + addr = address{ 0x00, static_cast(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(arg + registers_.x + 1) }); - auto const offset = read8(address{ 0x00, static_cast(arg + registers_.x) }); + auto const page = read8(address{ 0x00, static_cast(arg + registers_.x + 1) }); + auto const offset = read8(address{ 0x00, static_cast(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(arg + 1) }); - auto const offset = read8(address{ 0x00, static_cast(arg) }); + auto const page = read8(address{ 0x00, static_cast(arg + 1) }); + auto const offset = read8(address{ 0x00, static_cast(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((high << 8) | (low << 0)); + return static_cast((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(value >> 0 & 0xFF); - auto const high = static_cast(value >> 8 & 0xFF); + auto const low = static_cast(value >> 0 & 0xFF); + auto const high = static_cast(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 { - 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 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(internal_.v.get_name_table()) * 0x400u) + + (static_cast(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(x) - static_cast(s.x); - if (offset < 0 || static_cast(offset) >= tile_size) { continue; } + if (offset < 0 || static_cast(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(scanline_) - static_cast(s.get_y()); - if (row < 0 || static_cast(row) >= height) { continue; } + if (row < 0 || static_cast(row) >= height) { continue; } if (sprite_count_ < 8) { - sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast(row)); + sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast(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(addr.get_absolute() % 0x20) }; + auto const index = color_index{ static_cast(addr.get_absolute() % 0x20) }; auto const color = ref_color(index); - return static_cast(color); + return static_cast(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(addr.get_absolute() % 0x20) }; + auto const index = color_index{ static_cast(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( - 0x1000 * static_cast(pattern_table) + 0x10 * static_cast(tile) + row); - return read8(address{ addr } + (static_cast(bitplane) * 8u)); + auto const addr = static_cast( + 0x1000 * static_cast(pattern_table) + 0x10 * static_cast(tile) + row); + return read8(address{ addr } + (static_cast(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(color); + auto const index = static_cast(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((base & mask) >> offset_from_right); } \ - auto set_##name(type const v) -> void { base = (base & ~mask) | ((static_cast(v) << offset_from_right) & mask); } + auto set_##name(type const v) -> void { base = (base & ~mask) | ((static_cast(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 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 read_latch() -> u8; + auto read_ppustatus() -> u8; + auto read_oamdata() -> u8; + auto read_ppudata() -> u8; + + 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 +#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((page << 8) | (offset << 0)) } + constexpr explicit address(u8 const page, u8 const offset) + : address{ static_cast((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((get_absolute() & 0xFF00) >> 8); + return static_cast((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((get_absolute() & 0x00FF) >> 0); + return static_cast((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(a.get_absolute() + b) }; + return address{ static_cast(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(a + b.get_absolute()) }; + return address{ static_cast(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(a.get_absolute() - b) }; + return address{ static_cast(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(a.get_absolute() % b) }; + return address{ static_cast(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 +#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 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(duration.count()) * second().get_units() / (1000 * 1000)); + return from_units(static_cast(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 -#include namespace nes::sys { @@ -13,18 +13,18 @@ namespace nes::sys cycle_count cpu_cycle; cycle_count ppu_cycle; - std::vector ram; - std::vector sram; - std::vector vram; - std::vector oam; + std::vector ram; + std::vector sram; + std::vector vram; + std::vector 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{}; -- cgit v1.3.1