summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--app/mac/impl/display-spritekit.mm4
-rw-r--r--app/mac/impl/file-browser-posix.cc14
-rw-r--r--app/mac/impl/file-browser-posix.hh6
-rw-r--r--app/mac/impl/input-device-gc-gamepad.hh2
-rw-r--r--app/mac/impl/input-device-gc-gamepad.mm2
-rw-r--r--app/mac/impl/input-device-serial-controller.hh2
-rw-r--r--app/mac/scene.mm7
-rw-r--r--lib/CMakeLists.txt3
-rw-r--r--lib/nes/app/action.hh16
-rw-r--r--lib/nes/app/application.cc8
-rw-r--r--lib/nes/app/application.hh5
-rw-r--r--lib/nes/app/file-browser.hh13
-rw-r--r--lib/nes/app/graphics/renderer.cc37
-rw-r--r--lib/nes/app/graphics/renderer.hh8
-rw-r--r--lib/nes/app/input/input-device-keyboard.hh2
-rw-r--r--lib/nes/app/input/input-device.hh4
-rw-r--r--lib/nes/app/input/input-manager.cc2
-rw-r--r--lib/nes/app/ui/screen-browser.cc3
-rw-r--r--lib/nes/app/ui/screen-error.hh7
-rw-r--r--lib/nes/app/ui/screen-settings.cc2
-rw-r--r--lib/nes/common/CMakeLists.txt3
-rw-r--r--lib/nes/common/containers/CMakeLists.txt4
-rw-r--r--lib/nes/common/containers/box.hh8
-rw-r--r--lib/nes/common/containers/path-builder.cc12
-rw-r--r--lib/nes/common/containers/path-builder.hh11
-rw-r--r--lib/nes/common/containers/path-view.cc8
-rw-r--r--lib/nes/common/containers/path-view.hh10
-rw-r--r--lib/nes/common/containers/string-builder.cc18
-rw-r--r--lib/nes/common/containers/string-builder.hh23
-rw-r--r--lib/nes/common/containers/string-view.cc81
-rw-r--r--lib/nes/common/containers/string-view.hh40
-rw-r--r--lib/nes/common/fps-counter.cc7
-rw-r--r--lib/nes/common/fps-counter.hh3
-rw-r--r--lib/nes/common/utils.hh38
-rw-r--r--lib/nes/sys/cartridge.cc8
-rw-r--r--lib/nes/sys/cpu.cc4
-rw-r--r--lib/nes/sys/cpu.hh4
-rw-r--r--lib/nes/sys/nes.cc8
-rw-r--r--lib/nes/sys/nes.hh6
-rw-r--r--lib/nes/sys/ppu.cc7
-rw-r--r--lib/nes/sys/ppu.hh4
-rw-r--r--lib/nes/sys/types/cycle-count.hh9
-rw-r--r--lib/nes/sys/types/snapshot.hh6
44 files changed, 325 insertions, 145 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1aa3a60..101c1bd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,7 @@ project(
option(NES_ENABLE_SANITIZER_ADDRESS "Enable address sanitizer." OFF)
option(NES_ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer." OFF)
option(NES_ENABLE_DEBUG_OUTPUT "Enable debug output." OFF)
+option(NES_ENABLE_SNAPSHOTS "Enable snapshot functionality for debugging purposes." OFF)
option(NES_ENABLE_PPU "Enable Picture Processing Unit." ON)
add_library(nes_options INTERFACE)
diff --git a/app/mac/impl/display-spritekit.mm b/app/mac/impl/display-spritekit.mm
index a5809c3..b949f85 100644
--- a/app/mac/impl/display-spritekit.mm
+++ b/app/mac/impl/display-spritekit.mm
@@ -22,8 +22,8 @@ namespace nes::app::mac
auto display_spritekit::switch_buffers() -> void
{
- std::swap(buffer_back_, buffer_front_);
- std::swap(bytes_back_, bytes_front_);
+ swap(buffer_back_, buffer_front_);
+ swap(bytes_back_, bytes_front_);
auto texture = [SKTexture textureWithData:buffer_front_ size:CGSizeMake(width, height) flipped:YES];
[texture setFilteringMode:SKTextureFilteringNearest];
diff --git a/app/mac/impl/file-browser-posix.cc b/app/mac/impl/file-browser-posix.cc
index 500ce83..d17b97c 100644
--- a/app/mac/impl/file-browser-posix.cc
+++ b/app/mac/impl/file-browser-posix.cc
@@ -53,8 +53,8 @@ namespace nes::app::mac
return false;
}
- auto const name = std::string_view{ ent->d_name };
- if (name.length() > max_name_length) { continue; }
+ auto const name = string_view{ ent->d_name };
+ if (name.get_length() > max_name_length) { continue; }
if (name[0] == '.') { continue; }
auto type = entry_type{};
@@ -77,7 +77,7 @@ namespace nes::app::mac
return status::success;
}
- auto file_browser_posix::navigate(std::string_view const item) -> status
+ auto file_browser_posix::navigate(string_view const item) -> status
{
auto new_path = path_;
if (auto const s = new_path.push(item); s != status::success) { return s; }
@@ -86,12 +86,12 @@ namespace nes::app::mac
return status::success;
}
- auto file_browser_posix::load(std::string_view const item, span<u8> const buffer, u32* out_length) -> status
+ auto file_browser_posix::load(string_view const item, span<u8> const buffer, u32* out_length) -> status
{
auto file_path = path_;
if (auto const s = file_path.push(item); s != status::success) { return s; }
- auto const file_path_str = std::string{ file_path.get_path() };
+ auto const file_path_str = std::string{ file_path.get_path().get_data(), file_path.get_path().get_length() };
auto const fd = open(file_path_str.c_str(), O_RDONLY);
if (fd == -1)
{
@@ -121,9 +121,9 @@ namespace nes::app::mac
return status::success;
}
- auto file_browser_posix::reopen_directory(std::string_view const path) -> status
+ auto file_browser_posix::reopen_directory(string_view const path) -> status
{
- auto const path_str = std::string{ path };
+ auto const path_str = std::string{ path.get_data(), path.get_length() };
auto const new_it = opendir(path_str.c_str());
if (!new_it)
{
diff --git a/app/mac/impl/file-browser-posix.hh b/app/mac/impl/file-browser-posix.hh
index b60ce2b..1179c96 100644
--- a/app/mac/impl/file-browser-posix.hh
+++ b/app/mac/impl/file-browser-posix.hh
@@ -21,10 +21,10 @@ namespace nes::app::mac
auto seek(u32) -> void override;
auto read_next(entry* out_entry) -> bool override;
auto navigate_up() -> status override;
- auto navigate(std::string_view) -> status override;
- auto load(std::string_view, span<u8>, u32* out_length) -> status override;
+ auto navigate(string_view) -> status override;
+ auto load(string_view, span<u8>, u32* out_length) -> status override;
private:
- auto reopen_directory(std::string_view path) -> status;
+ auto reopen_directory(string_view path) -> status;
};
} // namespace nes::app::mac \ No newline at end of file
diff --git a/app/mac/impl/input-device-gc-gamepad.hh b/app/mac/impl/input-device-gc-gamepad.hh
index b4b4a4e..04085f3 100644
--- a/app/mac/impl/input-device-gc-gamepad.hh
+++ b/app/mac/impl/input-device-gc-gamepad.hh
@@ -16,7 +16,7 @@ namespace nes::app::mac
auto is_reliable() const -> bool override { return true; }
auto get_controller() const -> GCController* { return [profile_ controller]; }
- auto get_name() const -> std::string_view override;
+ auto get_name() const -> string_view override;
auto get_index() const -> index override;
auto set_index(index) -> void override;
auto read_buttons() -> sys::button_mask override;
diff --git a/app/mac/impl/input-device-gc-gamepad.mm b/app/mac/impl/input-device-gc-gamepad.mm
index d2f84ec..5d19120 100644
--- a/app/mac/impl/input-device-gc-gamepad.mm
+++ b/app/mac/impl/input-device-gc-gamepad.mm
@@ -7,7 +7,7 @@ namespace nes::app::mac
{
}
- auto input_device_gc_gamepad::get_name() const -> std::string_view
+ auto input_device_gc_gamepad::get_name() const -> string_view
{
return [[get_controller() vendorName] UTF8String];
}
diff --git a/app/mac/impl/input-device-serial-controller.hh b/app/mac/impl/input-device-serial-controller.hh
index 2022ed2..eb58907 100644
--- a/app/mac/impl/input-device-serial-controller.hh
+++ b/app/mac/impl/input-device-serial-controller.hh
@@ -17,7 +17,7 @@ namespace nes::app::mac
~input_device_serial_controller() override;
auto is_reliable() const -> bool override;
- auto get_name() const -> std::string_view override { return path_; }
+ auto get_name() const -> string_view override { return path_; }
auto get_index() const -> index override { return index_; }
auto set_index(index const v) -> void override { index_ = v; }
auto read_buttons() -> sys::button_mask override;
diff --git a/app/mac/scene.mm b/app/mac/scene.mm
index 0ff5122..0cfc2ac 100644
--- a/app/mac/scene.mm
+++ b/app/mac/scene.mm
@@ -5,6 +5,7 @@
#import "impl/input-device-gc-gamepad.hh"
#import "impl/input-device-serial-controller.hh"
#import "nes/app/application.hh"
+#import <vector>
#import <memory>
#import <optional>
@@ -90,9 +91,9 @@ namespace
{
auto const lastTimestamp = _lastTimestamp.value_or(currentTime);
_lastTimestamp = currentTime;
- auto deltaMicroseconds = static_cast<nes::u64>((currentTime - lastTimestamp) * 1000. * 1000.);
- deltaMicroseconds = std::min(deltaMicroseconds, nes::u64{ 50000 });
- _app->frame(std::chrono::microseconds{ deltaMicroseconds });
+ auto deltaMicroseconds = static_cast<nes::u32>((currentTime - lastTimestamp) * 1000. * 1000.);
+ deltaMicroseconds = nes::min(deltaMicroseconds, nes::u32{ 50000 });
+ _app->frame(deltaMicroseconds);
}
- (void)handleKeyboardConnected:(NSNotification*)notification
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 7dc5b9d..ce78076 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -11,5 +11,8 @@ if(NES_ENABLE_DEBUG_OUTPUT)
target_compile_definitions(nes PUBLIC NES_ENABLE_DEBUG_OUTPUT)
target_link_libraries(nes PUBLIC spdlog::spdlog)
endif()
+if(NES_ENABLE_SNAPSHOTS)
+ target_compile_definitions(nes PUBLIC NES_ENABLE_SNAPSHOTS)
+endif()
add_subdirectory(nes) \ No newline at end of file
diff --git a/lib/nes/app/action.hh b/lib/nes/app/action.hh
index cca7a35..ed879f3 100644
--- a/lib/nes/app/action.hh
+++ b/lib/nes/app/action.hh
@@ -1,7 +1,7 @@
#pragma once
-#include "../common/status.hh"
-#include <string_view>
+#include "nes/common/containers/string-view.hh"
+#include "nes/common/status.hh"
namespace nes::app
{
@@ -25,8 +25,8 @@ namespace nes::app
private:
type type_{ type::none };
- std::string_view file_name_;
- std::string_view message_;
+ string_view file_name_;
+ string_view message_;
status error_{ status::success };
public:
@@ -40,14 +40,14 @@ namespace nes::app
static auto cancel_quit() -> action { return action{ type::cancel_quit }; }
static auto confirm_quit() -> action { return action{ type::confirm_quit }; }
- static auto launch_game(std::string_view const file_name) -> action
+ static auto launch_game(string_view const file_name) -> action
{
auto res = action{ type::launch_game };
res.file_name_ = file_name;
return res;
}
- static auto show_error(std::string_view const message, status const error) -> action
+ static auto show_error(string_view const message, status const error) -> action
{
auto res = action{ type::show_error };
res.message_ = message;
@@ -56,8 +56,8 @@ namespace nes::app
}
auto get_type() const -> type { return type_; }
- auto get_file_name() const -> std::string_view { return file_name_; }
- auto get_message() const -> std::string_view { return message_; }
+ auto get_file_name() const -> string_view { return file_name_; }
+ auto get_message() const -> string_view { return message_; }
auto get_error() const -> status { return error_; }
private:
diff --git a/lib/nes/app/application.cc b/lib/nes/app/application.cc
index 015e641..ac9f731 100644
--- a/lib/nes/app/application.cc
+++ b/lib/nes/app/application.cc
@@ -46,9 +46,9 @@ namespace nes::app
display_.screen = &screen_title_;
}
- auto application::frame(std::chrono::microseconds const elapsed_time) -> void
+ auto application::frame(u32 const elapsed_time_us) -> void
{
- display_.fps_counter.frame(elapsed_time);
+ display_.fps_counter.frame(elapsed_time_us);
if (display_.popup)
{
@@ -89,7 +89,7 @@ namespace nes::app
// The scene is rendered by the console after the PPU requests a new frame (thus calling
// display_proxy::switch_buffers).
- console_->step(elapsed_time);
+ console_->step(sys::cycle_count::from_microseconds(elapsed_time_us));
if (console_->get_status() != status::success)
{
@@ -171,7 +171,7 @@ namespace nes::app
}
}
- auto application::show_error(std::string_view const message, status const error, action const& action) -> void
+ auto application::show_error(string_view const message, status const error, action const& action) -> void
{
screen_error_.set_message(message);
screen_error_.set_error(error);
diff --git a/lib/nes/app/application.hh b/lib/nes/app/application.hh
index c23f654..f0117b1 100644
--- a/lib/nes/app/application.hh
+++ b/lib/nes/app/application.hh
@@ -13,7 +13,6 @@
#include "nes/common/display.hh"
#include "nes/common/fps-counter.hh"
#include "nes/common/types.hh"
-#include <chrono>
namespace nes::app
{
@@ -71,14 +70,14 @@ namespace nes::app
auto operator=(application&&) -> application& = delete;
/// Request a new frame for the application.
- auto frame(std::chrono::microseconds elapsed_time) -> void;
+ auto frame(u32 elapsed_time_us) -> void;
auto add_controller(input_device_controller& c) -> void { input_manager_.add_controller(c); }
auto remove_controller(input_device_controller& c) -> void { input_manager_.remove_controller(c); }
private:
auto handle_action(action const&) -> void;
- auto show_error(std::string_view message, status error, action const& action = action::close_popup()) -> void;
+ auto show_error(string_view message, status error, action const& action = action::close_popup()) -> void;
auto go_to_screen(screen*) -> void;
};
} // namespace nes::app \ No newline at end of file
diff --git a/lib/nes/app/file-browser.hh b/lib/nes/app/file-browser.hh
index 3465000..1da4cd6 100644
--- a/lib/nes/app/file-browser.hh
+++ b/lib/nes/app/file-browser.hh
@@ -1,9 +1,10 @@
#pragma once
#include "nes/common/containers/span.hh"
+#include "nes/common/containers/string-view.hh"
#include "nes/common/types.hh"
#include "nes/common/status.hh"
-#include <string_view>
+#include "nes/common/utils.hh"
namespace nes
{
@@ -33,14 +34,14 @@ namespace nes::app
public:
explicit entry() = default;
- explicit entry(entry_type const type, std::string_view const name)
+ explicit entry(entry_type const type, string_view const name)
: type_{ type }
{
- std::copy_n(name.begin(), std::min(static_cast<u32>(name.length()), max_name_length), name_);
+ copy(name.get_data(), name_, min(name.get_length(), max_name_length));
}
auto get_type() const -> entry_type { return type_; }
- auto get_name() const -> std::string_view { return name_; }
+ auto get_name() const -> string_view { return name_; }
};
virtual ~file_browser() = default;
@@ -63,10 +64,10 @@ namespace nes::app
virtual auto navigate_up() -> status = 0;
/// Change the current working directory to an item.
- virtual auto navigate(std::string_view) -> status = 0;
+ virtual auto navigate(string_view) -> status = 0;
/// Load a file in the current working directory into memory.
- virtual auto load(std::string_view, span<u8>, u32* out_length) -> status = 0;
+ virtual auto load(string_view, span<u8>, u32* out_length) -> status = 0;
protected:
explicit file_browser() = default;
diff --git a/lib/nes/app/graphics/renderer.cc b/lib/nes/app/graphics/renderer.cc
index 4f0d562..1745dd7 100644
--- a/lib/nes/app/graphics/renderer.cc
+++ b/lib/nes/app/graphics/renderer.cc
@@ -7,6 +7,7 @@
#include "nes/app/graphics/tiles/characters.hh"
#include "nes/app/graphics/tiles/borders.hh"
#include "nes/common/display.hh"
+#include "nes/common/utils.hh"
namespace nes::app
{
@@ -64,32 +65,32 @@ namespace nes::app
}
auto renderer::render_text(
- i32 x, i32 const y, std::string_view const str, color const c, text_attributes const attributes) -> u32
+ i32 x, i32 const y, string_view const str, color const c, text_attributes const attributes) -> u32
{
// Enforce max length
char buffer[width];
- auto const length = std::min(static_cast<u32>(str.length()), std::min(width, attributes.get_max_width()));
- auto const ellipsize_dots = std::min(length, u32{ 3 });
+ auto const length = min(str.get_length(), min(width, attributes.get_max_width()));
+ auto const ellipsize_dots = min(length, u32{ 3 });
// Enforce ellipsize mode
- if (str.length() > length)
+ if (str.get_length() > length)
{
switch (attributes.get_ellipsize_mode())
{
case ellipsize_mode::clip:
{
- std::copy_n(str.begin(), length, buffer);
+ copy(str.get_data(), buffer, length);
break;
}
case ellipsize_mode::end:
{
- std::copy_n(str.begin(), length, buffer);
+ copy(str.get_data(), buffer, length);
for (auto i = u32{ 0 }; i < ellipsize_dots; ++i) { buffer[length - 1 - i] = '.'; }
break;
}
case ellipsize_mode::start:
{
- std::copy_n(str.begin() + str.length() - length, length, buffer);
+ copy(str.get_data() + str.get_length() - length, buffer, length);
for (auto i = u32{ 0 }; i < ellipsize_dots; ++i) { buffer[i] = '.'; }
break;
}
@@ -98,16 +99,16 @@ namespace nes::app
auto const visible = length - ellipsize_dots;
auto const start = visible / 2;
auto const end = visible - start;
- std::copy_n(str.begin(), start, buffer);
+ copy(str.get_data(), buffer, start);
for (auto i = u32{ 0 }; i < ellipsize_dots; ++i) { buffer[start + i] = '.'; }
- std::copy_n(str.begin() + str.length() - end, end, buffer + start + ellipsize_dots);
+ copy(str.get_data() + str.get_length() - end, buffer + start + ellipsize_dots, end);
break;
}
}
}
else
{
- std::copy_n(str.begin(), length, buffer);
+ copy(str.get_data(), buffer, length);
}
// Enforce alignment
@@ -132,10 +133,10 @@ namespace nes::app
if (c == color::transparent) { return; }
auto const resolved = resolve_color(c);
- auto const x_stop = std::min(x + static_cast<i32>(width), static_cast<i32>(renderer::width));
- auto const y_stop = std::min(y + static_cast<i32>(height), static_cast<i32>(renderer::height));
- auto const x_start = std::max(x, 0);
- auto const y_start = std::max(y, 0);
+ auto const x_stop = min(x + static_cast<i32>(width), static_cast<i32>(renderer::width));
+ auto const y_stop = min(y + static_cast<i32>(height), static_cast<i32>(renderer::height));
+ auto const x_start = max(x, 0);
+ auto const y_start = max(y, 0);
for (auto y_px = i32{ y_start * 8 }; y_px < y_stop * 8; ++y_px)
{
for (auto x_px = i32{ x_start * 8 }; x_px < x_stop * 8; ++x_px)
@@ -149,10 +150,10 @@ namespace nes::app
{
if (width <= 1 || height <= 1) { return; }
- auto const x_last = std::min(x + static_cast<i32>(width), static_cast<i32>(renderer::width)) - 1;
- auto const y_last = std::min(y + static_cast<i32>(height), static_cast<i32>(renderer::height)) - 1;
- auto const x_start = std::max(x, 0);
- auto const y_start = std::max(y, 0);
+ auto const x_last = min(x + static_cast<i32>(width), static_cast<i32>(renderer::width)) - 1;
+ auto const y_last = min(y + static_cast<i32>(height), static_cast<i32>(renderer::height)) - 1;
+ auto const x_start = max(x, 0);
+ auto const y_start = max(y, 0);
for (auto border_y = i32{ y_start }; border_y <= y_last; ++border_y)
{
for (auto border_x = i32{ x_start }; border_x <= x_last; ++border_x)
diff --git a/lib/nes/app/graphics/renderer.hh b/lib/nes/app/graphics/renderer.hh
index 2e24ad3..50ca092 100644
--- a/lib/nes/app/graphics/renderer.hh
+++ b/lib/nes/app/graphics/renderer.hh
@@ -3,8 +3,8 @@
#include "nes/app/graphics/color.hh"
#include "nes/app/graphics/text-attributes.hh"
#include "nes/common/containers/string-builder.hh"
+#include "nes/common/containers/string-view.hh"
#include "nes/common/types.hh"
-#include <string_view>
namespace nes
{
@@ -46,11 +46,11 @@ namespace nes::app
/// Render an image at the given tile coordinates.
auto render_image(i32 x, i32 y, image_view) -> void;
/// Render a string of text at the given tile coordinates (one tile per character).
- auto render_text(i32 x, i32 y, std::string_view, color, text_attributes = text_attributes{}) -> u32;
+ auto render_text(i32 x, i32 y, string_view, color, text_attributes = text_attributes{}) -> u32;
template<typename... Args>
auto render_text_format(
- i32 const x, i32 const y, color const c, text_attributes const attrs, std::string_view const fmt,
+ i32 const x, i32 const y, color const c, text_attributes const attrs, string_view const fmt,
Args... args) -> u32
{
string_buffer<width> buffer{};
@@ -60,7 +60,7 @@ namespace nes::app
template<typename... Args>
auto render_text_format(
- i32 const x, i32 const y, color const c, std::string_view const fmt, Args... args) -> u32
+ i32 const x, i32 const y, color const c, string_view const fmt, Args... args) -> u32
{
return render_text_format(x, y, c, text_attributes{}, fmt, args...);
}
diff --git a/lib/nes/app/input/input-device-keyboard.hh b/lib/nes/app/input/input-device-keyboard.hh
index ef89c59..1365a1b 100644
--- a/lib/nes/app/input/input-device-keyboard.hh
+++ b/lib/nes/app/input/input-device-keyboard.hh
@@ -43,7 +43,7 @@ namespace nes::app
return res;
}
- auto get_name() const -> std::string_view final { return "Keyboard"; }
+ auto get_name() const -> string_view final { return "Keyboard"; }
protected:
explicit input_device_keyboard() = default;
diff --git a/lib/nes/app/input/input-device.hh b/lib/nes/app/input/input-device.hh
index 008825d..bd2f7c2 100644
--- a/lib/nes/app/input/input-device.hh
+++ b/lib/nes/app/input/input-device.hh
@@ -1,7 +1,7 @@
#pragma once
#include "nes/sys/types/button-mask.hh"
-#include <string_view>
+#include "nes/common/containers/string-view.hh"
namespace nes::app
{
@@ -20,7 +20,7 @@ namespace nes::app
virtual auto read_buttons() -> sys::button_mask = 0;
/// Human-readable name for the device.
- virtual auto get_name() const -> std::string_view = 0;
+ virtual auto get_name() const -> string_view = 0;
protected:
explicit input_device() = default;
diff --git a/lib/nes/app/input/input-manager.cc b/lib/nes/app/input/input-manager.cc
index e88ac84..27b29e4 100644
--- a/lib/nes/app/input/input-manager.cc
+++ b/lib/nes/app/input/input-manager.cc
@@ -15,7 +15,7 @@ namespace nes::app
return res;
}
- auto get_name() const -> std::string_view override { return "(None)"; }
+ auto get_name() const -> string_view override { return "(None)"; }
auto read_buttons() -> sys::button_mask override { return sys::button_mask{}; }
};
} // namespace
diff --git a/lib/nes/app/ui/screen-browser.cc b/lib/nes/app/ui/screen-browser.cc
index 1b515bd..50b0060 100644
--- a/lib/nes/app/ui/screen-browser.cc
+++ b/lib/nes/app/ui/screen-browser.cc
@@ -4,6 +4,7 @@
#include "nes/app/graphics/tiles/icons.hh"
#include "nes/app/input/input-device-keyboard.hh"
#include "nes/common/containers/path-view.hh"
+#include "nes/common/utils.hh"
namespace nes::app
{
@@ -152,6 +153,6 @@ namespace nes::app
// Round up to get page count.
auto const page_count = (count + (page_size - 1)) / page_size;
// Always show at least one page.
- selection_.set_page_count(std::max(u32{ 1 }, page_count));
+ selection_.set_page_count(max(u32{ 1 }, page_count));
}
} // namespace nes::app \ No newline at end of file
diff --git a/lib/nes/app/ui/screen-error.hh b/lib/nes/app/ui/screen-error.hh
index 4559942..53b6407 100644
--- a/lib/nes/app/ui/screen-error.hh
+++ b/lib/nes/app/ui/screen-error.hh
@@ -1,6 +1,7 @@
#pragma once
#include "nes/app/ui/screen.hh"
+#include "nes/common/containers/string-view.hh"
namespace nes::app
{
@@ -10,17 +11,17 @@ namespace nes::app
class screen_error final : public screen
{
input_device_keyboard& keyboard_;
- std::string_view message_;
+ string_view message_;
status error_{ status::success };
action action_{};
public:
explicit screen_error(input_device_keyboard&);
- auto get_message() const -> std::string_view { return message_; }
+ auto get_message() const -> string_view { return message_; }
auto get_error() const -> status { return error_; }
auto get_action() const -> action { return action_; }
- auto set_message(std::string_view const v) -> void { message_ = v; }
+ auto set_message(string_view const v) -> void { message_ = v; }
auto set_error(status const v) -> void { error_ = v; }
auto set_action(action const& v) -> void { action_ = v; }
diff --git a/lib/nes/app/ui/screen-settings.cc b/lib/nes/app/ui/screen-settings.cc
index 98070d7..9ba4b50 100644
--- a/lib/nes/app/ui/screen-settings.cc
+++ b/lib/nes/app/ui/screen-settings.cc
@@ -7,7 +7,7 @@ namespace nes::app
auto screen_settings::selection_impl::render_item(
renderer& renderer, item const& item, i32 const x, i32 const y, u32 const width, color const c) const -> void
{
- auto const render = [&](std::string_view const label, std::string_view const value)
+ auto const render = [&](string_view const label, string_view const value)
{
auto const label_length = renderer.render_text(x, y, label, c);
auto const value_attrs = text_attributes{}
diff --git a/lib/nes/common/CMakeLists.txt b/lib/nes/common/CMakeLists.txt
index 9a7cc6b..e227ca8 100644
--- a/lib/nes/common/CMakeLists.txt
+++ b/lib/nes/common/CMakeLists.txt
@@ -7,6 +7,7 @@ target_sources(
display.hh
status.hh
fps-counter.hh
- fps-counter.cc)
+ fps-counter.cc
+ utils.hh)
add_subdirectory(containers) \ No newline at end of file
diff --git a/lib/nes/common/containers/CMakeLists.txt b/lib/nes/common/containers/CMakeLists.txt
index 351772f..69b6dd9 100644
--- a/lib/nes/common/containers/CMakeLists.txt
+++ b/lib/nes/common/containers/CMakeLists.txt
@@ -9,4 +9,6 @@ target_sources(
path-view.cc
span.hh
string-builder.hh
- string-builder.cc) \ No newline at end of file
+ string-builder.cc
+ string-view.hh
+ string-view.cc) \ No newline at end of file
diff --git a/lib/nes/common/containers/box.hh b/lib/nes/common/containers/box.hh
index 7bf2848..82f6448 100644
--- a/lib/nes/common/containers/box.hh
+++ b/lib/nes/common/containers/box.hh
@@ -2,6 +2,8 @@
#include "nes/common/types.hh"
#include "nes/common/debug.hh"
+#include "nes/common/utils.hh"
+#include <new>
namespace nes
{
@@ -56,15 +58,15 @@ namespace nes
operator bool() const { return has_value(); }
auto has_value() const -> bool { return initialized_; }
- auto get() -> T* { return has_value() ? std::launder(reinterpret_cast<T*>(buffer_)) : nullptr; }
- auto get() const -> T const* { return has_value() ? std::launder(reinterpret_cast<T const *>(buffer_)) : nullptr; }
+ auto get() -> T* { return has_value() ? launder(reinterpret_cast<T*>(buffer_)) : nullptr; }
+ auto get() const -> T const* { return has_value() ? launder(reinterpret_cast<T const *>(buffer_)) : nullptr; }
/// Construct a new value in-place, potentially replacing the old value.
template<typename... Args>
auto emplace(Args&&... args) -> void
{
clear();
- new (buffer_) T(std::forward<Args>(args)...);
+ new (buffer_) T(args...);
initialized_ = true;
}
diff --git a/lib/nes/common/containers/path-builder.cc b/lib/nes/common/containers/path-builder.cc
index 2e3ce07..f352b46 100644
--- a/lib/nes/common/containers/path-builder.cc
+++ b/lib/nes/common/containers/path-builder.cc
@@ -9,21 +9,21 @@ namespace nes
if (buffer_.get_length() > 0) { buffer_[length_++] = '/'; }
}
- auto path_builder::push(std::string_view component) -> status
+ auto path_builder::push(string_view component) -> status
{
// Trim leading and trailing slashes
- while (!component.empty() && component[0] == '/') { component = component.substr(1); }
- while (!component.empty() && component[component.length() - 1] == '/') { component = component.substr(0, component.length() - 1); }
- if (component.empty() || std::find(component.begin(), component.end(), '/') != component.end()) { return status::error_invalid_path; }
+ while (!component.is_empty() && component.get_first() == '/') { component = component.substring(1); }
+ while (!component.is_empty() && component.get_last() == '/') { component = component.substring(0, component.get_length() - 1); }
+ if (component.is_empty() || component.contains('/')) { return status::error_invalid_path; }
// Check if there is enough remaining capacity for "/<component>"
auto const add_leading_slash = length_ == 0 || buffer_[length_ - 1] != '/';
- auto const length = component.length() + (add_leading_slash ? 1 : 0);
+ auto const length = component.get_length() + (add_leading_slash ? 1 : 0);
if (length_ + length > buffer_.get_length()) { return status::error_buffer_overflow; }
// Append "/<component>"
if (add_leading_slash) { buffer_[length_++] = '/'; }
- for (auto i = u32{ 0 }; i < component.length(); ++i) { buffer_[length_++] = component[i]; }
+ for (auto i = u32{ 0 }; i < component.get_length(); ++i) { buffer_[length_++] = component[i]; }
return status::success;
}
diff --git a/lib/nes/common/containers/path-builder.hh b/lib/nes/common/containers/path-builder.hh
index 2991a83..3bddb87 100644
--- a/lib/nes/common/containers/path-builder.hh
+++ b/lib/nes/common/containers/path-builder.hh
@@ -1,10 +1,11 @@
#pragma once
#include "nes/common/containers/span.hh"
+#include "nes/common/containers/string-view.hh"
#include "nes/common/containers/path-view.hh"
#include "nes/common/types.hh"
#include "nes/common/status.hh"
-#include <string_view>
+#include "nes/common/utils.hh"
namespace nes
{
@@ -21,9 +22,9 @@ namespace nes
explicit path_builder(span<char>);
auto get_components() const -> path_view { return path_view{ get_path() }; }
- auto get_path() const -> std::string_view { return std::string_view{ buffer_.get_data(), length_ }; }
+ auto get_path() const -> string_view { return string_view{ buffer_.get_data(), length_ }; }
- auto push(std::string_view) -> status;
+ auto push(string_view) -> status;
auto pop() -> status;
};
@@ -42,13 +43,13 @@ namespace nes
path_buffer(path_buffer const& other)
: path_builder{ buffer_ }
{
- std::copy_n(other.buffer_, Capacity, buffer_);
+ copy(other.buffer_, buffer_, Capacity);
length_ = other.length_;
}
auto operator=(path_buffer const& other)
{
- std::copy_n(other.buffer_, Capacity, buffer_);
+ copy(other.buffer_, buffer_, Capacity);
length_ = other.length_;
}
};
diff --git a/lib/nes/common/containers/path-view.cc b/lib/nes/common/containers/path-view.cc
index c81668b..33d82a8 100644
--- a/lib/nes/common/containers/path-view.cc
+++ b/lib/nes/common/containers/path-view.cc
@@ -3,10 +3,10 @@
namespace nes
{
- auto path_view::iterator::operator*() const -> std::string_view
+ auto path_view::iterator::operator*() const -> string_view
{
NES_ASSERT(current_ != nullptr && component_length_ > 0 && "invalid iterator");
- return std::string_view{ current_, component_length_ };
+ return string_view{ current_, component_length_ };
}
auto path_view::iterator::operator++() -> iterator&
@@ -41,11 +41,11 @@ namespace nes
auto path_view::begin() const -> iterator
{
- return ++iterator{ path_.data(), 0, static_cast<u32>(path_.size()) };
+ return ++iterator{ path_.get_data(), 0, path_.get_length() };
}
auto path_view::end() const -> iterator
{
- return iterator{ path_.data() + path_.size(), 0, 0 };
+ return iterator{ path_.get_data() + path_.get_length(), 0, 0 };
}
} // namespace nes \ No newline at end of file
diff --git a/lib/nes/common/containers/path-view.hh b/lib/nes/common/containers/path-view.hh
index 7741060..1c25d26 100644
--- a/lib/nes/common/containers/path-view.hh
+++ b/lib/nes/common/containers/path-view.hh
@@ -1,14 +1,14 @@
#pragma once
+#include "nes/common/containers/string-view.hh"
#include "nes/common/types.hh"
-#include <string_view>
namespace nes
{
/// Non-owning copy of a path, useful for iterating over its components.
class path_view
{
- std::string_view path_;
+ string_view path_;
public:
/// An iterator for the path components.
@@ -24,7 +24,7 @@ namespace nes
auto operator==(iterator const& other) -> bool { return current_ == other.current_; }
auto operator!=(iterator const& other) -> bool { return current_ != other.current_; }
- auto operator*() const -> std::string_view;
+ auto operator*() const -> string_view;
auto operator++() -> iterator&;
auto operator++(int) -> iterator;
@@ -38,12 +38,12 @@ namespace nes
};
explicit path_view() = default;
- explicit path_view(std::string_view const path)
+ explicit path_view(string_view const path)
: path_{ path }
{
}
- auto get_path() const -> std::string_view { return path_; }
+ auto get_path() const -> string_view { return path_; }
auto begin() const -> iterator;
auto end() const -> iterator;
diff --git a/lib/nes/common/containers/string-builder.cc b/lib/nes/common/containers/string-builder.cc
index 74d9548..ad2f97f 100644
--- a/lib/nes/common/containers/string-builder.cc
+++ b/lib/nes/common/containers/string-builder.cc
@@ -16,7 +16,7 @@ namespace nes
return status::success;
}
- auto string_builder::append_string(std::string_view const value) -> status
+ auto string_builder::append_string(string_view const value) -> status
{
auto copy = *this;
for (auto const c : value)
@@ -103,13 +103,13 @@ namespace nes
return append_string(value ? "true" : "false");
}
- auto string_builder::append_format(std::string_view const fmt, format_arg const* args, u32 const arg_count) -> status
+ auto string_builder::append_format(string_view const fmt, format_arg const* args, u32 const arg_count) -> status
{
auto copy = *this;
// Go through the format string, inserting the arguments for the templates as necessary.
auto current_arg = u32{ 0 };
- for (auto i = u32{ 0 }; i < fmt.length(); ++i)
+ for (auto i = u32{ 0 }; i < fmt.get_length(); ++i)
{
if (fmt[i] == '{')
{
@@ -122,10 +122,10 @@ namespace nes
else
{
// start of template
- auto const params = &fmt[i]; // remember start position
+ auto const params_start = i; // remember start position
auto params_length = u32{ 0 };
// skip to the end of the template
- while (fmt[i] && fmt[i] != '}')
+ while (i < fmt.get_length() && fmt[i] != '}')
{
params_length++;
i++;
@@ -137,7 +137,7 @@ namespace nes
}
// end of template
- auto const p = std::string_view{ params, params_length };
+ auto const p = fmt.substring(params_start, params_length);
if (current_arg < arg_count)
{
if (auto const s = copy.append_format_arg(args[current_arg], p); s != status::success) { return s; }
@@ -182,11 +182,11 @@ namespace nes
return status::success;
}
- auto string_builder::append_format_arg(format_arg const arg, std::string_view const params) -> status
+ auto string_builder::append_format_arg(format_arg const arg, string_view const params) -> status
{
auto const parse_params = [&]
{
- if (!params.empty())
+ if (!params.is_empty())
{
return status::error_invalid_format_string;
}
@@ -196,7 +196,7 @@ namespace nes
auto const parse_params_integer = [&](number_format& out_format)
{
- if (params.empty() || params == "d")
+ if (params.is_empty() || params == "d")
{
out_format = number_format::decimal;
}
diff --git a/lib/nes/common/containers/string-builder.hh b/lib/nes/common/containers/string-builder.hh
index 0f8a64c..7dcbb34 100644
--- a/lib/nes/common/containers/string-builder.hh
+++ b/lib/nes/common/containers/string-builder.hh
@@ -1,9 +1,10 @@
#pragma once
-#include "nes/common/types.hh"
#include "nes/common/containers/span.hh"
+#include "nes/common/containers/string-view.hh"
+#include "nes/common/types.hh"
#include "nes/common/status.hh"
-#include <string_view>
+#include "nes/common/utils.hh"
namespace nes
{
@@ -38,7 +39,7 @@ namespace nes
format_arg_type type;
union
{
- std::string_view string;
+ string_view string;
char character;
i64 signed_integer;
u64 unsigned_integer;
@@ -48,7 +49,7 @@ namespace nes
format_arg() = delete;
explicit format_arg(char const* v) : type{ format_arg_type::string } { string = v; }
- explicit format_arg(std::string_view const v) : type{ format_arg_type::string } { string = v; }
+ explicit format_arg(string_view const v) : type{ format_arg_type::string } { string = v; }
explicit format_arg(char const v) : type{ format_arg_type::character } { character = v; }
explicit format_arg(unsigned char const v) : format_arg{ static_cast<char>(v) } {}
explicit format_arg(long long const v) : type{ format_arg_type::signed_integer } { signed_integer = v; }
@@ -66,10 +67,10 @@ namespace nes
explicit string_builder(span<char>);
/// Get the resulting string.
- auto get_result() const -> std::string_view { return std::string_view{ buffer_.get_data(), length_ }; }
+ auto get_result() const -> string_view { return string_view{ buffer_.get_data(), length_ }; }
auto append_char(char) -> status;
- auto append_string(std::string_view) -> status;
+ auto append_string(string_view) -> status;
auto append_int(i64, number_format = number_format::decimal) -> status;
auto append_int(u64, number_format = number_format::decimal) -> status;
auto append_bool(bool) -> status;
@@ -82,7 +83,7 @@ namespace nes
///
/// Curly braces can be escaped by repeating them twice like {{this}}.
template<typename... Args>
- auto append_format(std::string_view const fmt, Args... args) -> status
+ auto append_format(string_view const fmt, Args... args) -> status
{
constexpr u32 arg_count = sizeof...(Args);
// Add another argument at the end so we don't have an empty array expression.
@@ -92,8 +93,8 @@ namespace nes
}
private:
- auto append_format(std::string_view fmt, format_arg const* args, u32 arg_count) -> status;
- auto append_format_arg(format_arg, std::string_view params) -> status;
+ auto append_format(string_view fmt, format_arg const* args, u32 arg_count) -> status;
+ auto append_format_arg(format_arg, string_view params) -> status;
};
/// A string builder with a buffer embedded into it.
@@ -111,13 +112,13 @@ namespace nes
string_buffer(string_buffer const& other)
: string_builder{ buffer_ }
{
- std::copy_n(other.buffer_, Capacity, buffer_);
+ copy(other.buffer_, buffer_, Capacity);
length_ = other.length_;
}
auto operator=(string_buffer const& other)
{
- std::copy_n(other.buffer_, Capacity, buffer_);
+ copy(other.buffer_, buffer_, Capacity);
length_ = other.length_;
}
};
diff --git a/lib/nes/common/containers/string-view.cc b/lib/nes/common/containers/string-view.cc
new file mode 100644
index 0000000..8265d09
--- /dev/null
+++ b/lib/nes/common/containers/string-view.cc
@@ -0,0 +1,81 @@
+#include "nes/common/containers/string-view.hh"
+#include "nes/common/debug.hh"
+
+namespace nes
+{
+ namespace
+ {
+ auto compute_length(char const* c_string) -> u32
+ {
+ auto res = u32{ 0 };
+ while (*c_string)
+ {
+ res += 1;
+ c_string++;
+ }
+ return res;
+ }
+ } // namespace
+
+ string_view::string_view(span<char const> const data)
+ : data_{ data }
+ {
+ }
+
+ string_view::string_view(char const* data, u32 length)
+ : data_{ data, length }
+ {
+ }
+
+ string_view::string_view(char const* c_string)
+ : string_view{ c_string, compute_length(c_string) }
+ {
+ }
+
+ auto string_view::get_first() const -> char
+ {
+ NES_ASSERT(!is_empty() && "unable to get character of empty string");
+ return data_[0];
+ }
+
+ auto string_view::get_last() const -> char
+ {
+ NES_ASSERT(!is_empty() && "unable to get character of empty string");
+ return data_[data_.get_length() - 1];
+ }
+
+ auto string_view::contains(char const needle) const -> bool
+ {
+ for (const auto c : *this)
+ {
+ if (c == needle) { return true; }
+ }
+ return false;
+ }
+
+ auto string_view::substring(u32 const first) const -> string_view
+ {
+ return string_view{ data_.subspan(first) };
+ }
+
+ auto string_view::substring(u32 const first, u32 const length) const -> string_view
+ {
+ return string_view{ data_.subspan(first, length) };
+ }
+
+ auto operator==(string_view const lhs, string_view const rhs) -> bool
+ {
+ if (lhs.get_length() != rhs.get_length()) { return false; }
+
+ for (auto i = u32{ 0 }; i < lhs.get_length(); ++i)
+ {
+ if (lhs[i] != rhs[i]) { return false; }
+ }
+
+ return true;
+ }
+ auto operator!=(string_view const lhs, string_view const rhs) -> bool
+ {
+ return !(lhs == rhs);
+ }
+} // namespace nes \ No newline at end of file
diff --git a/lib/nes/common/containers/string-view.hh b/lib/nes/common/containers/string-view.hh
new file mode 100644
index 0000000..180a688
--- /dev/null
+++ b/lib/nes/common/containers/string-view.hh
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "nes/common/containers/span.hh"
+#include "nes/common/types.hh"
+
+namespace nes
+{
+ /// Non-owning view into a (not necessarily null-terminated) string.
+ class string_view
+ {
+ span<char const> data_;
+
+ public:
+ explicit string_view() = default;
+ explicit string_view(span<char const>);
+ explicit string_view(char const* data, u32 length);
+ string_view(char const* c_string);
+
+ using iterator = span<char const>::iterator;
+
+ auto operator[](u32 const index) const -> char { return data_[index]; }
+ auto get_span() const -> span<char const> { return data_; }
+ auto get_data() const -> char const* { return data_.get_data(); }
+ auto get_length() const -> u32 { return data_.get_length(); }
+ auto is_empty() const -> bool { return get_length() == 0; }
+ auto begin() const -> iterator { return data_.begin(); }
+ auto end() const -> iterator { return data_.end(); }
+
+ // String helpers
+
+ auto get_first() const -> char;
+ auto get_last() const -> char;
+ auto contains(char) const -> bool;
+ auto substring(u32 first) const -> string_view;
+ auto substring(u32 first, u32 length) const -> string_view;
+ };
+
+ auto operator==(string_view, string_view) -> bool;
+ auto operator!=(string_view, string_view) -> bool;
+} // namespace nes \ No newline at end of file
diff --git a/lib/nes/common/fps-counter.cc b/lib/nes/common/fps-counter.cc
index ef6169b..8f19c7e 100644
--- a/lib/nes/common/fps-counter.cc
+++ b/lib/nes/common/fps-counter.cc
@@ -2,9 +2,9 @@
namespace nes
{
- auto fps_counter::frame(std::chrono::microseconds const elapsed_time) -> void
+ auto fps_counter::frame(u32 const elapsed_time_us) -> void
{
- if (elapsed_time.count() <= 0) { return; }
+ if (elapsed_time_us == 0) { return; }
if (buffer_position_ == 0)
{
@@ -22,8 +22,7 @@ namespace nes
}
// Add the frame time to the buffer, replacing any existing content in the ring buffer.
- auto const frame_time = static_cast<u32>(elapsed_time.count());
- frame_times_[buffer_position_] = frame_time;
+ frame_times_[buffer_position_] = elapsed_time_us;
buffer_position_ = (buffer_position_ + 1) % buffer_size;
}
} // namespace nes \ No newline at end of file
diff --git a/lib/nes/common/fps-counter.hh b/lib/nes/common/fps-counter.hh
index 96db98c..f921880 100644
--- a/lib/nes/common/fps-counter.hh
+++ b/lib/nes/common/fps-counter.hh
@@ -1,7 +1,6 @@
#pragma once
#include "nes/common/types.hh"
-#include <chrono>
namespace nes
{
@@ -17,7 +16,7 @@ namespace nes
public:
explicit fps_counter() = default;
- auto frame(std::chrono::microseconds elapsed_time) -> void;
+ auto frame(u32 elapsed_time_us) -> void;
auto get_fps() const -> u32 { return buffered_fps_; }
};
} // namespace nes \ No newline at end of file
diff --git a/lib/nes/common/utils.hh b/lib/nes/common/utils.hh
new file mode 100644
index 0000000..460d0d5
--- /dev/null
+++ b/lib/nes/common/utils.hh
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "nes/common/types.hh"
+
+namespace nes
+{
+ template<typename T>
+ auto launder(T* p) -> T*
+ {
+ return __builtin_launder(p);
+ }
+
+ template<typename T>
+ auto copy(T const* src, T* dst, u32 const length)
+ {
+ for (auto i = u32{ 0 }; i < length; ++i) { dst[i] = src[i]; }
+ }
+
+ template<typename T>
+ auto min(T const a, T const b)
+ {
+ return a < b ? a : b;
+ }
+
+ template<typename T>
+ auto max(T const a, T const b)
+ {
+ return a > b ? a : b;
+ }
+
+ template<typename T>
+ auto swap(T& a, T& b) -> void
+ {
+ auto const tmp = a;
+ a = b;
+ b = tmp;
+ }
+} // namespace nes \ No newline at end of file
diff --git a/lib/nes/sys/cartridge.cc b/lib/nes/sys/cartridge.cc
index 0729107..b6670a3 100644
--- a/lib/nes/sys/cartridge.cc
+++ b/lib/nes/sys/cartridge.cc
@@ -1,6 +1,6 @@
#include "nes/sys/cartridge.hh"
#include "nes/common/status.hh"
-#include <algorithm>
+#include "nes/common/utils.hh"
namespace nes::sys
{
@@ -27,16 +27,16 @@ namespace nes::sys
prg_rom_size_ = h.get_prg_rom_banks() * prg_rom_bank_size;
if (data.get_length() < offset + prg_rom_size_) { return; }
if (prg_rom_size_ > max_prg_rom_size) { return; }
- std::copy_n(&data[offset], prg_rom_size_, prg_rom_);
+ copy(&data[offset], prg_rom_, prg_rom_size_);
offset += prg_rom_size_;
chr_rom_size_ = h.get_chr_rom_banks() * chr_rom_bank_size;
if (data.get_length() < offset + chr_rom_size_) { return; }
if (chr_rom_size_ > max_chr_rom_size) { return; }
- std::copy_n(&data[offset], chr_rom_size_, chr_rom_);
+ copy(&data[offset], chr_rom_, chr_rom_size_);
- ram_size_ = std::max(h.get_ram_banks(), 1u) * ram_bank_size;
+ ram_size_ = max(h.get_ram_banks(), u32{ 1 }) * ram_bank_size;
if (ram_size_ > max_ram_size) { return; }
status_ = get_mapper().validate(*this);
diff --git a/lib/nes/sys/cpu.cc b/lib/nes/sys/cpu.cc
index 09e2094..55bbb21 100644
--- a/lib/nes/sys/cpu.cc
+++ b/lib/nes/sys/cpu.cc
@@ -15,6 +15,7 @@ namespace nes::sys
registers_.pc = read16(address{ 0xFFFC });
}
+#ifdef NES_ENABLE_SNAPSHOTS
auto cpu::build_snapshot(snapshot& snapshot) -> void
{
snapshot.cpu_cycle = current_cycles_;
@@ -33,6 +34,7 @@ namespace nes::sys
snapshot.registers.v = registers_.p.get_v();
snapshot.registers.n = registers_.p.get_n();
}
+#endif
auto cpu::stall_cycles(cycle_count const count) -> void
{
@@ -1236,7 +1238,7 @@ namespace nes::sys
}
case addressing_mode::relative:
{
- auto const offset = static_cast<std::int8_t>(advance_pc8());
+ auto const offset = static_cast<i8>(advance_pc8());
auto const base = address{ registers_.pc };
addr = address{ static_cast<u16>(registers_.pc + offset) };
auto const page_crossing =
diff --git a/lib/nes/sys/cpu.hh b/lib/nes/sys/cpu.hh
index 99753a7..795039c 100644
--- a/lib/nes/sys/cpu.hh
+++ b/lib/nes/sys/cpu.hh
@@ -2,6 +2,7 @@
#include "nes/sys/types/cycle-count.hh"
#include "nes/sys/types/address.hh"
+#include "nes/sys/types/snapshot.hh"
#include "nes/common/status.hh"
#include "nes/common/types.hh"
@@ -10,7 +11,6 @@ namespace nes::sys
class ppu;
class controller;
class cartridge;
- struct snapshot;
class cpu
{
@@ -138,7 +138,9 @@ namespace nes::sys
auto operator=(cpu&&) -> cpu& = delete;
auto get_cycles() const -> cycle_count { return current_cycles_; }
+#ifdef NES_ENABLE_SNAPSHOTS
auto build_snapshot(snapshot&) -> void;
+#endif
auto stall_cycles(cycle_count) -> void;
auto trigger_nmi() -> void;
auto step() -> status;
diff --git a/lib/nes/sys/nes.cc b/lib/nes/sys/nes.cc
index 5cc47a4..ca12190 100644
--- a/lib/nes/sys/nes.cc
+++ b/lib/nes/sys/nes.cc
@@ -1,5 +1,4 @@
#include "nes/sys/nes.hh"
-#include "nes/sys/types/snapshot.hh"
namespace nes::sys
{
@@ -12,11 +11,6 @@ namespace nes::sys
{
}
- auto nes::step(std::chrono::microseconds const delta) -> void
- {
- step(cycle_count::from_duration(delta));
- }
-
auto nes::step() -> void
{
if (get_status() != status::success) { return; }
@@ -49,6 +43,7 @@ namespace nes::sys
}
}
+#ifdef NES_ENABLE_SNAPSHOTS
auto nes::get_snapshot() -> snapshot
{
auto res = snapshot{};
@@ -57,4 +52,5 @@ namespace nes::sys
ppu_.build_snapshot(res);
return res;
}
+#endif
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/nes.hh b/lib/nes/sys/nes.hh
index 2533cbb..8d03dd7 100644
--- a/lib/nes/sys/nes.hh
+++ b/lib/nes/sys/nes.hh
@@ -1,6 +1,7 @@
#pragma once
#include "nes/sys/types/cycle-count.hh"
+#include "nes/sys/types/snapshot.hh"
#include "nes/sys/cartridge.hh"
#include "nes/sys/controller.hh"
#include "nes/sys/cpu.hh"
@@ -14,8 +15,6 @@ namespace nes
namespace nes::sys
{
- struct snapshot;
-
/// The main console abstraction.
class nes
{
@@ -43,10 +42,11 @@ namespace nes::sys
auto ref_controller_2() -> controller& { return controller_2_; }
auto step() -> void;
- auto step(std::chrono::microseconds delta) -> void;
auto step(cycle_count delta) -> void;
auto step_to_nmi() -> void;
+#ifdef NES_ENABLE_SNAPSHOTS
auto get_snapshot() -> snapshot;
+#endif
};
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/ppu.cc b/lib/nes/sys/ppu.cc
index 2419030..ce145d5 100644
--- a/lib/nes/sys/ppu.cc
+++ b/lib/nes/sys/ppu.cc
@@ -6,6 +6,7 @@
#include "nes/common/display.hh"
#include "nes/common/rgb.hh"
#include "nes/common/debug.hh"
+#include "nes/common/utils.hh"
namespace nes::sys
{
@@ -16,11 +17,13 @@ namespace nes::sys
{
}
+#ifdef NES_ENABLE_SNAPSHOTS
auto ppu::build_snapshot(snapshot& snapshot) -> void
{
snapshot.vram = std::vector(std::begin(vram_), std::end(vram_));
snapshot.oam = std::vector(std::begin(oam_), std::end(oam_));
}
+#endif
auto ppu::step() -> void
{
@@ -291,7 +294,7 @@ namespace nes::sys
{
for (auto i = u32{ 0 }; i < tile_size / 2; ++i)
{
- std::swap(res.colors[i], res.colors[tile_size - 1 - i]);
+ swap(res.colors[i], res.colors[tile_size - 1 - i]);
}
}
@@ -382,7 +385,7 @@ namespace nes::sys
if (addr % 0x4000 <= address{ 0x3EFF })
{
- std::swap(res, ppudata_read_buffer_);
+ swap(res, ppudata_read_buffer_);
}
else
{
diff --git a/lib/nes/sys/ppu.hh b/lib/nes/sys/ppu.hh
index 5697081..898ddd3 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/sys/types/snapshot.hh"
#include "nes/common/containers/span.hh"
#include "nes/common/types.hh"
@@ -15,7 +16,6 @@ namespace nes::sys
class address;
class cpu;
class cartridge;
- struct snapshot;
class ppu
{
@@ -239,7 +239,9 @@ namespace nes::sys
auto operator=(ppu&&) -> ppu& = delete;
auto get_cycles() const -> cycle_count { return current_cycles_; }
+#ifdef NES_ENABLE_SNAPSHOTS
auto build_snapshot(snapshot&) -> void;
+#endif
auto step() -> void;
// Memory access
diff --git a/lib/nes/sys/types/cycle-count.hh b/lib/nes/sys/types/cycle-count.hh
index c977d1d..2368008 100644
--- a/lib/nes/sys/types/cycle-count.hh
+++ b/lib/nes/sys/types/cycle-count.hh
@@ -1,7 +1,6 @@
#pragma once
#include "nes/common/types.hh"
-#include <chrono>
namespace nes::sys
{
@@ -34,9 +33,9 @@ namespace nes::sys
return cycle_count{ units };
}
- static constexpr auto from_duration(std::chrono::microseconds const duration) -> cycle_count
+ static constexpr auto from_microseconds(u64 const microseconds) -> cycle_count
{
- return from_units(static_cast<u64>(duration.count()) * second().get_units() / (1000 * 1000));
+ return from_units(microseconds * second().get_units() / (1000 * 1000));
}
static constexpr auto from_cpu(u64 const cpu_cycles) -> cycle_count
@@ -52,9 +51,9 @@ namespace nes::sys
/// Value in implementation-defined units.
constexpr auto get_units() const -> u64 { return units_; }
- constexpr auto to_duration() const -> std::chrono::microseconds
+ constexpr auto to_microseconds() const -> u64
{
- return std::chrono::microseconds{ get_units() * 1000 * 1000 / second().get_units() };
+ return get_units() * 1000 * 1000 / second().get_units();
}
constexpr auto to_cpu() const -> u64
diff --git a/lib/nes/sys/types/snapshot.hh b/lib/nes/sys/types/snapshot.hh
index c057aeb..ff3f6a6 100644
--- a/lib/nes/sys/types/snapshot.hh
+++ b/lib/nes/sys/types/snapshot.hh
@@ -1,5 +1,7 @@
#pragma once
+#ifdef NES_ENABLE_SNAPSHOTS
+
#include "nes/sys/types/cycle-count.hh"
#include "nes/common/types.hh"
#include <vector>
@@ -60,4 +62,6 @@ namespace nes::sys
}
inline auto operator!=(snapshot const& a, snapshot const& b) -> bool { return !(a == b); }
-} // namespace nes::sys \ No newline at end of file
+} // namespace nes::sys
+
+#endif \ No newline at end of file