summaryrefslogtreecommitdiff
path: root/src/nes
diff options
context:
space:
mode:
authorHannes Schulze <haschu0103@outlook.de>2025-01-18 00:05:53 +0100
committerHannes Schulze <haschu0103@outlook.de>2025-01-18 00:05:53 +0100
commitd5a52cc491a222f1b7d33fa6789bed617ec6638b (patch)
treea1c849e94620eb2c132fbd1a61898ef51ce167ba /src/nes
parent9d80b5b8a61bd8c2336f5032de8b84fea15d685f (diff)
cpu: bugfixes
Diffstat (limited to 'src/nes')
-rw-r--r--src/nes/cpu.cc35
-rw-r--r--src/nes/cpu.hh9
-rw-r--r--src/nes/mapper.cc12
-rw-r--r--src/nes/nes.cc16
-rw-r--r--src/nes/nes.hh4
-rw-r--r--src/nes/ppu.cc10
-rw-r--r--src/nes/ppu.hh12
-rw-r--r--src/nes/util/address.hh2
8 files changed, 84 insertions, 16 deletions
diff --git a/src/nes/cpu.cc b/src/nes/cpu.cc
index 277c05d..2a079cc 100644
--- a/src/nes/cpu.cc
+++ b/src/nes/cpu.cc
@@ -14,6 +14,25 @@ namespace nes
registers_.pc = read16(address{ 0xFFFC });
}
+ auto cpu::snapshot(test::status& snapshot) -> void
+ {
+ snapshot.cpu_cycle = current_cycles_;
+ snapshot.ram = std::vector(std::begin(ram_), std::end(ram_));
+ snapshot.registers.pc = registers_.pc;
+ snapshot.registers.sp = registers_.sp;
+ snapshot.registers.a = registers_.a;
+ snapshot.registers.x = registers_.x;
+ snapshot.registers.y = registers_.y;
+ snapshot.registers.p = registers_.p;
+ snapshot.registers.c = registers_.c;
+ snapshot.registers.z = registers_.z;
+ snapshot.registers.i = registers_.i;
+ snapshot.registers.d = registers_.d;
+ snapshot.registers.b = registers_.b;
+ snapshot.registers.v = registers_.v;
+ snapshot.registers.n = registers_.n;
+ }
+
auto cpu::step_to(cycle_count const target) -> void
{
while (current_cycles_ < target)
@@ -71,7 +90,7 @@ namespace nes
case 0x27: run_rla<addressing_mode::zero_page>(); break;
case 0x28: run_plp(); break;
case 0x29: run_and<addressing_mode::immediate>(); break;
- case 0x2A: run_rol<addressing_mode::absolute>(); break;
+ case 0x2A: run_rol<addressing_mode::accumulator>(); break;
case 0x2B: run_anc<addressing_mode::immediate>(); break;
case 0x2C: run_bit<addressing_mode::absolute>(); break;
case 0x2D: run_and<addressing_mode::absolute>(); break;
@@ -352,7 +371,7 @@ namespace nes
{
// ASL: Arithmetic Shift Left
auto operand = fetch_operand<Mode>();
- eval_asl(operand.read());
+ operand.write(eval_asl(operand.read()));
current_cycles_ += shift_cycle_count<Mode>();
}
@@ -613,7 +632,7 @@ namespace nes
template<cpu::addressing_mode Mode>
auto cpu::run_ahx() -> void
{
- // AHX: AND A X H
+ // AHX: ???
// TODO
std::abort();
}
@@ -694,7 +713,7 @@ namespace nes
template<cpu::addressing_mode Mode>
auto cpu::run_tas() -> void
{
- // TAS: S = A & X + AND S H
+ // TAS: ???
// TODO
std::abort();
}
@@ -702,7 +721,7 @@ namespace nes
template<cpu::addressing_mode Mode>
auto cpu::run_shy() -> void
{
- // SHY: AND Y H
+ // SHY: ???
// TODO
std::abort();
}
@@ -710,7 +729,7 @@ namespace nes
template<cpu::addressing_mode Mode>
auto cpu::run_shx() -> void
{
- // SHY: AND X H
+ // SHY: ???
// TODO
std::abort();
}
@@ -796,7 +815,7 @@ namespace nes
template<cpu::addressing_mode Mode>
auto cpu::run_las() -> void
{
- // LAS: AND S, store into A, X, S
+ // LAS: ???
// TODO
std::abort();
}
@@ -1055,7 +1074,7 @@ namespace nes
registers_.a = new_val;
registers_.c = tmp > 0xFF;
- registers_.v = ((old_val ^ arg) & 0x80) == 0 && ((old_val ^ new_val) & 0x80) == 0;
+ registers_.v = ((old_val ^ arg) & 0x80) == 0 && ((old_val ^ new_val) & 0x80) != 0;
update_alu_flags(registers_.a);
}
diff --git a/src/nes/cpu.hh b/src/nes/cpu.hh
index 59f2db4..3587fd6 100644
--- a/src/nes/cpu.hh
+++ b/src/nes/cpu.hh
@@ -2,6 +2,7 @@
#include "nes/util/cycle_count.hh"
#include "nes/util/address.hh"
+#include "status.hh"
namespace nes
{
@@ -114,7 +115,7 @@ namespace nes
bool i : 1; // interrupt inhibit
bool d : 1; // decimal
bool b : 1; // break
- bool _ : 1; // (unused, always true)
+ bool : 1; // (unused, always true)
bool v : 1; // overflow
bool n : 1; // negative
};
@@ -130,6 +131,8 @@ namespace nes
auto operator=(cpu const&) -> cpu& = delete;
auto operator=(cpu&&) -> cpu& = delete;
+ auto snapshot(test::status&) -> void;
+
auto step_to(cycle_count) -> void;
private:
@@ -251,8 +254,8 @@ namespace nes
template<> auto name##_cycle_count<addressing_mode::mode>() -> cycle_count { return cycle_count::from_cpu(value); }
DEFINE_CYCLE_COUNT(jump)
- DEFINE_CYCLE_COUNT_INSTANCE(jump, absolute, 2)
- DEFINE_CYCLE_COUNT_INSTANCE(jump, indirect, 2)
+ DEFINE_CYCLE_COUNT_INSTANCE(jump, absolute, 3)
+ DEFINE_CYCLE_COUNT_INSTANCE(jump, indirect, 5)
DEFINE_CYCLE_COUNT(shift)
DEFINE_CYCLE_COUNT_INSTANCE(shift, accumulator, 2)
diff --git a/src/nes/mapper.cc b/src/nes/mapper.cc
index a540dbf..a451e3a 100644
--- a/src/nes/mapper.cc
+++ b/src/nes/mapper.cc
@@ -27,9 +27,13 @@ namespace nes
auto mapper::nrom_read(address const addr) -> std::uint8_t
{
+ if (addr <= address{ 0x5FFF })
+ {
+ return 0x0;
+ }
if (addr <= address{ 0x7FFF })
{
- return cartridge_.get_ram()[addr.get_absolute() % 0x2000];
+ return cartridge_.get_ram()[addr.get_absolute() - 0x6000];
}
if (addr <= address{ 0xBFFF })
{
@@ -52,9 +56,13 @@ namespace nes
auto mapper::nrom_write(address const addr, std::uint8_t const value) -> void
{
+ if (addr <= address{ 0x5FFF })
+ {
+ return;
+ }
if (addr <= address{ 0x7FFF })
{
- cartridge_.get_ram_mut()[addr.get_absolute() % 0x2000] = value;
+ cartridge_.get_ram_mut()[addr.get_absolute() - 0x6000] = value;
}
}
diff --git a/src/nes/nes.cc b/src/nes/nes.cc
index 0579735..84f3309 100644
--- a/src/nes/nes.cc
+++ b/src/nes/nes.cc
@@ -10,6 +10,7 @@ namespace nes
: cartridge_{ std::move(cartridge) }
, display_{ display }
, mapper_{ mapper::select(cartridge_) }
+ , ppu_{ cpu_, mapper_ }
, cpu_{ ppu_, mapper_, controller_1_, controller_2_ }
{
if (!cartridge_.is_valid())
@@ -24,7 +25,12 @@ namespace nes
auto nes::step(std::chrono::microseconds const delta) -> void
{
- current_cycles_ += cycle_count::from_duration(delta);
+ step(cycle_count::from_duration(delta));
+ }
+
+ auto nes::step(cycle_count const delta) -> void
+ {
+ current_cycles_ += delta;
cpu_.step_to(current_cycles_);
ppu_.step_to(current_cycles_);
@@ -32,4 +38,12 @@ namespace nes
display_.clear(rgb{ animation_progress_, animation_progress_, animation_progress_ });
display_.switch_buffers();
}
+
+ auto nes::snapshot() -> test::status
+ {
+ auto res = test::status{};
+ res.sram = std::vector(cartridge_.get_ram(), cartridge_.get_ram() + cartridge_.get_ram_length());
+ cpu_.snapshot(res);
+ return res;
+ }
} // namespace nes \ No newline at end of file
diff --git a/src/nes/nes.hh b/src/nes/nes.hh
index be50bbb..2701f4b 100644
--- a/src/nes/nes.hh
+++ b/src/nes/nes.hh
@@ -6,6 +6,7 @@
#include "nes/cpu.hh"
#include "nes/ppu.hh"
#include "nes/mapper.hh"
+#include "status.hh"
namespace nes
{
@@ -38,5 +39,8 @@ namespace nes
auto get_controller_2() -> controller& { return controller_2_; }
auto step(std::chrono::microseconds delta) -> void;
+ auto step(cycle_count delta) -> void;
+
+ auto snapshot() -> test::status;
};
} // namespace nes \ No newline at end of file
diff --git a/src/nes/ppu.cc b/src/nes/ppu.cc
index c2ec439..302b395 100644
--- a/src/nes/ppu.cc
+++ b/src/nes/ppu.cc
@@ -2,7 +2,17 @@
namespace nes
{
+ ppu::ppu(cpu& cpu, mapper& mapper)
+ : cpu_{ cpu }
+ , mapper_{ mapper }
+ {
+ }
+
auto ppu::step_to(cycle_count const cycle) -> void
{
+ while (current_cycles_ < cycle)
+ {
+ current_cycles_ += cycle_count::from_ppu(1);
+ }
}
} // namespace nes \ No newline at end of file
diff --git a/src/nes/ppu.hh b/src/nes/ppu.hh
index edb7aba..8f116c7 100644
--- a/src/nes/ppu.hh
+++ b/src/nes/ppu.hh
@@ -4,10 +4,20 @@
namespace nes
{
+ class cpu;
+ class mapper;
+
class ppu
{
+ static constexpr auto vram_size = std::size_t{ 0x800 };
+
+ cycle_count current_cycles_;
+ cpu& cpu_;
+ mapper& mapper_;
+ std::uint8_t vram_[vram_size]{};
+
public:
- explicit ppu() = default;
+ explicit ppu(cpu& cpu, mapper& mapper);
ppu(ppu const&) = delete;
ppu(ppu&&) = delete;
diff --git a/src/nes/util/address.hh b/src/nes/util/address.hh
index 0161998..77ee76a 100644
--- a/src/nes/util/address.hh
+++ b/src/nes/util/address.hh
@@ -21,7 +21,7 @@ namespace nes
/// 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)) }
+ : address{ static_cast<std::uint16_t>((page << 8) | (offset << 0)) }
{
}