From f0d0d9abc67766322b7c39531e9c9e430eff8f3f Mon Sep 17 00:00:00 2001 From: scawful Date: Sat, 19 Aug 2023 14:12:45 -0400 Subject: [PATCH] Create SNES skeleton --- src/app/emu/snes.cc | 124 ++++++++++++++++++++++++++++++++++++++++++++ src/app/emu/snes.h | 73 ++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 src/app/emu/snes.cc create mode 100644 src/app/emu/snes.h diff --git a/src/app/emu/snes.cc b/src/app/emu/snes.cc new file mode 100644 index 00000000..73945155 --- /dev/null +++ b/src/app/emu/snes.cc @@ -0,0 +1,124 @@ +#include "snes.h" + +#include +#include + +#include "app/emu/apu.h" +#include "app/emu/cpu.h" +#include "app/emu/mem.h" +#include "app/emu/ppu.h" + +namespace yaze { +namespace app { +namespace emu { + +void SNES::Init(ROM& rom) { + // Initialize CPU + cpu.Init(); + + // Initialize PPU + ppu.Init(); + + // Initialize APU + apu.Init(); + + // Load ROM + memory_.SetMemory(rom.vector()); +} + +void SNES::Run() { + running_ = true; + + const int cpuClockSpeed = 21477272; // 21.477272 MHz + const int ppuClockSpeed = 5369318; // 5.369318 MHz + const int apuClockSpeed = 32000; // 32 KHz + const double targetFPS = 60.0; // 60 frames per second + + const double cpuCycleTime = 1.0 / cpuClockSpeed; + const double ppuCycleTime = 1.0 / ppuClockSpeed; + const double apuCycleTime = 1.0 / apuClockSpeed; + const double frameTime = 1.0 / targetFPS; + + double cpuAccumulatedTime = 0.0; + double ppuAccumulatedTime = 0.0; + double apuAccumulatedTime = 0.0; + double frameAccumulatedTime = 0.0; + + auto lastTime = std::chrono::high_resolution_clock::now(); + + while (running_) { + auto currentTime = std::chrono::high_resolution_clock::now(); + double deltaTime = + std::chrono::duration(currentTime - lastTime).count(); + lastTime = currentTime; + + cpuAccumulatedTime += deltaTime; + ppuAccumulatedTime += deltaTime; + apuAccumulatedTime += deltaTime; + frameAccumulatedTime += deltaTime; + + while (cpuAccumulatedTime >= cpuCycleTime) { + cpu.ExecuteInstruction(cpu.ReadByte(cpu.PC)); + cpuAccumulatedTime -= cpuCycleTime; + } + + while (ppuAccumulatedTime >= ppuCycleTime) { + RenderScanline(); + ppuAccumulatedTime -= ppuCycleTime; + } + + while (apuAccumulatedTime >= apuCycleTime) { + // apu.Update(); + apuAccumulatedTime -= apuCycleTime; + } + + if (frameAccumulatedTime >= frameTime) { + // renderer.Render(); + frameAccumulatedTime -= frameTime; + } + + HandleInput(); + } +} + +void SNES::RenderScanline() { + // Render background layers + for (int layer = 0; layer < 4; layer++) { + DrawBackgroundLayer(layer); + } + + // Render sprites + DrawSprites(); +} + +void SNES::DrawBackgroundLayer(int layer) { + // ... +} + +void SNES::DrawSprites() { + // ... +} + +void SNES::HandleInput() { + // ... +} + +void SNES::SaveState(const std::string& path) { + // ... +} + +void SNES::LoadState(const std::string& path) { + // ... +} + +void SNES::Debug() { + // ... +} + +void SNES::Breakpoint(uint16_t address) { + // ... +} + +} // namespace emu +} // namespace app +} // namespace yaze \ No newline at end of file diff --git a/src/app/emu/snes.h b/src/app/emu/snes.h new file mode 100644 index 00000000..f96db879 --- /dev/null +++ b/src/app/emu/snes.h @@ -0,0 +1,73 @@ +#include +#include + +#include "app/emu/apu.h" +#include "app/emu/cpu.h" +#include "app/emu/dbg.h" +#include "app/emu/ppu.h" +#include "app/rom.h" + +namespace yaze { +namespace app { +namespace emu { + +class SNES { + public: + SNES()=default; + ~SNES()=default; + + // Initialization + void Init(ROM& rom); + + // Main emulation loop + void Run(); + + // Functions for CPU-related operations + void Fetch(); + void Decode(); + void Execute(); + + // Functions for PPU-related operations + void RenderScanline(); + void UpdateSprites(); + void DrawBackgroundLayer(int layer); + void DrawSprites(); + + // Memory-related functions + uint8_t ReadMemory(uint16_t address); + void WriteMemory(uint16_t address, uint8_t value); + + // Controller input handling + void HandleInput(); + + // Save/Load game state + void SaveState(const std::string& path); + void LoadState(const std::string& path); + + // Debugger + void Debug(); + void Breakpoint(uint16_t address); + + bool running() const { return running_; } + + private: + // Components of the SNES + MemoryImpl memory_; + CPU cpu{memory_}; + PPU ppu{memory_}; + APU apu{memory_}; + + // Helper classes + Debugger debugger; + + // Other private member variables + std::vector rom_data; + bool running_; + uint16_t pc; + uint32_t cycle; + int scanline; +}; + +} // namespace emu +} // namespace app +} // namespace yaze \ No newline at end of file