Add VirtualClock, MockClock, dependency injection
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<int16_t> audioSamples_;
|
||||
// Other state variables (registers, counters, channel settings, etc.)
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -72,11 +72,13 @@ const std::unordered_map<uint8_t, std::string> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<uint8_t> frame_buffer_;
|
||||
|
||||
Tilemap tilemap_;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <string>
|
||||
|
||||
#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_;
|
||||
|
||||
Reference in New Issue
Block a user