Create SNES skeleton
This commit is contained in:
124
src/app/emu/snes.cc
Normal file
124
src/app/emu/snes.cc
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#include "snes.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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<double>(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
|
||||||
73
src/app/emu/snes.h
Normal file
73
src/app/emu/snes.h
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#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<uint8_t> rom_data;
|
||||||
|
bool running_;
|
||||||
|
uint16_t pc;
|
||||||
|
uint32_t cycle;
|
||||||
|
int scanline;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace emu
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
Reference in New Issue
Block a user