Lay down BaseCPU structure
This commit is contained in:
@@ -9,15 +9,15 @@ Core::Core() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Core::Stop() {
|
void Core::Stop() {
|
||||||
cpu.Reset();
|
cpu->Reset();
|
||||||
cpu.mem.Reset();
|
cpu->mem.Reset();
|
||||||
pause = true;
|
pause = true;
|
||||||
romLoaded = false;
|
romLoaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::LoadROM(const std::string& rom_) {
|
void Core::LoadROM(const std::string& rom_) {
|
||||||
rom = rom_;
|
rom = rom_;
|
||||||
cpu.Reset();
|
cpu->Reset();
|
||||||
pause = false;
|
pause = false;
|
||||||
romLoaded = true;
|
romLoaded = true;
|
||||||
|
|
||||||
@@ -30,21 +30,21 @@ void Core::LoadROM(const std::string& rom_) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu.mem.LoadROM(isArchive, rom);
|
cpu->mem.LoadROM(isArchive, rom);
|
||||||
GameDB::match(cpu.mem);
|
GameDB::match(cpu->mem);
|
||||||
cpu.mem.mmio.vi.isPal = cpu.mem.IsROMPAL();
|
cpu->mem.mmio.vi.isPal = cpu->mem.IsROMPAL();
|
||||||
cpu.mem.mmio.si.pif.InitDevices(cpu.mem.saveType);
|
cpu->mem.mmio.si.pif.InitDevices(cpu->mem.saveType);
|
||||||
cpu.mem.mmio.si.pif.LoadMempak(rom);
|
cpu->mem.mmio.si.pif.LoadMempak(rom);
|
||||||
cpu.mem.mmio.si.pif.LoadEeprom(cpu.mem.saveType, rom);
|
cpu->mem.mmio.si.pif.LoadEeprom(cpu->mem.saveType, rom);
|
||||||
cpu.mem.flash.Load(cpu.mem.saveType, rom);
|
cpu->mem.flash.Load(cpu->mem.saveType, rom);
|
||||||
cpu.mem.LoadSRAM(cpu.mem.saveType, rom);
|
cpu->mem.LoadSRAM(cpu->mem.saveType, rom);
|
||||||
PIF::ExecutePIF(cpu.mem, cpu.regs);
|
PIF::ExecutePIF(cpu->mem, cpu->regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Run(float volumeL, float volumeR) {
|
void Core::Run(float volumeL, float volumeR) {
|
||||||
Mem& mem = cpu.mem;
|
Mem& mem = cpu->mem;
|
||||||
MMIO& mmio = mem.mmio;
|
MMIO& mmio = mem.mmio;
|
||||||
Registers& regs = cpu.regs;
|
Registers& regs = cpu->regs;
|
||||||
|
|
||||||
for (int field = 0; field < mmio.vi.numFields; field++) {
|
for (int field = 0; field < mmio.vi.numFields; field++) {
|
||||||
int frameCycles = 0;
|
int frameCycles = 0;
|
||||||
@@ -56,7 +56,7 @@ void Core::Run(float volumeL, float volumeR) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
for(; cycles < mem.mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
||||||
int taken = cpu.Step();
|
int taken = cpu->Step();
|
||||||
static int cpuSteps = 0;
|
static int cpuSteps = 0;
|
||||||
cpuSteps += taken;
|
cpuSteps += taken;
|
||||||
if(mmio.rsp.spStatus.halt) {
|
if(mmio.rsp.spStatus.halt) {
|
||||||
@@ -86,7 +86,7 @@ void Core::Run(float volumeL, float volumeR) {
|
|||||||
InterruptRaise(mmio.mi, regs, Interrupt::VI);
|
InterruptRaise(mmio.mi, regs, Interrupt::VI);
|
||||||
}
|
}
|
||||||
|
|
||||||
mmio.ai.Step(cpu.mem, regs, frameCycles, volumeL, volumeR);
|
mmio.ai.Step(cpu->mem, regs, frameCycles, volumeL, volumeR);
|
||||||
scheduler.tick(frameCycles, mem, regs);
|
scheduler.tick(frameCycles, mem, regs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ struct Core {
|
|||||||
void LoadROM(const std::string&);
|
void LoadROM(const std::string&);
|
||||||
void Run(float volumeL, float volumeR);
|
void Run(float volumeL, float volumeR);
|
||||||
void TogglePause() { pause = !pause; }
|
void TogglePause() { pause = !pause; }
|
||||||
[[nodiscard]] VI& GetVI() { return cpu.mem.mmio.vi; }
|
[[nodiscard]] VI& GetVI() { return cpu->mem.mmio.vi; }
|
||||||
|
|
||||||
u32 breakpoint = 0;
|
u32 breakpoint = 0;
|
||||||
|
|
||||||
@@ -23,6 +23,6 @@ struct Core {
|
|||||||
int cycles = 0;
|
int cycles = 0;
|
||||||
bool romLoaded = false;
|
bool romLoaded = false;
|
||||||
std::string rom;
|
std::string rom;
|
||||||
Interpreter cpu;
|
std::unique_ptr<BaseCPU> cpu;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/backend/core/BaseCPU.hpp
Normal file
13
src/backend/core/BaseCPU.hpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <Registers.hpp>
|
||||||
|
#include <Mem.hpp>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
struct BaseCPU {
|
||||||
|
virtual ~BaseCPU() = default;
|
||||||
|
virtual int Step() {return 0;}
|
||||||
|
virtual void Reset() {}
|
||||||
|
Registers regs;
|
||||||
|
Mem mem;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <Mem.hpp>
|
#include <Mem.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "BaseCPU.hpp"
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Core;
|
struct Core;
|
||||||
struct Interpreter {
|
struct Interpreter : BaseCPU {
|
||||||
Interpreter() = default;
|
Interpreter() = default;
|
||||||
~Interpreter() = default;
|
~Interpreter() override = default;
|
||||||
FORCE_INLINE int Step() {
|
FORCE_INLINE int Step() override {
|
||||||
CheckCompareInterrupt();
|
CheckCompareInterrupt();
|
||||||
|
|
||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
@@ -35,7 +36,7 @@ struct Interpreter {
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
void Reset();
|
void Reset() override;
|
||||||
Registers regs;
|
Registers regs;
|
||||||
Mem mem;
|
Mem mem;
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ App::App() : window(core) {
|
|||||||
|
|
||||||
void App::Run() {
|
void App::Run() {
|
||||||
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
|
||||||
n64::SI& si = core.cpu.mem.mmio.si;
|
n64::SI& si = core.cpu->mem.mmio.si;
|
||||||
|
|
||||||
while (!window.done) {
|
while (!window.done) {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace fs = std::filesystem;
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
Settings::Settings() {
|
Settings::Settings(n64::Core& core) {
|
||||||
auto fileExists = fs::exists("resources/settings.json");
|
auto fileExists = fs::exists("resources/settings.json");
|
||||||
std::fstream settingsFile;
|
std::fstream settingsFile;
|
||||||
if(fileExists) {
|
if(fileExists) {
|
||||||
@@ -34,20 +34,29 @@ Settings::Settings() {
|
|||||||
volumeR = oldVolumeR;
|
volumeR = oldVolumeR;
|
||||||
checkjsonentry(mute, bool, "audio", "mute", false);
|
checkjsonentry(mute, bool, "audio", "mute", false);
|
||||||
checkjsonentry(lockChannels, bool, "audio", "lockChannels", true);
|
checkjsonentry(lockChannels, bool, "audio", "lockChannels", true);
|
||||||
|
checkjsonentry(jit, bool, "cpu", "enableJIT", false);
|
||||||
} else {
|
} else {
|
||||||
settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::in | std::fstream::out);
|
settingsFile = std::fstream("resources/settings.json", std::fstream::trunc | std::fstream::in | std::fstream::out);
|
||||||
settings["audio"]["volumeR"] = 0.5;
|
settings["audio"]["volumeR"] = 0.5;
|
||||||
settings["audio"]["volumeL"] = 0.5;
|
settings["audio"]["volumeL"] = 0.5;
|
||||||
settings["audio"]["lockChannels"] = true;
|
settings["audio"]["lockChannels"] = true;
|
||||||
settings["audio"]["mute"] = false;
|
settings["audio"]["mute"] = false;
|
||||||
|
settings["cpu"]["enableJIT"] = false;
|
||||||
|
|
||||||
oldVolumeR = volumeR = 0.5;
|
oldVolumeR = volumeR = 0.5;
|
||||||
oldVolumeL = volumeL = 0.5;
|
oldVolumeL = volumeL = 0.5;
|
||||||
lockChannels = true;
|
lockChannels = true;
|
||||||
mute = false;
|
mute = false;
|
||||||
|
jit = false;
|
||||||
|
|
||||||
settingsFile << settings;
|
settingsFile << settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(jit) {
|
||||||
|
Util::panic("JIT is unimplemented!");
|
||||||
|
} else {
|
||||||
|
core.cpu = std::make_unique<n64::Interpreter>();
|
||||||
|
}
|
||||||
settingsFile.close();
|
settingsFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +73,7 @@ Settings::~Settings() {
|
|||||||
settings["audio"]["volumeL"] = oldVolumeL;
|
settings["audio"]["volumeL"] = oldVolumeL;
|
||||||
settings["audio"]["lockChannels"] = lockChannels;
|
settings["audio"]["lockChannels"] = lockChannels;
|
||||||
settings["audio"]["mute"] = mute;
|
settings["audio"]["mute"] = mute;
|
||||||
|
settings["cpu"]["enableJIT"] = jit;
|
||||||
settingsFile << settings;
|
settingsFile << settings;
|
||||||
|
|
||||||
settingsFile.close();
|
settingsFile.close();
|
||||||
@@ -73,9 +83,9 @@ void Settings::RenderWidget(bool& show) {
|
|||||||
if(show) {
|
if(show) {
|
||||||
ImGui::OpenPopup("Settings");
|
ImGui::OpenPopup("Settings");
|
||||||
if(ImGui::BeginPopupModal("Settings", &show)) {
|
if(ImGui::BeginPopupModal("Settings", &show)) {
|
||||||
enum class SelectedSetting { Audio, COUNT };
|
enum class SelectedSetting { CPU, Audio, COUNT };
|
||||||
static SelectedSetting selectedSetting = SelectedSetting::Audio;
|
static SelectedSetting selectedSetting = SelectedSetting::CPU;
|
||||||
const char *categories[(int)SelectedSetting::COUNT] = { "Audio" };
|
const char *categories[(int)SelectedSetting::COUNT] = { "CPU", "Audio" };
|
||||||
CreateComboList("##", (int*)&selectedSetting, categories, (int)SelectedSetting::COUNT);
|
CreateComboList("##", (int*)&selectedSetting, categories, (int)SelectedSetting::COUNT);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
switch (selectedSetting) {
|
switch (selectedSetting) {
|
||||||
@@ -111,6 +121,9 @@ void Settings::RenderWidget(bool& show) {
|
|||||||
oldVolumeR = volumeR;
|
oldVolumeR = volumeR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SelectedSetting::CPU:
|
||||||
|
ImGui::Checkbox("Enable JIT", &jit);
|
||||||
break;
|
break;
|
||||||
case SelectedSetting::COUNT:
|
case SelectedSetting::COUNT:
|
||||||
Util::panic("BRUH");
|
Util::panic("BRUH");
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace n64 { struct Core; }
|
|||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
Settings();
|
Settings(n64::Core& core);
|
||||||
~Settings();
|
~Settings();
|
||||||
|
|
||||||
[[nodiscard]] FORCE_INLINE float GetVolumeL() const { return volumeL; };
|
[[nodiscard]] FORCE_INLINE float GetVolumeL() const { return volumeL; };
|
||||||
@@ -14,6 +14,7 @@ struct Settings {
|
|||||||
|
|
||||||
void RenderWidget(bool& show);
|
void RenderWidget(bool& show);
|
||||||
private:
|
private:
|
||||||
|
bool jit = false;
|
||||||
float volumeL, volumeR;
|
float volumeL, volumeR;
|
||||||
float oldVolumeL, oldVolumeR;
|
float oldVolumeL, oldVolumeR;
|
||||||
bool lockChannels = true;
|
bool lockChannels = true;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
VkInstance instance{};
|
VkInstance instance{};
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
Window::Window(n64::Core& core) : settings() {
|
Window::Window(n64::Core& core) : settings(core) {
|
||||||
InitSDL();
|
InitSDL();
|
||||||
InitParallelRDP(core.cpu.mem.GetRDRAM(), window);
|
InitParallelRDP(core.cpu->mem.GetRDRAM(), window);
|
||||||
InitImgui();
|
InitImgui();
|
||||||
NFD::Init();
|
NFD::Init();
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ ImDrawData* Window::Present(n64::Core& core) {
|
|||||||
void Window::LoadROM(n64::Core& core, const std::string &path) {
|
void Window::LoadROM(n64::Core& core, const std::string &path) {
|
||||||
if(!path.empty()) {
|
if(!path.empty()) {
|
||||||
core.LoadROM(path);
|
core.LoadROM(path);
|
||||||
gameName = core.cpu.mem.rom.gameNameDB;
|
gameName = core.cpu->mem.rom.gameNameDB;
|
||||||
|
|
||||||
if(gameName.empty()) {
|
if(gameName.empty()) {
|
||||||
gameName = fs::path(path).stem().string();
|
gameName = fs::path(path).stem().string();
|
||||||
@@ -177,13 +177,13 @@ void Window::RenderMainMenuBar(n64::Core &core) {
|
|||||||
OpenROMDialog(*this, core);
|
OpenROMDialog(*this, core);
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Dump RDRAM")) {
|
if (ImGui::MenuItem("Dump RDRAM")) {
|
||||||
core.cpu.mem.DumpRDRAM();
|
core.cpu->mem.DumpRDRAM();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Dump IMEM")) {
|
if (ImGui::MenuItem("Dump IMEM")) {
|
||||||
core.cpu.mem.DumpIMEM();
|
core.cpu->mem.DumpIMEM();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Dump DMEM")) {
|
if (ImGui::MenuItem("Dump DMEM")) {
|
||||||
core.cpu.mem.DumpDMEM();
|
core.cpu->mem.DumpDMEM();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Exit")) {
|
if (ImGui::MenuItem("Exit")) {
|
||||||
done = true;
|
done = true;
|
||||||
@@ -228,8 +228,8 @@ void Window::Render(n64::Core& core) {
|
|||||||
static u32 lastFrame = 0;
|
static u32 lastFrame = 0;
|
||||||
if(!core.pause && core.romLoaded && lastFrame < ticks - 1000) {
|
if(!core.pause && core.romLoaded && lastFrame < ticks - 1000) {
|
||||||
lastFrame = ticks;
|
lastFrame = ticks;
|
||||||
windowTitle += fmt::format(" | {:02d} VI/s", core.cpu.mem.mmio.vi.swaps);
|
windowTitle += fmt::format(" | {:02d} VI/s", core.cpu->mem.mmio.vi.swaps);
|
||||||
core.cpu.mem.mmio.vi.swaps = 0;
|
core.cpu->mem.mmio.vi.swaps = 0;
|
||||||
SDL_SetWindowTitle(window, windowTitle.c_str());
|
SDL_SetWindowTitle(window, windowTitle.c_str());
|
||||||
windowTitle = shadowWindowTitle;
|
windowTitle = shadowWindowTitle;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user