Add VirtualClock, MockClock, dependency injection

This commit is contained in:
scawful
2023-08-20 23:45:56 -04:00
parent 2084f2d5a5
commit d538317629
9 changed files with 62 additions and 26 deletions

View File

@@ -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

View File

@@ -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.)
};

View File

@@ -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

View File

@@ -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++) {

View File

@@ -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

View File

@@ -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

View File

@@ -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_;

View File

@@ -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_;