diff --git a/src/app/emu/apu.cc b/src/app/emu/apu.cc index 04f524cf..154eec9e 100644 --- a/src/app/emu/apu.cc +++ b/src/app/emu/apu.cc @@ -10,11 +10,9 @@ namespace yaze { namespace app { namespace emu { -APU::APU(Memory& memory) : memory_(memory) {} - void APU::Init() { // Set the clock frequency - SetFrequency(kApuClockSpeed); + clock_.SetFrequency(kApuClockSpeed); // Initialize registers // ... @@ -22,14 +20,14 @@ void APU::Init() { void APU::Reset() { // Reset the clock - ResetAccumulatedTime(); + clock_.ResetAccumulatedTime(); // Reset the SPC700 // ... } void APU::Update() { - auto cycles_to_run = GetCycleCount(); + auto cycles_to_run = clock_.GetCycleCount(); for (auto i = 0; i < cycles_to_run; ++i) { // Update the APU diff --git a/src/app/emu/apu.h b/src/app/emu/apu.h index e1de33eb..b7ef7e51 100644 --- a/src/app/emu/apu.h +++ b/src/app/emu/apu.h @@ -15,10 +15,10 @@ const int kApuClockSpeed = 1024000; // 1.024 MHz const int apuSampleRate = 32000; // 32 KHz const int apuClocksPerSample = 64; // 64 clocks per sample -class APU : public SPC700, public Clock { +class APU : public SPC700, public Observer { public: // Initializes the APU with the necessary resources and dependencies - APU(Memory &memory); + APU(Memory &memory, VirtualClock &clock) : memory_(memory), clock_(clock) {} void Init(); @@ -28,6 +28,14 @@ class APU : public SPC700, public Clock { // Runs the APU for one frame void Update(); + void Notify(uint32_t address, uint8_t data) override { + if (address >= 0x2140 && address <= 0x2143) { + // Handle communication with the APU + } + } + + void UpdateClock(int delta_time) { clock_.UpdateClock(delta_time); } + // Reads a byte from the specified APU register uint8_t ReadRegister(uint16_t address); @@ -57,6 +65,7 @@ class APU : public SPC700, public Clock { // Member variables to store internal APU state and resources Memory &memory_; + VirtualClock &clock_; std::vector audioSamples_; // Other state variables (registers, counters, channel settings, etc.) }; diff --git a/src/app/emu/clock.h b/src/app/emu/clock.h index a33ebcbe..3ce5d2be 100644 --- a/src/app/emu/clock.h +++ b/src/app/emu/clock.h @@ -7,7 +7,17 @@ namespace yaze { namespace app { namespace emu { -class Clock { +class VirtualClock { + public: + virtual ~VirtualClock() = default; + virtual void UpdateClock(double delta) = 0; + virtual unsigned long long GetCycleCount() const = 0; + virtual void ResetAccumulatedTime() = 0; + virtual void SetFrequency(float new_frequency) = 0; + virtual float GetFrequency() const = 0; +}; + +class Clock : public VirtualClock { public: Clock() = default; virtual ~Clock() = default; @@ -27,15 +37,17 @@ class Clock { cycleCount++; } - void UpdateClock(double delta) { + void UpdateClock(double delta) override { UpdateCycleCount(delta); ResetAccumulatedTime(); } - unsigned long long GetCycleCount() const { return cycleCount; } - float GetFrequency() const { return frequency; } - void SetFrequency(float new_frequency) { this->frequency = new_frequency; } - void ResetAccumulatedTime() { accumulatedTime = 0.0; } + void ResetAccumulatedTime() override { accumulatedTime = 0.0; } + unsigned long long GetCycleCount() const override { return cycleCount; } + float GetFrequency() const override { return frequency; } + void SetFrequency(float new_frequency) override { + this->frequency = new_frequency; + } private: uint64_t cycle = 0; // Current cycle diff --git a/src/app/emu/cpu.cc b/src/app/emu/cpu.cc index 43977572..ecb8c1e2 100644 --- a/src/app/emu/cpu.cc +++ b/src/app/emu/cpu.cc @@ -70,7 +70,7 @@ uint8_t CPU::FetchByteDirectPage(uint8_t operand) { } void CPU::Update() { - auto cycles_to_run = GetCycleCount(); + auto cycles_to_run = clock.GetCycleCount(); // Execute the calculated number of cycles for (int i = 0; i < cycles_to_run; i++) { diff --git a/src/app/emu/cpu.h b/src/app/emu/cpu.h index b104a530..bd506246 100644 --- a/src/app/emu/cpu.h +++ b/src/app/emu/cpu.h @@ -72,11 +72,13 @@ const std::unordered_map opcode_to_mnemonic = { const int kCpuClockSpeed = 21477272; // 21.477272 MHz -class CPU : public Memory, public Clock, public Loggable { +class CPU : public Memory, public Loggable { public: - explicit CPU(Memory& mem) : memory(mem) {} + explicit CPU(Memory& mem, VirtualClock& vclock) + : memory(mem), clock(vclock) {} + void Init() { - SetFrequency(kCpuClockSpeed); + clock.SetFrequency(kCpuClockSpeed); memory.ClearMemory(); } @@ -1037,6 +1039,7 @@ class CPU : public Memory, public Clock, public Loggable { } int16_t SP() const override { return memory.SP(); } void SetSP(int16_t value) override { memory.SetSP(value); } + void UpdateClock(int delta_time) { clock.UpdateClock(delta_time); } private: void compare(uint16_t register_value, uint16_t memory_value) { @@ -1083,6 +1086,7 @@ class CPU : public Memory, public Clock, public Loggable { uint8_t at(int i) const override { return 0; } Memory& memory; + VirtualClock& clock; }; } // namespace emu diff --git a/src/app/emu/ppu.cc b/src/app/emu/ppu.cc index fadb2a72..8bb25ea9 100644 --- a/src/app/emu/ppu.cc +++ b/src/app/emu/ppu.cc @@ -10,8 +10,6 @@ namespace yaze { namespace app { namespace emu { -PPU::PPU(Memory& memory) : memory_(memory) {} - void PPU::RenderScanline() { // Fetch the tile data from VRAM, tile map data from memory, and palette data // from CGRAM @@ -47,7 +45,7 @@ void PPU::RenderScanline() { } void PPU::Update() { - auto cycles_to_run = GetCycleCount(); + auto cycles_to_run = clock_.GetCycleCount(); UpdateInternalState(cycles_to_run); @@ -55,7 +53,7 @@ void PPU::Update() { if (currentScanline < visibleScanlines) { // Render the current scanline // This involves fetching tile data, applying palette colors, handling - // sprite priorities, etc. + // sprite spriorities, etc. RenderScanline(); // Increment the current scanline diff --git a/src/app/emu/ppu.h b/src/app/emu/ppu.h index 75366586..1be7405f 100644 --- a/src/app/emu/ppu.h +++ b/src/app/emu/ppu.h @@ -631,7 +631,7 @@ const int kPpuClockSpeed = 5369318; // 5.369318 MHz class PPU : public Clock { public: // Initializes the PPU with the necessary resources and dependencies - PPU(Memory& memory); + PPU(Memory& memory, VirtualClock& clock) : memory_(memory), clock_(clock) {} void Init() { // Initialize the frame buffer with a size that corresponds to the @@ -714,6 +714,7 @@ class PPU : public Clock { // =========================================================== // Member variables to store internal PPU state and resources Memory& memory_; + VirtualClock& clock_; std::vector frame_buffer_; Tilemap tilemap_; diff --git a/src/app/emu/snes.h b/src/app/emu/snes.h index 3b2b945e..586c1ff2 100644 --- a/src/app/emu/snes.h +++ b/src/app/emu/snes.h @@ -2,6 +2,7 @@ #include #include "app/emu/apu.h" +#include "app/emu/clock.h" #include "app/emu/cpu.h" #include "app/emu/dbg.h" #include "app/emu/ppu.h" @@ -102,9 +103,11 @@ class SNES : public DMA { // Components of the SNES MemoryImpl memory_; - CPU cpu{memory_}; - PPU ppu{memory_}; - APU apu{memory_}; + Clock clock_; + + CPU cpu{memory_, clock_}; + PPU ppu{memory_, clock_}; + APU apu{memory_, clock_}; // Helper classes ROMInfo rom_info_; diff --git a/test/cpu_test.cc b/test/cpu_test.cc index 7fc0f9b0..0660b292 100644 --- a/test/cpu_test.cc +++ b/test/cpu_test.cc @@ -3,12 +3,22 @@ #include #include +#include "app/emu/clock.h" #include "app/emu/mem.h" namespace yaze { namespace app { namespace emu { +class MockClock : public VirtualClock { + public: + MOCK_METHOD(void, UpdateClock, (double delta), (override)); + MOCK_METHOD(unsigned long long, GetCycleCount, (), (const, override)); + MOCK_METHOD(void, ResetAccumulatedTime, (), (override)); + MOCK_METHOD(void, SetFrequency, (float new_frequency), (override)); + MOCK_METHOD(float, GetFrequency, (), (const, override)); +}; + class MockMemory : public Memory { public: MOCK_CONST_METHOD1(ReadByte, uint8_t(uint16_t address)); @@ -133,7 +143,8 @@ class CPUTest : public ::testing::Test { } MockMemory mock_memory; - CPU cpu{mock_memory}; + MockClock mock_clock; + CPU cpu{mock_memory, mock_clock}; }; using ::testing::_;