diff options
Diffstat (limited to 'lib/nes/sys')
| -rw-r--r-- | lib/nes/sys/cartridge.cc | 32 | ||||
| -rw-r--r-- | lib/nes/sys/cartridge.hh | 66 | ||||
| -rw-r--r-- | lib/nes/sys/controller.cc | 6 | ||||
| -rw-r--r-- | lib/nes/sys/controller.hh | 7 | ||||
| -rw-r--r-- | lib/nes/sys/cpu.cc | 88 | ||||
| -rw-r--r-- | lib/nes/sys/cpu.hh | 71 | ||||
| -rw-r--r-- | lib/nes/sys/mapper.cc | 20 | ||||
| -rw-r--r-- | lib/nes/sys/mapper.hh | 11 | ||||
| -rw-r--r-- | lib/nes/sys/nes.cc | 4 | ||||
| -rw-r--r-- | lib/nes/sys/nes.hh | 3 | ||||
| -rw-r--r-- | lib/nes/sys/ppu.cc | 70 | ||||
| -rw-r--r-- | lib/nes/sys/ppu.hh | 135 | ||||
| -rw-r--r-- | lib/nes/sys/types/address.hh | 36 | ||||
| -rw-r--r-- | lib/nes/sys/types/button-mask.hh | 10 | ||||
| -rw-r--r-- | lib/nes/sys/types/cycle-count.hh | 33 | ||||
| -rw-r--r-- | lib/nes/sys/types/snapshot.hh | 22 |
16 files changed, 314 insertions, 300 deletions
diff --git a/lib/nes/sys/cartridge.cc b/lib/nes/sys/cartridge.cc index 9697185..43f9430 100644 --- a/lib/nes/sys/cartridge.cc +++ b/lib/nes/sys/cartridge.cc @@ -1,6 +1,7 @@ #include "nes/sys/cartridge.hh" #include "nes/sys/types/status.hh" #include <fstream> +#include <algorithm> namespace nes::sys { @@ -9,11 +10,11 @@ namespace nes::sys { } - auto cartridge::from_data(void const* data, std::size_t const length) -> cartridge + auto cartridge::from_data(void const* data, u32 const length) -> cartridge { // See: https://www.nesdev.org/wiki/INES - auto const bytes = static_cast<std::uint8_t const*>(data); + auto const bytes = static_cast<u8 const*>(data); auto res = cartridge{ status::success }; // Parse header. @@ -23,26 +24,29 @@ namespace nes::sys { return cartridge{ status::error_invalid_ines_data }; } - auto const mapper_number = static_cast<std::uint8_t>((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0)); + auto const mapper_number = static_cast<u8>((h.get_mapper_high() << 4) | (h.get_mapper_low() << 0)); res.mapper_ = &mapper::get(mapper_number); res.name_table_arrangement_ = h.get_name_table_arrangement(); // Load program data. - auto offset = std::size_t{ 16 }; + auto offset = u32{ 16 }; if (h.get_has_trainer()) { offset += 512; } - auto const prg_rom_size = h.get_prg_rom_banks() * prg_rom_bank_size; - if (length < offset + prg_rom_size) { return cartridge{ status::error_invalid_ines_data }; } - res.prg_rom_ = std::vector(&bytes[offset], &bytes[offset + prg_rom_size]); + res.prg_rom_size_ = h.get_prg_rom_banks() * prg_rom_bank_size; + if (length < offset + res.prg_rom_size_) { return cartridge{ status::error_invalid_ines_data }; } + if (res.prg_rom_size_ > max_prg_rom_size) { return cartridge{ status::error_invalid_ines_data }; } + std::copy_n(&bytes[offset], res.prg_rom_size_, res.prg_rom_); - offset += prg_rom_size; + offset += res.prg_rom_size_; - auto const chr_rom_size = h.get_chr_rom_banks() * chr_rom_bank_size; - if (length < offset + chr_rom_size) { return cartridge{ status::error_invalid_ines_data }; } - res.chr_rom_ = std::vector(&bytes[offset], &bytes[offset + chr_rom_size]); + res.chr_rom_size_ = h.get_chr_rom_banks() * chr_rom_bank_size; + if (length < offset + res.chr_rom_size_) { return cartridge{ status::error_invalid_ines_data }; } + if (res.chr_rom_size_ > max_chr_rom_size) { return cartridge{ status::error_invalid_ines_data }; } + std::copy_n(&bytes[offset], res.chr_rom_size_, res.chr_rom_); - res.ram_ = std::vector(std::max(h.get_ram_banks(), 1u) * ram_bank_size, std::uint8_t{ 0 }); + res.ram_size_ = std::max(h.get_ram_banks(), 1u) * ram_bank_size; + if (res.ram_size_ > max_ram_size) { return cartridge{ status::error_invalid_ines_data }; } if (auto const status = res.get_mapper().validate(res); status != status::success) { @@ -60,9 +64,9 @@ namespace nes::sys stream.seekg(0, std::ios::end); auto const length = stream.tellg(); stream.seekg(0, std::ios::beg); - auto data = std::vector<std::uint8_t>(static_cast<std::size_t>(length)); + auto data = std::vector<u8>(static_cast<u32>(length)); stream.read(reinterpret_cast<char*>(data.data()), length); - return from_data(data.data(), data.size()); + return from_data(data.data(), static_cast<u32>(length)); } } // namespace nes::sys
\ No newline at end of file diff --git a/lib/nes/sys/cartridge.hh b/lib/nes/sys/cartridge.hh index d82af84..f8c3c3b 100644 --- a/lib/nes/sys/cartridge.hh +++ b/lib/nes/sys/cartridge.hh @@ -2,7 +2,7 @@ #include "nes/sys/types/status.hh" #include "nes/sys/mapper.hh" -#include <cstddef> +#include "nes/common/types.hh" #include <vector> #include <string_view> @@ -16,32 +16,35 @@ namespace nes::sys class cartridge { - static constexpr auto prg_rom_bank_size = std::size_t{ 16 * 1024 }; - static constexpr auto chr_rom_bank_size = std::size_t{ 8 * 1024 }; - static constexpr auto ram_bank_size = std::size_t{ 8 * 1024 }; - static constexpr auto header_length = std::size_t{ 16 }; + static constexpr auto prg_rom_bank_size = u32{ 16 * 1024 }; + static constexpr auto chr_rom_bank_size = u32{ 8 * 1024 }; + static constexpr auto ram_bank_size = u32{ 8 * 1024 }; + static constexpr auto max_prg_rom_size = u32{ 4 * prg_rom_bank_size }; + static constexpr auto max_chr_rom_size = u32{ 4 * chr_rom_bank_size }; + static constexpr auto max_ram_size = u32{ 4 * ram_bank_size }; + static constexpr auto header_length = u32{ 16 }; struct header { - auto get_magic_0() const -> std::uint8_t { return value[0]; } - auto get_magic_1() const -> std::uint8_t { return value[1]; } - auto get_magic_2() const -> std::uint8_t { return value[2]; } - auto get_magic_3() const -> std::uint8_t { return value[3]; } - auto get_prg_rom_banks() const -> unsigned { return value[4]; } - auto get_chr_rom_banks() const -> unsigned { return value[5]; } - auto get_control_1() const -> std::uint8_t { return value[6]; } - auto get_control_2() const -> std::uint8_t { return value[7]; } - auto get_ram_banks() const -> unsigned { return value[8]; } + auto get_magic_0() const -> u8 { return value[0]; } + auto get_magic_1() const -> u8 { return value[1]; } + auto get_magic_2() const -> u8 { return value[2]; } + auto get_magic_3() const -> u8 { return value[3]; } + auto get_prg_rom_banks() const -> u32 { return value[4]; } + auto get_chr_rom_banks() const -> u32 { return value[5]; } + auto get_control_1() const -> u8 { return value[6]; } + auto get_control_2() const -> u8 { return value[7]; } + auto get_ram_banks() const -> u32 { return value[8]; } auto get_has_trainer() const -> bool { return get_control_1() & 0b00000100; } - auto get_mapper_low() const -> unsigned { return (get_control_1() & 0b11110000) >> 4; } - auto get_mapper_high() const -> unsigned { return (get_control_2() & 0b11110000) >> 0; } + auto get_mapper_low() const -> u32 { return (get_control_1() & 0b11110000) >> 4; } + auto get_mapper_high() const -> u32 { return (get_control_2() & 0b11110000) >> 0; } auto get_name_table_arrangement() const -> name_table_arrangement { return static_cast<name_table_arrangement>((get_control_1() & 0b00000001) >> 0); } - std::uint8_t value[header_length]{}; + u8 value[header_length]{}; - explicit header(std::uint8_t const* v) + explicit header(u8 const* v) { - for (auto i = std::size_t{ 0 }; i < header_length; ++i) + for (auto i = u32{ 0 }; i < header_length; ++i) { value[i] = v[i]; } @@ -49,26 +52,29 @@ namespace nes::sys }; status status_{ status::error_uninitialized }; - std::vector<std::uint8_t> prg_rom_; - std::vector<std::uint8_t> chr_rom_; - std::vector<std::uint8_t> ram_; + u8 prg_rom_[max_prg_rom_size]{}; + u8 chr_rom_[max_chr_rom_size]{}; + u8 ram_[max_ram_size]{}; + u32 prg_rom_size_{}; + u32 chr_rom_size_{}; + u32 ram_size_{}; name_table_arrangement name_table_arrangement_{}; mapper* mapper_{ &mapper::invalid() }; public: explicit cartridge() = default; - static auto from_data(void const* data, std::size_t length) -> cartridge; + static auto from_data(void const* data, u32 length) -> cartridge; static auto from_file(std::string_view path) -> cartridge; auto get_status() const -> status { return status_; } - auto get_prg_rom() const -> std::uint8_t const* { return prg_rom_.data(); } - auto get_prg_rom_length() const -> std::size_t { return prg_rom_.size(); } - auto get_chr_rom() const -> std::uint8_t const* { return chr_rom_.data(); } - auto get_chr_rom_length() const -> std::size_t { return chr_rom_.size(); } - auto get_ram() const -> std::uint8_t const* { return ram_.data(); } - auto get_ram_mut() -> std::uint8_t* { return ram_.data(); } - auto get_ram_length() const -> std::size_t { return ram_.size(); } + auto get_prg_rom() const -> u8 const* { return prg_rom_; } + auto get_prg_rom_length() const -> u32 { return prg_rom_size_; } + auto get_chr_rom() const -> u8 const* { return chr_rom_; } + auto get_chr_rom_length() const -> u32 { return chr_rom_size_; } + auto get_ram() const -> u8 const* { return ram_; } + auto get_ram_mut() -> u8* { return ram_; } + auto get_ram_length() const -> u32 { return ram_size_; } auto get_mapper() const -> mapper& { return *mapper_; } auto get_name_table_arrangement() const -> name_table_arrangement { return name_table_arrangement_; } diff --git a/lib/nes/sys/controller.cc b/lib/nes/sys/controller.cc index 92dd897..d653f44 100644 --- a/lib/nes/sys/controller.cc +++ b/lib/nes/sys/controller.cc @@ -2,15 +2,15 @@ namespace nes::sys { - auto controller::read() -> std::uint8_t + auto controller::read() -> u8 { auto const res = index_ < 8 ? (pressed_.get_raw_value() >> index_) & 1 : 0; index_ += 1; if (strobing_) { index_ = 0; } - return static_cast<std::uint8_t>(res); + return static_cast<u8>(res); } - auto controller::write(std::uint8_t const value) -> void + auto controller::write(u8 const value) -> void { strobing_ = value & 1; if (strobing_) { index_ = 0; } diff --git a/lib/nes/sys/controller.hh b/lib/nes/sys/controller.hh index d3a32fd..c330365 100644 --- a/lib/nes/sys/controller.hh +++ b/lib/nes/sys/controller.hh @@ -1,13 +1,14 @@ #pragma once #include "nes/sys/types/button-mask.hh" +#include "nes/common/types.hh" namespace nes::sys { class controller { button_mask pressed_; - unsigned index_{ 0 }; + u32 index_{ 0 }; bool strobing_{ false }; public: @@ -24,7 +25,7 @@ namespace nes::sys // IO register - auto read() -> std::uint8_t; - auto write(std::uint8_t) -> void; + auto read() -> u8; + auto write(u8) -> void; }; } // namespace nes::sys
\ No newline at end of file diff --git a/lib/nes/sys/cpu.cc b/lib/nes/sys/cpu.cc index 8b05f66..09e2094 100644 --- a/lib/nes/sys/cpu.cc +++ b/lib/nes/sys/cpu.cc @@ -541,7 +541,7 @@ namespace nes::sys // LSR: Logical Shift Right auto operand = fetch_operand<Mode>(); auto const old_val = operand.read(); - auto const new_val = static_cast<std::uint8_t>(old_val >> 1); + auto const new_val = static_cast<u8>(old_val >> 1); operand.write(new_val); registers_.p.set_c((old_val & 0x1) != 0); update_zn(new_val); @@ -692,7 +692,7 @@ namespace nes::sys { // SAX: AND A X auto operand = fetch_operand<Mode>(); - auto const result = static_cast<std::uint8_t>(registers_.a & registers_.x); + auto const result = static_cast<u8>(registers_.a & registers_.x); operand.write(result); current_cycles_ += operand.get_cycles(); return status::success; @@ -921,7 +921,7 @@ namespace nes::sys { // DCP: DEC + CMP auto operand = fetch_operand<Mode>(force_page_crossing::yes); - auto const tmp = static_cast<std::uint8_t>(operand.read() - 1); + auto const tmp = static_cast<u8>(operand.read() - 1); operand.write(tmp); eval_cmp(registers_.a, tmp); current_cycles_ += operand.get_cycles() + cycle_count::from_cpu(2); @@ -934,7 +934,7 @@ namespace nes::sys // DEC: Decrement Memory auto operand = fetch_operand<Mode>(); auto const old_val = read8(operand.get_address()); - auto const new_val = static_cast<std::uint8_t>(old_val - 1); + auto const new_val = static_cast<u8>(old_val - 1); write8(operand.get_address(), new_val); update_zn(new_val); current_cycles_ += inc_dec_cycle_count<Mode>(); @@ -1000,7 +1000,7 @@ namespace nes::sys { // ISC: INC + SBC auto operand = fetch_operand<Mode>(force_page_crossing::yes); - auto const tmp = static_cast<std::uint8_t>(operand.read() + 1); + auto const tmp = static_cast<u8>(operand.read() + 1); operand.write(tmp); eval_adc(~tmp); current_cycles_ += operand.get_cycles() + cycle_count::from_cpu(2); @@ -1013,7 +1013,7 @@ namespace nes::sys // INC: Increment Memory auto operand = fetch_operand<Mode>(); auto const old_val = read8(operand.get_address()); - auto const new_val = static_cast<std::uint8_t>(old_val + 1); + auto const new_val = static_cast<u8>(old_val + 1); write8(operand.get_address(), new_val); update_zn(new_val); current_cycles_ += inc_dec_cycle_count<Mode>(); @@ -1049,48 +1049,48 @@ namespace nes::sys // Helpers // ----------------------------------------------------------------------------------------------------------------- - auto cpu::advance_pc8() -> std::uint8_t + auto cpu::advance_pc8() -> u8 { auto const val = read8(address{ registers_.pc }); registers_.pc += 1; return val; } - auto cpu::advance_pc16() -> std::uint16_t + auto cpu::advance_pc16() -> u16 { auto const val = read16(address{ registers_.pc }); registers_.pc += 2; return val; } - auto cpu::push_stack8(std::uint8_t const value) -> void + auto cpu::push_stack8(u8 const value) -> void { write8(stack_offset + registers_.sp, value); registers_.sp -= 1; } - auto cpu::push_stack16(std::uint16_t const value) -> void + auto cpu::push_stack16(u16 const value) -> void { - auto const low = static_cast<std::uint8_t>(value >> 0 & 0xFF); - auto const high = static_cast<std::uint8_t>(value >> 8 & 0xFF); + auto const low = static_cast<u8>(value >> 0 & 0xFF); + auto const high = static_cast<u8>(value >> 8 & 0xFF); push_stack8(high); push_stack8(low); } - auto cpu::pop_stack8() -> std::uint8_t + auto cpu::pop_stack8() -> u8 { registers_.sp += 1; return read8(stack_offset + registers_.sp); } - auto cpu::pop_stack16() -> std::uint16_t + auto cpu::pop_stack16() -> u16 { auto const low = pop_stack8(); auto const high = pop_stack8(); - return static_cast<std::uint16_t>((high << 8) | (low << 0)); + return static_cast<u16>((high << 8) | (low << 0)); } - auto cpu::update_zn(std::uint8_t const value) -> void + auto cpu::update_zn(u8 const value) -> void { registers_.p.set_z(value == 0); registers_.p.set_n((value & 0x80) != 0); @@ -1122,43 +1122,43 @@ namespace nes::sys current_cycles_ += cycle_count::from_cpu(7); } - auto cpu::eval_ror(std::uint8_t const arg) -> std::uint8_t + auto cpu::eval_ror(u8 const arg) -> u8 { - auto const res = static_cast<std::uint8_t>(((registers_.p.get_c() ? 1 :0) << 7) | (arg >> 1)); + auto const res = static_cast<u8>(((registers_.p.get_c() ? 1 :0) << 7) | (arg >> 1)); registers_.p.set_c((arg & 0x1) != 0); update_zn(res); return res; } - auto cpu::eval_rol(std::uint8_t const arg) -> std::uint8_t + auto cpu::eval_rol(u8 const arg) -> u8 { - auto const res = static_cast<std::uint8_t>((arg << 1) | (registers_.p.get_c() ? 1 : 0)); + auto const res = static_cast<u8>((arg << 1) | (registers_.p.get_c() ? 1 : 0)); registers_.p.set_c((arg & 0x80) != 0); update_zn(res); return res; } - auto cpu::eval_asl(std::uint8_t const arg) -> std::uint8_t + auto cpu::eval_asl(u8 const arg) -> u8 { - auto const new_val = static_cast<std::uint8_t>(arg << 1); + auto const new_val = static_cast<u8>(arg << 1); registers_.p.set_c((arg & 0x80) != 0); update_zn(new_val); return new_val; } - auto cpu::eval_lsr(std::uint8_t const arg) -> std::uint8_t + auto cpu::eval_lsr(u8 const arg) -> u8 { - auto const new_val = static_cast<std::uint8_t>(arg >> 1); + auto const new_val = static_cast<u8>(arg >> 1); registers_.p.set_c((arg & 0x01) != 0); update_zn(new_val); return new_val; } - auto cpu::eval_adc(std::uint8_t const arg) -> void + auto cpu::eval_adc(u8 const arg) -> void { auto const old_val = registers_.a; auto const tmp = old_val + arg + (registers_.p.get_c() ? 1 : 0); - auto const new_val = static_cast<std::uint8_t>(tmp); + auto const new_val = static_cast<u8>(tmp); registers_.a = new_val; registers_.p.set_c(tmp > 0xFF); @@ -1166,25 +1166,25 @@ namespace nes::sys update_zn(registers_.a); } - auto cpu::eval_and(std::uint8_t const arg) -> void + auto cpu::eval_and(u8 const arg) -> void { registers_.a &= arg; update_zn(registers_.a); } - auto cpu::eval_ora(std::uint8_t const arg) -> void + auto cpu::eval_ora(u8 const arg) -> void { registers_.a |= arg; update_zn(registers_.a); } - auto cpu::eval_eor(std::uint8_t const arg) -> void + auto cpu::eval_eor(u8 const arg) -> void { registers_.a ^= arg; update_zn(registers_.a); } - auto cpu::eval_cmp(std::uint8_t const a, std::uint8_t const b) -> void + auto cpu::eval_cmp(u8 const a, u8 const b) -> void { update_zn(a - b); registers_.p.set_c(a >= b); @@ -1238,7 +1238,7 @@ namespace nes::sys { auto const offset = static_cast<std::int8_t>(advance_pc8()); auto const base = address{ registers_.pc }; - addr = address{ static_cast<std::uint16_t>(registers_.pc + offset) }; + addr = address{ static_cast<u16>(registers_.pc + offset) }; auto const page_crossing = base.get_page() != addr.get_page() || force_page_crossing == force_page_crossing::yes; cycles = cycle_count::from_cpu(page_crossing ? 4 : 3); @@ -1257,14 +1257,14 @@ namespace nes::sys case addressing_mode::zero_page_indexed_x: { // PEEK((arg + X) % 256) - addr = address{ 0x00, static_cast<std::uint8_t>(advance_pc8() + registers_.x) }; + addr = address{ 0x00, static_cast<u8>(advance_pc8() + registers_.x) }; cycles = cycle_count::from_cpu(4); break; } case addressing_mode::zero_page_indexed_y: { // PEEK((arg + Y) % 256) - addr = address{ 0x00, static_cast<std::uint8_t>(advance_pc8() + registers_.y) }; + addr = address{ 0x00, static_cast<u8>(advance_pc8() + registers_.y) }; cycles = cycle_count::from_cpu(4); break; } @@ -1292,8 +1292,8 @@ namespace nes::sys { // PEEK(PEEK((arg + X) % 256) + PEEK((arg + X + 1) % 256) * 256) auto const arg = advance_pc8(); - auto const page = read8(address{ 0x00, static_cast<std::uint8_t>(arg + registers_.x + 1) }); - auto const offset = read8(address{ 0x00, static_cast<std::uint8_t>(arg + registers_.x) }); + auto const page = read8(address{ 0x00, static_cast<u8>(arg + registers_.x + 1) }); + auto const offset = read8(address{ 0x00, static_cast<u8>(arg + registers_.x) }); addr = address{ page, offset }; cycles = cycle_count::from_cpu(6); break; @@ -1302,8 +1302,8 @@ namespace nes::sys { // PEEK(PEEK(arg) + PEEK((arg + 1) % 256) * 256 + Y) auto const arg = advance_pc8(); - auto const page = read8(address{ 0x00, static_cast<std::uint8_t>(arg + 1) }); - auto const offset = read8(address{ 0x00, static_cast<std::uint8_t>(arg) }); + auto const page = read8(address{ 0x00, static_cast<u8>(arg + 1) }); + auto const offset = read8(address{ 0x00, static_cast<u8>(arg) }); auto const base = address{ page, offset }; addr = base + registers_.y; auto const page_crossing = @@ -1338,7 +1338,7 @@ namespace nes::sys // See: https://www.nesdev.org/wiki/CPU_memory_map // - auto cpu::read8(address const addr) -> std::uint8_t + auto cpu::read8(address const addr) -> u8 { if (addr <= address{ 0x1FFF }) { return ram_[addr.get_absolute() % ram_size]; } if (addr <= address{ 0x3FFF }) @@ -1373,14 +1373,14 @@ namespace nes::sys return cartridge_.get_mapper().read_cpu(addr, cartridge_); } - auto cpu::read16(address const addr) -> std::uint16_t + auto cpu::read16(address const addr) -> u16 { auto const low = read8(addr + 0); auto const high = read8(addr + 1); - return static_cast<std::uint16_t>((high << 8) | (low << 0)); + return static_cast<u16>((high << 8) | (low << 0)); } - auto cpu::write8(address const addr, std::uint8_t const value) -> void + auto cpu::write8(address const addr, u8 const value) -> void { if (addr <= address{ 0x1FFF }) { ram_[addr.get_absolute() % ram_size] = value; return; } if (addr <= address{ 0x3FFF }) @@ -1415,10 +1415,10 @@ namespace nes::sys cartridge_.get_mapper().write_cpu(addr, value, cartridge_); } - auto cpu::write16(address const addr, std::uint16_t const value) -> void + auto cpu::write16(address const addr, u16 const value) -> void { - auto const low = static_cast<std::uint8_t>(value >> 0 & 0xFF); - auto const high = static_cast<std::uint8_t>(value >> 8 & 0xFF); + auto const low = static_cast<u8>(value >> 0 & 0xFF); + auto const high = static_cast<u8>(value >> 8 & 0xFF); write8(addr + 0, low); write8(addr + 1, high); } diff --git a/lib/nes/sys/cpu.hh b/lib/nes/sys/cpu.hh index 2702c20..5d6466f 100644 --- a/lib/nes/sys/cpu.hh +++ b/lib/nes/sys/cpu.hh @@ -3,6 +3,7 @@ #include "nes/sys/types/cycle-count.hh" #include "nes/sys/types/address.hh" #include "nes/sys/types/status.hh" +#include "nes/common/types.hh" namespace nes::sys { @@ -13,7 +14,7 @@ namespace nes::sys class cpu { - static constexpr auto ram_size = std::size_t{ 0x800 }; + static constexpr auto ram_size = u32{ 0x800 }; static constexpr auto stack_offset = address{ 0x100 }; cycle_count current_cycles_; @@ -21,17 +22,17 @@ namespace nes::sys cartridge& cartridge_; controller& controller_1_; controller& controller_2_; - std::uint8_t ram_[ram_size]{}; + u8 ram_[ram_size]{}; bool nmi_pending_{ false }; // Registers struct { - std::uint16_t pc{ 0 }; - std::uint8_t sp{ 0xFD }; - std::uint8_t a{ 0 }; - std::uint8_t x{ 0 }; - std::uint8_t y{ 0 }; + u16 pc{ 0 }; + u8 sp{ 0xFD }; + u8 a{ 0 }; + u8 x{ 0 }; + u8 y{ 0 }; struct { auto get_c() const -> bool { return value & 0b00000001; } // carry @@ -50,7 +51,7 @@ namespace nes::sys auto set_v(bool const v) -> void { value = (value & ~0b01000000) | (v ? 0b01000000 : 0); } auto set_n(bool const v) -> void { value = (value & ~0b10000000) | (v ? 0b10000000 : 0); } - std::uint8_t value{ 0b00100100 }; + u8 value{ 0b00100100 }; } p{}; } registers_{}; @@ -91,8 +92,8 @@ namespace nes::sys { } - auto read() -> std::uint8_t { return cpu_.read8(address_); } - auto write(std::uint8_t const value) -> void { cpu_.write8(address_, value); } + auto read() -> u8 { return cpu_.read8(address_); } + auto write(u8 const value) -> void { cpu_.write8(address_, value); } auto get_address() -> address { return address_; } auto get_cycles() -> cycle_count { return cycles_; } }; @@ -108,23 +109,23 @@ namespace nes::sys { } - auto read() -> std::uint8_t { return cpu_.registers_.a; } - auto write(std::uint8_t const value) -> void { cpu_.registers_.a = value; } + auto read() -> u8 { return cpu_.registers_.a; } + auto write(u8 const value) -> void { cpu_.registers_.a = value; } auto get_cycles() -> cycle_count { return cycle_count::from_cpu(2); } }; template<> class operand<addressing_mode::immediate> { - std::uint8_t value_{ 0 }; + u8 value_{ 0 }; public: - explicit operand(std::uint8_t const value) + explicit operand(u8 const value) : value_{ value } { } - auto read() -> std::uint8_t { return value_; } + auto read() -> u8 { return value_; } auto get_cycles() -> cycle_count { return cycle_count::from_cpu(2); } }; @@ -145,10 +146,10 @@ namespace nes::sys // Memory access - auto read8(address) -> std::uint8_t; - auto read16(address) -> std::uint16_t; - auto write8(address, std::uint8_t) -> void; - auto write16(address, std::uint16_t) -> void; + auto read8(address) -> u8; + auto read16(address) -> u16; + auto write8(address, u8) -> void; + auto write16(address, u16) -> void; private: // Instructions @@ -240,26 +241,26 @@ namespace nes::sys // Helpers - auto advance_pc8() -> std::uint8_t; - auto advance_pc16() -> std::uint16_t; - auto push_stack8(std::uint8_t) -> void; - auto push_stack16(std::uint16_t) -> void; - auto pop_stack8() -> std::uint8_t; - auto pop_stack16() -> std::uint16_t; - auto update_zn(std::uint8_t value) -> void; + auto advance_pc8() -> u8; + auto advance_pc16() -> u16; + auto push_stack8(u8) -> void; + auto push_stack16(u16) -> void; + auto pop_stack8() -> u8; + auto pop_stack16() -> u16; + auto update_zn(u8 value) -> void; template<addressing_mode Mode> auto branch(bool condition) -> void; auto execute_interrupt(address) -> void; - auto eval_ror(std::uint8_t arg) -> std::uint8_t; - auto eval_rol(std::uint8_t arg) -> std::uint8_t; - auto eval_asl(std::uint8_t arg) -> std::uint8_t; - auto eval_lsr(std::uint8_t arg) -> std::uint8_t; - auto eval_adc(std::uint8_t arg) -> void; - auto eval_and(std::uint8_t arg) -> void; - auto eval_ora(std::uint8_t arg) -> void; - auto eval_eor(std::uint8_t arg) -> void; - auto eval_cmp(std::uint8_t a, std::uint8_t b) -> void; + auto eval_ror(u8 arg) -> u8; + auto eval_rol(u8 arg) -> u8; + auto eval_asl(u8 arg) -> u8; + auto eval_lsr(u8 arg) -> u8; + auto eval_adc(u8 arg) -> void; + auto eval_and(u8 arg) -> void; + auto eval_ora(u8 arg) -> void; + auto eval_eor(u8 arg) -> void; + auto eval_cmp(u8 a, u8 b) -> void; auto eval_plp() -> void; auto eval_php() -> void; diff --git a/lib/nes/sys/mapper.cc b/lib/nes/sys/mapper.cc index fc6ec6c..d779076 100644 --- a/lib/nes/sys/mapper.cc +++ b/lib/nes/sys/mapper.cc @@ -34,7 +34,7 @@ namespace nes::sys return status::success; } - auto read_cpu(address const addr, cartridge& cartridge) -> std::uint8_t override + auto read_cpu(address const addr, cartridge& cartridge) -> u8 override { if (addr <= address{ 0x5FFF }) { @@ -59,7 +59,7 @@ namespace nes::sys return 0x0; } - auto write_cpu(address const addr, std::uint8_t const value, cartridge& cartridge) -> void override + auto write_cpu(address const addr, u8 const value, cartridge& cartridge) -> void override { if (addr <= address{ 0x5FFF }) { @@ -72,7 +72,7 @@ namespace nes::sys } } - auto read_ppu(address const addr, cartridge& cartridge, std::uint8_t const* vram) -> std::uint8_t override + auto read_ppu(address const addr, cartridge& cartridge, u8 const* vram) -> u8 override { if (addr <= address{ 0x1FFF }) { @@ -87,7 +87,7 @@ namespace nes::sys return 0x0; } - auto write_ppu(address const addr, std::uint8_t const value, cartridge& cartridge, std::uint8_t* vram) -> void override + auto write_ppu(address const addr, u8 const value, cartridge& cartridge, u8* vram) -> void override { if (addr <= address{ 0x1FFF }) { @@ -101,7 +101,7 @@ namespace nes::sys } private: - static auto mirrored_vram_address(address const addr, cartridge const& cartridge) -> unsigned + static auto mirrored_vram_address(address const addr, cartridge const& cartridge) -> u32 { auto const rel = addr.get_absolute() % 0x1000u; @@ -137,10 +137,10 @@ namespace nes::sys explicit mapper_invalid() = default; auto validate(cartridge&) -> status override { return status::error_unsupported_mapper; } - auto read_cpu(address, cartridge&) -> std::uint8_t override { return 0; } - auto write_cpu(address, std::uint8_t, cartridge&) -> void override {} - auto read_ppu(address, cartridge&, std::uint8_t const*) -> std::uint8_t override { return 0; } - auto write_ppu(address, std::uint8_t, cartridge&, std::uint8_t*) -> void override {} + auto read_cpu(address, cartridge&) -> u8 override { return 0; } + auto write_cpu(address, u8, cartridge&) -> void override {} + auto read_ppu(address, cartridge&, u8 const*) -> u8 override { return 0; } + auto write_ppu(address, u8, cartridge&, u8*) -> void override {} }; } // namespace @@ -154,7 +154,7 @@ namespace nes::sys return instance; } - auto mapper::get(std::uint8_t const number) -> mapper& + auto mapper::get(u8 const number) -> mapper& { switch (number) { diff --git a/lib/nes/sys/mapper.hh b/lib/nes/sys/mapper.hh index 5db198b..c7c9784 100644 --- a/lib/nes/sys/mapper.hh +++ b/lib/nes/sys/mapper.hh @@ -2,6 +2,7 @@ #include "nes/sys/types/address.hh" #include "nes/sys/types/status.hh" +#include "nes/common/types.hh" namespace nes::sys { @@ -11,7 +12,7 @@ namespace nes::sys { public: static auto invalid() -> mapper&; - static auto get(std::uint8_t number) -> mapper&; + static auto get(u8 number) -> mapper&; virtual ~mapper() = default; @@ -21,10 +22,10 @@ namespace nes::sys auto operator=(mapper&&) -> mapper& = delete; virtual auto validate(cartridge&) -> status = 0; - virtual auto read_cpu(address, cartridge&) -> std::uint8_t = 0; - virtual auto write_cpu(address, std::uint8_t, cartridge&) -> void = 0; - virtual auto read_ppu(address, cartridge&, std::uint8_t const* vram) -> std::uint8_t = 0; - virtual auto write_ppu(address, std::uint8_t, cartridge&, std::uint8_t* vram) -> void = 0; + virtual auto read_cpu(address, cartridge&) -> u8 = 0; + virtual auto write_cpu(address, u8, cartridge&) -> void = 0; + virtual auto read_ppu(address, cartridge&, u8 const* vram) -> u8 = 0; + virtual auto write_ppu(address, u8, cartridge&, u8* vram) -> void = 0; protected: explicit mapper() = default; diff --git a/lib/nes/sys/nes.cc b/lib/nes/sys/nes.cc index 6caf6de..a711f06 100644 --- a/lib/nes/sys/nes.cc +++ b/lib/nes/sys/nes.cc @@ -1,11 +1,9 @@ #include "nes/sys/nes.hh" #include "nes/sys/types/snapshot.hh" -#include "nes/common/display.hh" -#include "nes/common/rgb.hh" namespace nes::sys { - nes::nes(cartridge cartridge, display& display) + nes::nes(cartridge const& cartridge, display& display) : cartridge_{ std::move(cartridge) } , display_{ display } , ppu_{ cpu_, cartridge_, display_ } diff --git a/lib/nes/sys/nes.hh b/lib/nes/sys/nes.hh index 4e0fd63..4150935 100644 --- a/lib/nes/sys/nes.hh +++ b/lib/nes/sys/nes.hh @@ -28,7 +28,8 @@ namespace nes::sys status status_{ status::success }; public: - explicit nes(cartridge, display&); + // TODO: Don't copy cartridge + explicit nes(cartridge const&, display&); nes(nes const&) = delete; nes(nes&&) = delete; diff --git a/lib/nes/sys/ppu.cc b/lib/nes/sys/ppu.cc index 00cddbe..c9e6f11 100644 --- a/lib/nes/sys/ppu.cc +++ b/lib/nes/sys/ppu.cc @@ -79,7 +79,7 @@ namespace nes::sys // Load the tile palette for the background from the attribute table. auto const addr = address{ 0x23C0 } + - (static_cast<unsigned>(internal_.v.get_name_table()) * 0x400u) + + (static_cast<u32>(internal_.v.get_name_table()) * 0x400u) + ((internal_.v.get_coarse_y() & 0b11100u) << 1) + ((internal_.v.get_coarse_x() & 0b11100u) >> 2); auto const shift = @@ -190,11 +190,11 @@ namespace nes::sys auto foreground_color = color_index{ 0 }; if (mask_.get_enable_sprites()) { - for (auto i = unsigned{ 0 }; i < sprite_count_; ++i) + for (auto i = u32{ 0 }; i < sprite_count_; ++i) { auto const s = sprites_[i]; auto const offset = static_cast<int>(x) - static_cast<int>(s.x); - if (offset < 0 || static_cast<unsigned>(offset) >= tile_size) { continue; } + if (offset < 0 || static_cast<u32>(offset) >= tile_size) { continue; } auto const color = s.pattern.colors[offset]; if (color.get_color() == palette_color::_0) { continue; } @@ -237,15 +237,15 @@ namespace nes::sys { auto const height = get_sprite_height(); sprite_count_ = 0; - for (auto i = unsigned{ 0 }; i < sprite_max_count; ++i) + for (auto i = u32{ 0 }; i < sprite_max_count; ++i) { auto const s = sprite{ &oam_[i * 4] }; auto const row = static_cast<int>(scanline_) - static_cast<int>(s.get_y()); - if (row < 0 || static_cast<unsigned>(row) >= height) { continue; } + if (row < 0 || static_cast<u32>(row) >= height) { continue; } if (sprite_count_ < 8) { - sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast<unsigned>(row)); + sprites_[sprite_count_].pattern = fetch_sprite_pattern(s, static_cast<u32>(row)); sprites_[sprite_count_].x = s.get_x(); sprites_[sprite_count_].is_in_front = !s.get_behind_background(); sprites_[sprite_count_].is_sprite_zero = i == 0; @@ -259,7 +259,7 @@ namespace nes::sys } } - auto ppu::fetch_sprite_pattern(sprite const s, unsigned row) -> tile_row + auto ppu::fetch_sprite_pattern(sprite const s, u32 row) -> tile_row { if (s.get_flip_vertical()) { row = get_sprite_height() - 1 - row; } tile tile; @@ -289,7 +289,7 @@ namespace nes::sys if (s.get_flip_horizontal()) { - for (auto i = unsigned{ 0 }; i < tile_size / 2; ++i) + for (auto i = u32{ 0 }; i < tile_size / 2; ++i) { std::swap(res.colors[i], res.colors[tile_size - 1 - i]); } @@ -306,21 +306,21 @@ namespace nes::sys // See: https://www.nesdev.org/wiki/PPU_memory_map // - auto ppu::read8(address addr) -> std::uint8_t + auto ppu::read8(address addr) -> u8 { addr = addr % 0x4000; // PPU only has 16 KiB addresses. if (addr <= address{ 0x3EFF }) { return cartridge_.get_mapper().read_ppu(addr, cartridge_, vram_); } if (addr <= address{ 0x3FFF }) { - auto const index = color_index{ static_cast<std::uint8_t>(addr.get_absolute() % 0x20) }; + auto const index = color_index{ static_cast<u8>(addr.get_absolute() % 0x20) }; auto const color = ref_color(index); - return static_cast<std::uint8_t>(color); + return static_cast<u8>(color); } return 0x0; } - auto ppu::write8(address addr, std::uint8_t const value) -> void + auto ppu::write8(address addr, u8 const value) -> void { addr = addr % 0x4000; // PPU only has 16 KiB addresses. if (addr <= address{ 0x3EFF }) @@ -330,7 +330,7 @@ namespace nes::sys } if (addr <= address{ 0x3FFF }) { - auto const index = color_index{ static_cast<std::uint8_t>(addr.get_absolute() % 0x20) }; + auto const index = color_index{ static_cast<u8>(addr.get_absolute() % 0x20) }; ref_color(index) = color{ value }; return; } @@ -344,12 +344,12 @@ namespace nes::sys // See: https://www.nesdev.org/wiki/PPU_registers // - auto ppu::read_latch() -> std::uint8_t + auto ppu::read_latch() -> u8 { return latch_; } - auto ppu::read_ppustatus() -> std::uint8_t + auto ppu::read_ppustatus() -> u8 { auto res = status_; res.set_remaining(latch_); @@ -362,7 +362,7 @@ namespace nes::sys return res.value; } - auto ppu::read_oamdata() -> std::uint8_t + auto ppu::read_oamdata() -> u8 { auto res = oam_[oamaddr_]; if ((oamaddr_ & 0x3) == 0x2) @@ -374,7 +374,7 @@ namespace nes::sys return res; } - auto ppu::read_ppudata() -> std::uint8_t + auto ppu::read_ppudata() -> u8 { auto const addr = address{ internal_.v.value }; auto res = read8(addr); @@ -395,12 +395,12 @@ namespace nes::sys return res; } - auto ppu::write_latch(std::uint8_t const value) -> void + auto ppu::write_latch(u8 const value) -> void { latch_ = value; } - auto ppu::write_ppuctrl(std::uint8_t const value) -> void + auto ppu::write_ppuctrl(u8 const value) -> void { write_latch(value); if (current_cycles_ > boot_up_cycles) @@ -412,7 +412,7 @@ namespace nes::sys } } - auto ppu::write_ppuscroll(std::uint8_t const value) -> void + auto ppu::write_ppuscroll(u8 const value) -> void { write_latch(value); if (current_cycles_ > boot_up_cycles) @@ -435,7 +435,7 @@ namespace nes::sys } } - auto ppu::write_ppumask(std::uint8_t const value) -> void + auto ppu::write_ppumask(u8 const value) -> void { write_latch(value); if (current_cycles_ > boot_up_cycles) @@ -445,7 +445,7 @@ namespace nes::sys } } - auto ppu::write_ppuaddr(std::uint8_t const value) -> void + auto ppu::write_ppuaddr(u8 const value) -> void { write_latch(value); if (current_cycles_ > boot_up_cycles) @@ -467,7 +467,7 @@ namespace nes::sys } } - auto ppu::write_ppudata(std::uint8_t const value) -> void + auto ppu::write_ppudata(u8 const value) -> void { NES_DEBUG_LOG(ppu, "PPUDATA <- {:#2x} (address: {:#4x})", value, internal_.v); write_latch(value); @@ -475,14 +475,14 @@ namespace nes::sys increment_vram(); } - auto ppu::write_oamaddr(std::uint8_t const value) -> void + auto ppu::write_oamaddr(u8 const value) -> void { NES_DEBUG_LOG(ppu, "OAMADDR <- {:#2x}", value); write_latch(value); oamaddr_ = value; } - auto ppu::write_oamdata(std::uint8_t const value) -> void + auto ppu::write_oamdata(u8 const value) -> void { NES_DEBUG_LOG(ppu, "OAMDATA <- {:#2x}", value); write_latch(value); @@ -490,11 +490,11 @@ namespace nes::sys oamaddr_ += 1; } - auto ppu::write_oamdma(std::uint8_t const value) -> void + auto ppu::write_oamdma(u8 const value) -> void { NES_DEBUG_LOG(ppu, "OAMDMA <- {:#2x}", value); auto addr = address{ value, 0x00 }; - for (auto i = unsigned{ 0 }; i < 256; ++i) + for (auto i = u32{ 0 }; i < 256; ++i) { oam_[oamaddr_] = cpu_.read8(addr); oamaddr_ += 1; @@ -574,7 +574,7 @@ namespace nes::sys internal_.v.set_vertical_name_table(internal_.t.get_vertical_name_table()); } - auto ppu::get_sprite_height() const -> unsigned + auto ppu::get_sprite_height() const -> u32 { switch (control_.get_sprite_size()) { @@ -588,17 +588,17 @@ namespace nes::sys } auto ppu::get_tile_bitplane( - pattern_table const pattern_table, tile const tile, unsigned const row, bitplane const bitplane) -> std::uint8_t + pattern_table const pattern_table, tile const tile, u32 const row, bitplane const bitplane) -> u8 { - auto const addr = static_cast<std::uint16_t>( - 0x1000 * static_cast<unsigned>(pattern_table) + 0x10 * static_cast<unsigned>(tile) + row); - return read8(address{ addr } + (static_cast<unsigned>(bitplane) * 8u)); + auto const addr = static_cast<u16>( + 0x1000 * static_cast<u32>(pattern_table) + 0x10 * static_cast<u32>(tile) + row); + return read8(address{ addr } + (static_cast<u32>(bitplane) * 8u)); } - auto ppu::get_tile_row(palette const palette, std::uint8_t bitplane_0, std::uint8_t bitplane_1) const -> tile_row + auto ppu::get_tile_row(palette const palette, u8 bitplane_0, u8 bitplane_1) const -> tile_row { auto res = tile_row{}; - for (auto i = unsigned{ 0 }; i < tile_size; ++i) + for (auto i = u32{ 0 }; i < tile_size; ++i) { auto const bit_0 = (bitplane_0 & 0b10000000u) >> 7; auto const bit_1 = (bitplane_1 & 0b10000000u) >> 7; @@ -624,7 +624,7 @@ namespace nes::sys auto ppu::resolve_color(color const color) const -> rgb { - auto const index = static_cast<std::uint8_t>(color); + auto const index = static_cast<u8>(color); switch (index & 0x3F) { case 0x00: return rgb::from_hex(0x666666); diff --git a/lib/nes/sys/ppu.hh b/lib/nes/sys/ppu.hh index cdca0ae..013546a 100644 --- a/lib/nes/sys/ppu.hh +++ b/lib/nes/sys/ppu.hh @@ -1,6 +1,7 @@ #pragma once #include "nes/sys/types/cycle-count.hh" +#include "nes/common/types.hh" namespace nes { @@ -17,40 +18,40 @@ namespace nes::sys class ppu { - static constexpr auto sprite_max_count = unsigned{ 64 }; - static constexpr auto vram_size = std::size_t{ 0x800 }; - static constexpr auto oam_size = std::size_t{ sprite_max_count * 4 }; - static constexpr auto palette_buffer_size = std::size_t{ 0x20 }; - static constexpr auto tile_size = unsigned{ 8 }; + static constexpr auto sprite_max_count = u32{ 64 }; + static constexpr auto vram_size = u32{ 0x800 }; + static constexpr auto oam_size = u32{ sprite_max_count * 4 }; + static constexpr auto palette_buffer_size = u32{ 0x20 }; + static constexpr auto tile_size = u32{ 8 }; // Writes to some registers are ignored until this clock cycle. static constexpr auto boot_up_cycles = cycle_count::from_ppu(29658); - enum class bitplane : unsigned { _0, _1 }; - enum class palette : unsigned { _0, _1, _2, _3 }; - enum class palette_color : unsigned { _0, _1, _2, _3 }; - enum class name_table : unsigned { _0, _1, _2, _3 }; - enum class role : unsigned { background, foreground }; - enum class pattern_table : unsigned { _0, _1 }; - enum class vram_increment : unsigned { forward, downward }; - enum class sprite_size : unsigned { single_height, double_height }; - enum class tile : std::uint8_t {}; - enum class color : std::uint8_t {}; + enum class bitplane : u32 { _0, _1 }; + enum class palette : u32 { _0, _1, _2, _3 }; + enum class palette_color : u32 { _0, _1, _2, _3 }; + enum class name_table : u32 { _0, _1, _2, _3 }; + enum class role : u32 { background, foreground }; + enum class pattern_table : u32 { _0, _1 }; + enum class vram_increment : u32 { forward, downward }; + enum class sprite_size : u32 { single_height, double_height }; + enum class tile : u8 {}; + enum class color : u8 {}; #define BITFIELD_VALIDATE(mask, offset_from_right) \ static_assert((mask & (1 << offset_from_right)) != 0); \ static_assert(offset_from_right == 0 || (mask & (1 << (offset_from_right - 1))) == 0); #define BITFIELD_VALUE(name, base, mask, offset_from_right) \ BITFIELD_VALIDATE(mask, offset_from_right) \ - auto get_##name() const -> unsigned { return (base & mask) >> offset_from_right; } \ - auto set_##name(unsigned const v) -> void { base = (base & ~mask) | ((v << offset_from_right) & mask); } + auto get_##name() const -> u32 { return (base & mask) >> offset_from_right; } \ + auto set_##name(u32 const v) -> void { base = (base & ~mask) | ((v << offset_from_right) & mask); } #define BITFIELD_ENUM(name, type, base, mask, offset_from_right) \ BITFIELD_VALIDATE(mask, offset_from_right) \ auto get_##name() const -> type { return static_cast<type>((base & mask) >> offset_from_right); } \ - auto set_##name(type const v) -> void { base = (base & ~mask) | ((static_cast<unsigned>(v) << offset_from_right) & mask); } + auto set_##name(type const v) -> void { base = (base & ~mask) | ((static_cast<u32>(v) << offset_from_right) & mask); } #define BITFIELD_FLAG(name, base, mask, offset_from_right) \ BITFIELD_VALIDATE(mask, offset_from_right) \ auto get_##name() const -> bool { return base & mask; } \ - auto set_##name(unsigned const v) -> void { base = (base & ~mask) | (v ? mask : 0); } + auto set_##name(u32 const v) -> void { base = (base & ~mask) | (v ? mask : 0); } struct color_index { @@ -58,11 +59,11 @@ namespace nes::sys BITFIELD_ENUM(palette, palette, value, 0b00001100, 2) BITFIELD_ENUM(role, role, value, 0b00010000, 4) - std::uint8_t value{}; + u8 value{}; color_index() = default; - explicit color_index(std::uint8_t const value) + explicit color_index(u8 const value) : value{ value } { } @@ -81,21 +82,21 @@ namespace nes::sys BITFIELD_FLAG(flip_horizontal, value[2], 0b01000000, 6) BITFIELD_FLAG(flip_vertical, value[2], 0b10000000, 7) - auto get_y() const -> std::uint8_t { return value[0]; } - auto get_tile_index() const -> std::uint8_t { return value[1]; } - auto get_attributes() const -> std::uint8_t { return value[2]; } - auto get_x() const -> std::uint8_t { return value[3]; } + auto get_y() const -> u8 { return value[0]; } + auto get_tile_index() const -> u8 { return value[1]; } + auto get_attributes() const -> u8 { return value[2]; } + auto get_x() const -> u8 { return value[3]; } - auto set_y(std::uint8_t const v) -> void { value[0] = v; } - auto set_tile_index(std::uint8_t const v) -> void { value[1] = v; } - auto set_attributes(std::uint8_t const v) -> void { value[2] = v; } - auto set_x(std::uint8_t const v) -> void { value[3] = v; } + auto set_y(u8 const v) -> void { value[0] = v; } + auto set_tile_index(u8 const v) -> void { value[1] = v; } + auto set_attributes(u8 const v) -> void { value[2] = v; } + auto set_x(u8 const v) -> void { value[3] = v; } - std::uint8_t value[4]{}; + u8 value[4]{}; explicit sprite() = default; - explicit sprite(std::uint8_t const* data) + explicit sprite(u8 const* data) : value{ data[0], data[1], data[2], data[3] } { } @@ -109,7 +110,7 @@ namespace nes::sys struct evaluated_sprite { tile_row pattern; - std::uint8_t x{ 0 }; + u8 x{ 0 }; bool is_in_front{ false }; bool is_sprite_zero{ false }; }; @@ -118,8 +119,8 @@ namespace nes::sys cpu& cpu_; cartridge& cartridge_; display& display_; - std::uint8_t vram_[vram_size]{}; - std::uint8_t oam_[oam_size]{}; + u8 vram_[vram_size]{}; + u8 oam_[oam_size]{}; color palette_buffer_[palette_buffer_size] { color{ 0x09 }, color{ 0x01 }, color{ 0x00 }, color{ 0x01 }, @@ -131,7 +132,7 @@ namespace nes::sys color{ 0x08 }, color{ 0x3A }, color{ 0x00 }, color{ 0x02 }, color{ 0x00 }, color{ 0x20 }, color{ 0x2C }, color{ 0x08 }, }; - std::uint8_t latch_{}; // The last read/written IO register value, returned when reading write-only registers. + u8 latch_{}; // The last read/written IO register value, returned when reading write-only registers. struct { BITFIELD_FLAG(sprite_overflow, value, 0b00100000, 5) @@ -139,9 +140,9 @@ namespace nes::sys BITFIELD_FLAG(vblank, value, 0b10000000, 7) // Set the remaining (unused) bits based on the given value. - auto set_remaining(std::uint8_t const v) -> void { value = (value & ~0b00011111) | (v & 0b00011111); } + auto set_remaining(u8 const v) -> void { value = (value & ~0b00011111) | (v & 0b00011111); } - std::uint8_t value{ 0b00000000 }; + u8 value{ 0b00000000 }; } status_{}; struct { @@ -160,7 +161,7 @@ namespace nes::sys // Enable/disable vblank NMI. BITFIELD_FLAG(vblank_nmi, value, 0b10000000, 7) - std::uint8_t value{ 0b00000000 }; + u8 value{ 0b00000000 }; } control_{}; struct { @@ -181,7 +182,7 @@ namespace nes::sys // Emphasize blue. BITFIELD_FLAG(emphasize_blue, value, 0b10000000, 7) - std::uint8_t value{ 0b00000000 }; + u8 value{ 0b00000000 }; } mask_{}; struct { @@ -201,15 +202,15 @@ namespace nes::sys BITFIELD_VALUE(address_low, value, 0b0000000011111111, 0) BITFIELD_VALUE(address_high, value, 0b0111111100000000, 8) - std::uint16_t value{}; + u16 value{}; } v{}, t{}; // Current and temporary VRAM address and scroll position (15 bits) - std::uint8_t x{}; // Fine X scroll (3 bits) + u8 x{}; // Fine X scroll (3 bits) bool w{}; // Second write toggle (1 bit) } internal_{}; - std::uint8_t oamaddr_{}; // Address accessed by IO registers - std::uint8_t ppudata_read_buffer_{}; // Delays PPUDATA reads by one. - unsigned scanline_{ 240 }; - unsigned scanline_cycle_{ 340 }; + u8 oamaddr_{}; // Address accessed by IO registers + u8 ppudata_read_buffer_{}; // Delays PPUDATA reads by one. + u32 scanline_{ 240 }; + u32 scanline_cycle_{ 340 }; bool even_frame_{ true }; tile_row current_background_{}; tile_row next_background_{}; @@ -217,11 +218,11 @@ namespace nes::sys { tile tile{ 0 }; palette palette{ 0 }; - std::uint8_t bitplane_0{ 0 }; - std::uint8_t bitplane_1{ 0 }; + u8 bitplane_0{ 0 }; + u8 bitplane_1{ 0 }; } fetch_cycle_{}; // Data populated during the fetch cycle. evaluated_sprite sprites_[8]{}; // Evaluated sprites. - unsigned sprite_count_{ 0 }; // Number of evaluated sprites in sprites_. + u32 sprite_count_{ 0 }; // Number of evaluated sprites in sprites_. #undef BITFIELD_VALIDATE #undef BITFIELD_VALUE @@ -242,30 +243,30 @@ namespace nes::sys // Memory access - auto read8(address) -> std::uint8_t; - auto write8(address, std::uint8_t) -> void; + auto read8(address) -> u8; + auto write8(address, u8) -> void; // IO registers - auto read_latch() -> std::uint8_t; - auto read_ppustatus() -> std::uint8_t; - auto read_oamdata() -> std::uint8_t; - auto read_ppudata() -> std::uint8_t; + auto read_latch() -> u8; + auto read_ppustatus() -> u8; + auto read_oamdata() -> u8; + auto read_ppudata() -> u8; - auto write_latch(std::uint8_t) -> void; - auto write_ppuctrl(std::uint8_t) -> void; - auto write_ppuscroll(std::uint8_t) -> void; - auto write_ppumask(std::uint8_t) -> void; - auto write_ppuaddr(std::uint8_t) -> void; - auto write_ppudata(std::uint8_t) -> void; - auto write_oamaddr(std::uint8_t) -> void; - auto write_oamdata(std::uint8_t) -> void; - auto write_oamdma(std::uint8_t) -> void; + auto write_latch(u8) -> void; + auto write_ppuctrl(u8) -> void; + auto write_ppuscroll(u8) -> void; + auto write_ppumask(u8) -> void; + auto write_ppuaddr(u8) -> void; + auto write_ppudata(u8) -> void; + auto write_oamaddr(u8) -> void; + auto write_oamdata(u8) -> void; + auto write_oamdma(u8) -> void; private: auto render_pixel() -> void; auto evaluate_sprites() -> void; - auto fetch_sprite_pattern(sprite, unsigned row) -> tile_row; + auto fetch_sprite_pattern(sprite, u32 row) -> tile_row; // Helpers @@ -274,9 +275,9 @@ namespace nes::sys auto increment_y() -> void; auto copy_x() -> void; auto copy_y() -> void; - auto get_sprite_height() const -> unsigned; - auto get_tile_bitplane(pattern_table, tile, unsigned row, bitplane) -> std::uint8_t; - auto get_tile_row(palette, std::uint8_t bitplane_0, std::uint8_t bitplane_1) const -> tile_row; + auto get_sprite_height() const -> u32; + auto get_tile_bitplane(pattern_table, tile, u32 row, bitplane) -> u8; + auto get_tile_row(palette, u8 bitplane_0, u8 bitplane_1) const -> tile_row; auto ref_color(color_index) -> color&; auto resolve_color(color) const -> rgb; }; diff --git a/lib/nes/sys/types/address.hh b/lib/nes/sys/types/address.hh index dde9c94..d8b857b 100644 --- a/lib/nes/sys/types/address.hh +++ b/lib/nes/sys/types/address.hh @@ -1,6 +1,6 @@ #pragma once -#include <cstdint> +#include "nes/common/types.hh" namespace nes::sys { @@ -8,40 +8,40 @@ namespace nes::sys /// 14 bit addresses). class address { - std::uint16_t absolute_{ 0 }; + u16 absolute_{ 0 }; public: /// Create a zero address. constexpr explicit address() = default; /// Create an address from its absolute value. - constexpr explicit address(std::uint16_t const absolute) + constexpr explicit address(u16 const absolute) : absolute_{ absolute } { } /// Create an address from its page and offset combination. - constexpr explicit address(std::uint8_t const page, std::uint8_t const offset) - : address{ static_cast<std::uint16_t>((page << 8) | (offset << 0)) } + constexpr explicit address(u8 const page, u8 const offset) + : address{ static_cast<u16>((page << 8) | (offset << 0)) } { } /// Get the absolute address value. - constexpr auto get_absolute() const -> std::uint16_t + constexpr auto get_absolute() const -> u16 { return absolute_; } /// Get the address page (the first 8 bits). - constexpr auto get_page() const -> std::uint8_t + constexpr auto get_page() const -> u8 { - return static_cast<std::uint8_t>((get_absolute() & 0xFF00) >> 8); + return static_cast<u8>((get_absolute() & 0xFF00) >> 8); } /// Get the offset within the page (the last 8 bits). - constexpr auto get_offset() const -> std::uint8_t + constexpr auto get_offset() const -> u8 { - return static_cast<std::uint8_t>((get_absolute() & 0x00FF) >> 0); + return static_cast<u8>((get_absolute() & 0x00FF) >> 0); } }; @@ -52,23 +52,23 @@ namespace nes::sys constexpr auto operator<=(address const a, address const b) -> bool { return a.get_absolute() <= b.get_absolute(); } constexpr auto operator>=(address const a, address const b) -> bool { return a.get_absolute() >= b.get_absolute(); } - constexpr auto operator+(address const a, unsigned const b) -> address + constexpr auto operator+(address const a, u32 const b) -> address { - return address{ static_cast<std::uint16_t>(a.get_absolute() + b) }; + return address{ static_cast<u16>(a.get_absolute() + b) }; } - constexpr auto operator+(unsigned const a, address const b) -> address + constexpr auto operator+(u32 const a, address const b) -> address { - return address{ static_cast<std::uint16_t>(a + b.get_absolute()) }; + return address{ static_cast<u16>(a + b.get_absolute()) }; } - constexpr auto operator-(address const a, unsigned const b) -> address + constexpr auto operator-(address const a, u32 const b) -> address { - return address{ static_cast<std::uint16_t>(a.get_absolute() - b) }; + return address{ static_cast<u16>(a.get_absolute() - b) }; } - constexpr auto operator%(address const a, unsigned const b) -> address + constexpr auto operator%(address const a, u32 const b) -> address { - return address{ static_cast<std::uint16_t>(a.get_absolute() % b) }; + return address{ static_cast<u16>(a.get_absolute() % b) }; } } // namespace nes::sys
\ No newline at end of file diff --git a/lib/nes/sys/types/button-mask.hh b/lib/nes/sys/types/button-mask.hh index 64be0b6..4a44530 100644 --- a/lib/nes/sys/types/button-mask.hh +++ b/lib/nes/sys/types/button-mask.hh @@ -1,18 +1,18 @@ #pragma once -#include <cstdint> +#include "nes/common/types.hh" namespace nes::sys { /// Buttons pressed on a controller. class button_mask { - std::uint8_t raw_value_{ 0 }; + u8 raw_value_{ 0 }; public: constexpr explicit button_mask() = default; - static constexpr auto from_raw_value(std::uint8_t const raw_value) -> button_mask + static constexpr auto from_raw_value(u8 const raw_value) -> button_mask { return button_mask{ raw_value }; } @@ -21,10 +21,10 @@ namespace nes::sys constexpr auto remove(button_mask const other) -> void { raw_value_ ^= other.raw_value_; } constexpr auto contains(button_mask const other) const -> bool { return (raw_value_ & other.raw_value_) == other.raw_value_; } constexpr auto is_empty() const -> bool { return raw_value_ == 0; } - constexpr auto get_raw_value() const -> std::uint8_t { return raw_value_; } + constexpr auto get_raw_value() const -> u8 { return raw_value_; } private: - constexpr explicit button_mask(std::uint8_t const raw_value) + constexpr explicit button_mask(u8 const raw_value) : raw_value_{ raw_value } { } diff --git a/lib/nes/sys/types/cycle-count.hh b/lib/nes/sys/types/cycle-count.hh index 95ce9e5..c977d1d 100644 --- a/lib/nes/sys/types/cycle-count.hh +++ b/lib/nes/sys/types/cycle-count.hh @@ -1,5 +1,6 @@ #pragma once +#include "nes/common/types.hh" #include <chrono> namespace nes::sys @@ -12,11 +13,11 @@ namespace nes::sys { friend constexpr auto operator+(cycle_count, cycle_count) -> cycle_count; friend constexpr auto operator-(cycle_count, cycle_count) -> cycle_count; - friend constexpr auto operator*(std::uint64_t, cycle_count) -> cycle_count; - friend constexpr auto operator*(cycle_count, std::uint64_t) -> cycle_count; - friend constexpr auto operator/(cycle_count, cycle_count) -> std::uint64_t; + friend constexpr auto operator*(u64, cycle_count) -> cycle_count; + friend constexpr auto operator*(cycle_count, u64) -> cycle_count; + friend constexpr auto operator/(cycle_count, cycle_count) -> u64; - std::uint64_t units_{ 0 }; // The most fine-granular cycle count (here: PPU cycles). + u64 units_{ 0 }; // The most fine-granular cycle count (here: PPU cycles). static constexpr auto ppu_cycle() -> cycle_count { return cycle_count{ 1 }; } static constexpr auto cpu_cycle() -> cycle_count { return cycle_count{ 3 }; } @@ -26,48 +27,48 @@ namespace nes::sys constexpr explicit cycle_count() = default; constexpr auto operator+=(cycle_count const other) -> cycle_count& { return *this = *this + other; } - constexpr auto operator*=(std::uint64_t const other) -> cycle_count& { return *this = *this * other; } + constexpr auto operator*=(u64 const other) -> cycle_count& { return *this = *this * other; } - static constexpr auto from_units(std::uint64_t const units) -> cycle_count + static constexpr auto from_units(u64 const units) -> cycle_count { return cycle_count{ units }; } static constexpr auto from_duration(std::chrono::microseconds const duration) -> cycle_count { - return from_units(static_cast<std::uint64_t>(duration.count()) * second().get_units() / (1000 * 1000)); + return from_units(static_cast<u64>(duration.count()) * second().get_units() / (1000 * 1000)); } - static constexpr auto from_cpu(std::uint64_t const cpu_cycles) -> cycle_count + static constexpr auto from_cpu(u64 const cpu_cycles) -> cycle_count { return cpu_cycles * cpu_cycle(); } - static constexpr auto from_ppu(std::uint64_t const ppu_cycles) -> cycle_count + static constexpr auto from_ppu(u64 const ppu_cycles) -> cycle_count { return ppu_cycles * ppu_cycle(); } /// Value in implementation-defined units. - constexpr auto get_units() const -> std::uint64_t { return units_; } + constexpr auto get_units() const -> u64 { return units_; } constexpr auto to_duration() const -> std::chrono::microseconds { return std::chrono::microseconds{ get_units() * 1000 * 1000 / second().get_units() }; } - constexpr auto to_cpu() const -> std::uint64_t + constexpr auto to_cpu() const -> u64 { return *this / cpu_cycle(); } - constexpr auto to_ppu() const -> std::uint64_t + constexpr auto to_ppu() const -> u64 { return *this / ppu_cycle(); } private: - constexpr explicit cycle_count(std::uint64_t const units) + constexpr explicit cycle_count(u64 const units) : units_{ units } { } @@ -81,7 +82,7 @@ namespace nes::sys constexpr auto operator>=(cycle_count const a, cycle_count const b) -> bool { return a.get_units() >= b.get_units(); } constexpr auto operator+(cycle_count const a, cycle_count const b) -> cycle_count { return cycle_count{ a.get_units() + b.get_units() }; } constexpr auto operator-(cycle_count const a, cycle_count const b) -> cycle_count { return cycle_count{ a.get_units() - b.get_units() }; } - constexpr auto operator*(std::uint64_t const a, cycle_count const b) -> cycle_count { return cycle_count{ a * b.get_units() }; } - constexpr auto operator*(cycle_count const a, std::uint64_t const b) -> cycle_count { return cycle_count{ a.get_units() * b }; } - constexpr auto operator/(cycle_count const a, cycle_count const b) -> std::uint64_t { return a.get_units() / b.get_units(); } + constexpr auto operator*(u64 const a, cycle_count const b) -> cycle_count { return cycle_count{ a * b.get_units() }; } + constexpr auto operator*(cycle_count const a, u64 const b) -> cycle_count { return cycle_count{ a.get_units() * b }; } + constexpr auto operator/(cycle_count const a, cycle_count const b) -> u64 { return a.get_units() / b.get_units(); } } // namespace nes::sys
\ No newline at end of file diff --git a/lib/nes/sys/types/snapshot.hh b/lib/nes/sys/types/snapshot.hh index 3b1b3b4..c057aeb 100644 --- a/lib/nes/sys/types/snapshot.hh +++ b/lib/nes/sys/types/snapshot.hh @@ -1,8 +1,8 @@ #pragma once #include "nes/sys/types/cycle-count.hh" +#include "nes/common/types.hh" #include <vector> -#include <cstdint> namespace nes::sys { @@ -13,18 +13,18 @@ namespace nes::sys cycle_count cpu_cycle; cycle_count ppu_cycle; - std::vector<std::uint8_t> ram; - std::vector<std::uint8_t> sram; - std::vector<std::uint8_t> vram; - std::vector<std::uint8_t> oam; + std::vector<u8> ram; + std::vector<u8> sram; + std::vector<u8> vram; + std::vector<u8> oam; struct { - std::uint16_t pc{}; - std::uint8_t sp{}; - std::uint8_t a{}; - std::uint8_t x{}; - std::uint8_t y{}; - std::uint8_t p{}; + u16 pc{}; + u8 sp{}; + u8 a{}; + u8 x{}; + u8 y{}; + u8 p{}; bool c{}; bool z{}; bool i{}; |
