summaryrefslogtreecommitdiff
path: root/lib/nes
diff options
context:
space:
mode:
authorHannes Schulze <haschu0103@outlook.de>2025-02-01 01:25:15 +0100
committerHannes Schulze <haschu0103@outlook.de>2025-02-01 01:25:15 +0100
commitcbde52a60605a4fe853d3a3562b2a059e2143e6e (patch)
treea32ce689b17bab4b27025d437a51ce855eca043e /lib/nes
parent9ca793417149cbaa7b5f4b7797bc929e6e191f28 (diff)
avoid copy construction for cartridge
Diffstat (limited to 'lib/nes')
-rw-r--r--lib/nes/app/application.cc17
-rw-r--r--lib/nes/sys/cartridge.cc60
-rw-r--r--lib/nes/sys/cartridge.hh10
-rw-r--r--lib/nes/sys/nes.cc4
-rw-r--r--lib/nes/sys/nes.hh6
-rw-r--r--lib/nes/sys/types/status.hh3
6 files changed, 40 insertions, 60 deletions
diff --git a/lib/nes/app/application.cc b/lib/nes/app/application.cc
index 0c1a4cb..264e07a 100644
--- a/lib/nes/app/application.cc
+++ b/lib/nes/app/application.cc
@@ -4,7 +4,7 @@
#include "nes/app/ui/screen.hh"
#include "nes/app/graphics/renderer.hh"
#include "ui/action.hh"
-
+#include <fstream>
#include <iostream>
namespace nes::app
@@ -74,7 +74,20 @@ namespace nes::app
}
case action::load_game:
{
- console_.emplace(sys::cartridge::from_file(file), display_);
+ auto stream = std::ifstream{ file, std::ios::binary };
+ if (!stream.good())
+ {
+ std::cerr << "Unable to open cartridge file!" << std::endl;
+ std::abort();
+ }
+
+ stream.seekg(0, std::ios::end);
+ auto const length = stream.tellg();
+ stream.seekg(0, std::ios::beg);
+ auto data = std::vector<u8>(static_cast<u32>(length));
+ stream.read(reinterpret_cast<char*>(data.data()), length);
+
+ console_.emplace(display_, data.data(), static_cast<u32>(length));
if (console_->get_status() != sys::status::success)
{
std::cerr << "Unable to load cartridge: " << to_string(console_->get_status()) << std::endl;
diff --git a/lib/nes/sys/cartridge.cc b/lib/nes/sys/cartridge.cc
index 43f9430..fcb7e84 100644
--- a/lib/nes/sys/cartridge.cc
+++ b/lib/nes/sys/cartridge.cc
@@ -5,68 +5,44 @@
namespace nes::sys
{
- cartridge::cartridge(status const status)
- : status_{ status }
- {
- }
-
- auto cartridge::from_data(void const* data, u32 const length) -> cartridge
+ cartridge::cartridge(u8 const* data, u32 const length)
{
// See: https://www.nesdev.org/wiki/INES
auto const bytes = static_cast<u8 const*>(data);
- auto res = cartridge{ status::success };
// Parse header.
- if (length < header_length) { return cartridge{ status::error_invalid_ines_data }; }
+ if (length < header_length) { return; }
auto const h = header{ bytes };
if (h.get_magic_0() != 'N' || h.get_magic_1() != 'E' || h.get_magic_2() != 'S' || h.get_magic_3() != 0x1A)
{
- return cartridge{ status::error_invalid_ines_data };
+ return;
}
auto const mapper_number = static_cast<u8>((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0));
- res.mapper_ = &mapper::get(mapper_number);
- res.name_table_arrangement_ = h.get_name_table_arrangement();
+ mapper_ = &mapper::get(mapper_number);
+ name_table_arrangement_ = h.get_name_table_arrangement();
// Load program data.
auto offset = u32{ 16 };
if (h.get_has_trainer()) { offset += 512; }
- 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_);
+ prg_rom_size_ = h.get_prg_rom_banks() * prg_rom_bank_size;
+ if (length < offset + prg_rom_size_) { return; }
+ if (prg_rom_size_ > max_prg_rom_size) { return; }
+ std::copy_n(&bytes[offset], prg_rom_size_, prg_rom_);
- offset += res.prg_rom_size_;
+ offset += prg_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_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)
- {
- return cartridge{ status };
- }
-
- return res;
- }
-
- auto cartridge::from_file(std::string_view const path) -> cartridge
- {
- auto stream = std::ifstream{ path, std::ios::binary };
- if (!stream.good()) { return cartridge{ status::error_system_error }; }
+ chr_rom_size_ = h.get_chr_rom_banks() * chr_rom_bank_size;
+ if (length < offset + chr_rom_size_) { return; }
+ if (chr_rom_size_ > max_chr_rom_size) { return; }
+ std::copy_n(&bytes[offset], chr_rom_size_, chr_rom_);
- stream.seekg(0, std::ios::end);
- auto const length = stream.tellg();
- stream.seekg(0, std::ios::beg);
- auto data = std::vector<u8>(static_cast<u32>(length));
- stream.read(reinterpret_cast<char*>(data.data()), length);
+ ram_size_ = std::max(h.get_ram_banks(), 1u) * ram_bank_size;
+ if (ram_size_ > max_ram_size) { return; }
- return from_data(data.data(), static_cast<u32>(length));
+ status_ = get_mapper().validate(*this);
+ if (status_ != status::success) { return; }
}
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/cartridge.hh b/lib/nes/sys/cartridge.hh
index f8c3c3b..2cfb114 100644
--- a/lib/nes/sys/cartridge.hh
+++ b/lib/nes/sys/cartridge.hh
@@ -51,7 +51,7 @@ namespace nes::sys
}
};
- status status_{ status::error_uninitialized };
+ status status_{ status::error_invalid_ines_data };
u8 prg_rom_[max_prg_rom_size]{};
u8 chr_rom_[max_chr_rom_size]{};
u8 ram_[max_ram_size]{};
@@ -62,10 +62,7 @@ namespace nes::sys
mapper* mapper_{ &mapper::invalid() };
public:
- explicit cartridge() = default;
-
- static auto from_data(void const* data, u32 length) -> cartridge;
- static auto from_file(std::string_view path) -> cartridge;
+ explicit cartridge(u8 const* data, u32 length);
auto get_status() const -> status { return status_; }
auto get_prg_rom() const -> u8 const* { return prg_rom_; }
@@ -77,8 +74,5 @@ namespace nes::sys
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_; }
-
- private:
- explicit cartridge(status);
};
} // namespace nes::sys \ No newline at end of file
diff --git a/lib/nes/sys/nes.cc b/lib/nes/sys/nes.cc
index a711f06..3195826 100644
--- a/lib/nes/sys/nes.cc
+++ b/lib/nes/sys/nes.cc
@@ -3,8 +3,8 @@
namespace nes::sys
{
- nes::nes(cartridge const& cartridge, display& display)
- : cartridge_{ std::move(cartridge) }
+ nes::nes(display& display, u8 const* rom_data, u32 rom_length)
+ : cartridge_{ rom_data, rom_length }
, display_{ display }
, ppu_{ cpu_, cartridge_, display_ }
, cpu_{ ppu_, cartridge_, controller_1_, controller_2_ }
diff --git a/lib/nes/sys/nes.hh b/lib/nes/sys/nes.hh
index 4150935..5e081b3 100644
--- a/lib/nes/sys/nes.hh
+++ b/lib/nes/sys/nes.hh
@@ -5,6 +5,7 @@
#include "nes/sys/controller.hh"
#include "nes/sys/cpu.hh"
#include "nes/sys/ppu.hh"
+#include <string_view>
namespace nes
{
@@ -25,11 +26,10 @@ namespace nes::sys
ppu ppu_;
cpu cpu_;
cycle_count current_cycles_;
- status status_{ status::success };
+ status status_{ status::error_invalid_ines_data };
public:
- // TODO: Don't copy cartridge
- explicit nes(cartridge const&, display&);
+ explicit nes(display&, u8 const* rom_data, u32 rom_length);
nes(nes const&) = delete;
nes(nes&&) = delete;
diff --git a/lib/nes/sys/types/status.hh b/lib/nes/sys/types/status.hh
index c622ffb..9b1e824 100644
--- a/lib/nes/sys/types/status.hh
+++ b/lib/nes/sys/types/status.hh
@@ -6,7 +6,6 @@ namespace nes::sys
enum class status
{
success,
- error_uninitialized,
error_system_error,
error_invalid_ines_data,
error_unsupported_mapper,
@@ -19,8 +18,6 @@ namespace nes::sys
{
case status::success:
return "Success";
- case status::error_uninitialized:
- return "Uninitialized";
case status::error_system_error:
return "System error";
case status::error_invalid_ines_data: