Things to neat up that I noticed with Hazel <3
This commit is contained in:
@@ -22,7 +22,12 @@ Core::Core() {
|
|||||||
void Core::Stop() {
|
void Core::Stop() {
|
||||||
pause = true;
|
pause = true;
|
||||||
romLoaded = false;
|
romLoaded = false;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Reset() {
|
||||||
cpu->Reset();
|
cpu->Reset();
|
||||||
|
cpu->GetMem().mmio.si.pif.Execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::LoadTAS(const fs::path &path) const { return cpu->GetMem().mmio.si.pif.movie.Load(path); }
|
bool Core::LoadTAS(const fs::path &path) const { return cpu->GetMem().mmio.si.pif.movie.Load(path); }
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ struct Core {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Stop();
|
void Stop();
|
||||||
|
void Reset();
|
||||||
void LoadROM(const std::string &);
|
void LoadROM(const std::string &);
|
||||||
[[nodiscard]] bool LoadTAS(const fs::path &) const;
|
[[nodiscard]] bool LoadTAS(const fs::path &) const;
|
||||||
void Run(float volumeL, float volumeR);
|
void Run(float volumeL, float volumeR);
|
||||||
|
|||||||
@@ -10,6 +10,5 @@ struct BaseCPU {
|
|||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
virtual Mem &GetMem() = 0;
|
virtual Mem &GetMem() = 0;
|
||||||
virtual Registers &GetRegs() = 0;
|
virtual Registers &GetRegs() = 0;
|
||||||
[[nodiscard]] virtual Disassembler::DisassemblyResult Disassemble(u32) = 0;
|
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#include <Disassembler.hpp>
|
#include <Disassembler.hpp>
|
||||||
|
#include <Core.hpp>
|
||||||
|
|
||||||
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const {
|
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const {
|
||||||
cs_insn *insn;
|
cs_insn *insn;
|
||||||
const auto bytes = Util::IntegralToBuffer(instruction);
|
const auto bytes = Util::IntegralToBuffer(std::byteswap(instruction));
|
||||||
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
|
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
|
||||||
|
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
@@ -15,9 +16,21 @@ Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 addres
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] Disassembler::DisassemblyResult Disassembler::Disassemble(const u32 address) const {
|
||||||
|
n64::Core& core = n64::Core::GetInstance();
|
||||||
|
n64::Mem& mem = core.cpu->GetMem();
|
||||||
|
u32 paddr;
|
||||||
|
if(!core.cpu->GetRegs().cop0.MapVAddr(n64::Cop0::TLBAccessType::LOAD, address, paddr))
|
||||||
|
return DisassemblyResult{false, ""};
|
||||||
|
|
||||||
|
u32 instruction = mem.Read<u32>(paddr);
|
||||||
|
|
||||||
|
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
|
||||||
|
}
|
||||||
|
|
||||||
Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 address, const u32 instruction) const {
|
Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 address, const u32 instruction) const {
|
||||||
cs_insn *insn;
|
cs_insn *insn;
|
||||||
const auto bytes = Util::IntegralToBuffer(instruction);
|
const auto bytes = Util::IntegralToBuffer(std::byteswap(instruction));
|
||||||
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
|
const auto count = cs_disasm(handle, bytes.data(), bytes.size(), address, 0, &insn);
|
||||||
|
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
@@ -29,29 +42,41 @@ Disassembler::DisassemblyResult Disassembler::DisassembleDetailed(const u32 addr
|
|||||||
|
|
||||||
result.full += std::format("0x{:016X}", result.address) + ":\t";
|
result.full += std::format("0x{:016X}", result.address) + ":\t";
|
||||||
result.full += result.mnemonic + "\t";
|
result.full += result.mnemonic + "\t";
|
||||||
|
result.comment = "// ";
|
||||||
|
|
||||||
const cs_detail *details = insn[0].detail;
|
const cs_detail *details = insn[0].detail;
|
||||||
auto formatOperand = [&](const cs_mips_op &operand) {
|
auto formatOperand = [&](const cs_mips_op &operand) {
|
||||||
switch (operand.type) {
|
switch (operand.type) {
|
||||||
case MIPS_OP_IMM:
|
case MIPS_OP_IMM:
|
||||||
return std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm);
|
return DisassemblyResult::Operand{
|
||||||
|
0xffcbf1ae,
|
||||||
|
std::format("#{:X}", operand.is_unsigned ? operand.uimm : operand.imm)
|
||||||
|
};
|
||||||
case MIPS_OP_MEM:
|
case MIPS_OP_MEM:
|
||||||
return std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp);
|
return DisassemblyResult::Operand{
|
||||||
|
0xffaef1c3,
|
||||||
|
std::format("{}(0x{:X})", cs_reg_name(handle, operand.mem.base), operand.mem.disp)
|
||||||
|
};
|
||||||
case MIPS_OP_REG:
|
case MIPS_OP_REG:
|
||||||
return std::format("{}", cs_reg_name(handle, operand.reg));
|
return DisassemblyResult::Operand{
|
||||||
|
0xffaef1eb,
|
||||||
|
std::format("{}", cs_reg_name(handle, operand.reg))
|
||||||
|
};
|
||||||
default:
|
default:
|
||||||
return std::string{""};
|
return DisassemblyResult::Operand { 0xff808080, "" };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto formatComment = [&](const cs_mips_op &operand) {
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
for (u8 i = 0; i < details->mips.op_count && i < 3; i++) {
|
for (u8 i = 0; i < details->mips.op_count && i < 3; i++) {
|
||||||
result.ops[i] = formatOperand(details->mips.operands[i]);
|
result.ops[i] = formatOperand(details->mips.operands[i]);
|
||||||
result.full += result.ops[i] + "\t";
|
result.full += result.ops[i].str + "\t";
|
||||||
}
|
}
|
||||||
|
|
||||||
result.full += "\t// ";
|
result.full += result.comment;
|
||||||
|
|
||||||
// TODO: generate a comment
|
|
||||||
|
|
||||||
cs_free(insn, count);
|
cs_free(insn, count);
|
||||||
|
|
||||||
|
|||||||
@@ -10,24 +10,25 @@ struct Disassembler {
|
|||||||
std::string full;
|
std::string full;
|
||||||
u64 address;
|
u64 address;
|
||||||
std::string mnemonic;
|
std::string mnemonic;
|
||||||
std::array<std::string, 3> ops{};
|
struct Operand {
|
||||||
|
u32 color;
|
||||||
|
std::string str;
|
||||||
|
};
|
||||||
|
std::array<Operand, 3> ops{};
|
||||||
|
std::string comment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
~Disassembler() { cs_close(&handle); }
|
||||||
|
|
||||||
static Disassembler &GetInstance(bool rsp = false) {
|
static Disassembler &GetInstance(bool rsp = false) {
|
||||||
static Disassembler ret(rsp);
|
static Disassembler ret(rsp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] DisassemblyResult Disassemble(const u32 address, const u32 instruction) const {
|
[[nodiscard]] DisassemblyResult Disassemble(const u32 address) const;
|
||||||
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
~Disassembler() { cs_close(&handle); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
[[nodiscard]] DisassemblyResult DisassembleDetailed(u32 address, u32 instruction) const;
|
[[nodiscard]] DisassemblyResult DisassembleDetailed(u32 address, u32 instruction) const;
|
||||||
[[nodiscard]] DisassemblyResult DisassembleSimple(u32 address, u32 instruction) const;
|
[[nodiscard]] DisassemblyResult DisassembleSimple(u32 address, u32 instruction) const;
|
||||||
|
private:
|
||||||
explicit Disassembler(const bool rsp) : rsp(rsp) {
|
explicit Disassembler(const bool rsp) : rsp(rsp) {
|
||||||
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN), &handle) !=
|
if (cs_open(CS_ARCH_MIPS, static_cast<cs_mode>((rsp ? CS_MODE_32 : CS_MODE_64) | CS_MODE_BIG_ENDIAN), &handle) !=
|
||||||
CS_ERR_OK) {
|
CS_ERR_OK) {
|
||||||
|
|||||||
@@ -21,14 +21,6 @@ void Interpreter::CheckCompareInterrupt() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Disassembler::DisassemblyResult Interpreter::Disassemble(const u32 address) {
|
|
||||||
u32 paddr;
|
|
||||||
if (!regs.cop0.MapVAddr(Cop0::LOAD, address, paddr)) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return Disassembler::GetInstance().Disassemble(address, mem.Read<u32>(paddr));
|
|
||||||
}
|
|
||||||
|
|
||||||
int Interpreter::Step() {
|
int Interpreter::Step() {
|
||||||
CheckCompareInterrupt();
|
CheckCompareInterrupt();
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ struct Interpreter : BaseCPU {
|
|||||||
Mem &GetMem() override { return mem; }
|
Mem &GetMem() override { return mem; }
|
||||||
|
|
||||||
Registers &GetRegs() override { return regs; }
|
Registers &GetRegs() override { return regs; }
|
||||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Registers regs;
|
Registers regs;
|
||||||
Mem mem;
|
Mem mem;
|
||||||
|
|||||||
@@ -107,8 +107,26 @@ int JIT::Step() {
|
|||||||
trace("\tMIPS code (guest PC = 0x{:016X}):", blockPC);
|
trace("\tMIPS code (guest PC = 0x{:016X}):", blockPC);
|
||||||
while (!instrEndsBlock) {
|
while (!instrEndsBlock) {
|
||||||
// CheckCompareInterrupt();
|
// CheckCompareInterrupt();
|
||||||
|
paddr = 0;
|
||||||
|
|
||||||
instruction = FetchInstruction();
|
if (check_address_error(0b11, u64(blockPC))) [[unlikely]] {
|
||||||
|
/*regs.cop0.HandleTLBException(blockPC);
|
||||||
|
regs.cop0.FireException(ExceptionCode::AddressErrorLoad, 0, blockPC);
|
||||||
|
return 1;*/
|
||||||
|
|
||||||
|
panic("[JIT]: Unhandled exception ADL due to unaligned PC virtual value! (0x{:016X})", blockPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!regs.cop0.MapVAddr(Cop0::LOAD, blockPC, paddr)) {
|
||||||
|
/*regs.cop0.HandleTLBException(blockPC);
|
||||||
|
regs.cop0.FireException(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD), 0, blockPC);
|
||||||
|
return 1;*/
|
||||||
|
panic(
|
||||||
|
"[JIT]: Unhandled exception TLB exception {} when retrieving PC physical address! (virtual: 0x{:016X})",
|
||||||
|
static_cast<int>(Cop0::GetTLBExceptionCode(regs.cop0.tlbError, Cop0::LOAD)), static_cast<u64>(blockPC));
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction = mem.Read<u32>(paddr);
|
||||||
instructionsInBlock++;
|
instructionsInBlock++;
|
||||||
|
|
||||||
blockOldPC = blockPC;
|
blockOldPC = blockPC;
|
||||||
@@ -118,17 +136,9 @@ int JIT::Step() {
|
|||||||
if((instrEndsBlock = InstrEndsBlock(instruction)))
|
if((instrEndsBlock = InstrEndsBlock(instruction)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*u32 bswapped = std::byteswap(instruction);
|
trace("{}", Disassembler::GetInstance().DisassembleSimple(paddr, instruction).full);
|
||||||
auto count = cs_disasm(disassemblerMips, reinterpret_cast<const u8 *>(&bswapped), 4, blockPC, 0, &insn);
|
|
||||||
|
|
||||||
if (count > 0) {
|
/*if(ShouldServiceInterrupt()) {
|
||||||
trace("\t\t0x{:016X}:\t{}\t\t{}\n", insn->address, insn->mnemonic, insn->op_str);
|
|
||||||
cs_free(insn, count);
|
|
||||||
} else {
|
|
||||||
trace("\t\tCould not disassemble 0x{:08X} due to error {}\n", instruction, (int)cs_errno(disassemblerMips));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ShouldServiceInterrupt()) {
|
|
||||||
regs.cop0.FireException(ExceptionCode::Interrupt, 0, blockPC);
|
regs.cop0.FireException(ExceptionCode::Interrupt, 0, blockPC);
|
||||||
return 1;
|
return 1;
|
||||||
}*/
|
}*/
|
||||||
|
|||||||
@@ -39,9 +39,6 @@ struct JIT : BaseCPU {
|
|||||||
Mem &GetMem() override { return mem; }
|
Mem &GetMem() override { return mem; }
|
||||||
|
|
||||||
Registers &GetRegs() override { return regs; }
|
Registers &GetRegs() override { return regs; }
|
||||||
|
|
||||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override { return {}; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Xbyak::CodeGenerator code{kCodeCacheAllocSize};
|
Xbyak::CodeGenerator code{kCodeCacheAllocSize};
|
||||||
Registers regs;
|
Registers regs;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ Mem::Mem(JIT *jit) : flash(saveData), jit(jit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Mem::Reset() {
|
void Mem::Reset() {
|
||||||
std::ranges::fill(rom.cart, 0);
|
|
||||||
std::ranges::fill(isviewer, 0);
|
std::ranges::fill(isviewer, 0);
|
||||||
flash.Reset();
|
flash.Reset();
|
||||||
if (saveData.is_mapped()) {
|
if (saveData.is_mapped()) {
|
||||||
@@ -454,7 +453,7 @@ void Mem::Write<u32>(const u32 paddr, const u32 val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __aarch64__
|
#ifndef __aarch64__
|
||||||
void Mem::WriteJIT(const const u32 paddr, const u64 val) {
|
void Mem::WriteJIT(const u32 paddr, const u64 val) {
|
||||||
WriteInterpreter(paddr, val);
|
WriteInterpreter(paddr, val);
|
||||||
if (jit)
|
if (jit)
|
||||||
jit->InvalidateBlock(paddr);
|
jit->InvalidateBlock(paddr);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ void Cop0::tlbw(const int index_) {
|
|||||||
|
|
||||||
void Cop0::tlbp() {
|
void Cop0::tlbp() {
|
||||||
int match = -1;
|
int match = -1;
|
||||||
if (const TLBEntry *entry = TLBTryMatch(entryHi.raw, match); entry && match >= 0) {
|
if (const TLBEntry *entry = TLBTryMatch(entryHi.raw, match); match >= 0) {
|
||||||
index.raw = match;
|
index.raw = match;
|
||||||
} else {
|
} else {
|
||||||
index.raw = 0;
|
index.raw = 0;
|
||||||
|
|||||||
@@ -14,28 +14,17 @@ bool Debugger::render() {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("Follow program counter:", &followPC);
|
ImGui::Checkbox("Follow program counter:", &followPC);
|
||||||
if(followPC)
|
if(followPC)
|
||||||
startAddr = core.cpu->GetRegs().oldPC - 64; // TODO: arbitrary???
|
startAddr = core.cpu->GetRegs().pc - 128; // TODO: arbitrary???
|
||||||
|
|
||||||
if(ImGui::BeginTable("Disassembly", 3, ImGuiTableFlags_RowBg)) {
|
if(ImGui::BeginTable("Disassembly", 3, ImGuiTableFlags_RowBg)) {
|
||||||
ImGui::TableSetupColumn("Address");
|
ImGui::TableSetupColumn("Address");
|
||||||
ImGui::TableSetupColumn("Mnemonic");
|
ImGui::TableSetupColumn("Instruction");
|
||||||
ImGui::TableSetupColumn("Comment");
|
ImGui::TableSetupColumn("Comment");
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
for(u64 addr = startAddr; addr < startAddr + MAX_LINES_OF_DISASM * sizeof(u32); addr += sizeof(u32)) {
|
for(u64 addr = startAddr; addr < startAddr + MAX_LINES_OF_DISASM * sizeof(u32); addr += sizeof(u32)) {
|
||||||
auto disasm = core.cpu->Disassemble(addr);
|
auto disasm = Disassembler::GetInstance().Disassemble(addr);
|
||||||
std::string op_str;
|
auto isPc = addr == core.cpu->GetRegs().pc;
|
||||||
for(int i = 0; i < 3; i++) {
|
|
||||||
if(i < 2) {
|
|
||||||
if(!disasm.ops[i].empty()) {
|
|
||||||
op_str += disasm.ops[i];
|
|
||||||
if(!disasm.ops[i+1].empty()) op_str += ", ";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(!disasm.ops[i].empty()) op_str += disasm.ops[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto isPc = addr == core.cpu->GetRegs().oldPC;
|
|
||||||
if(isPc) {
|
if(isPc) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_TableRowBg, 0x809a9ade);
|
ImGui::PushStyleColor(ImGuiCol_TableRowBg, 0x809a9ade);
|
||||||
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, 0x807777bf);
|
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, 0x807777bf);
|
||||||
@@ -45,9 +34,25 @@ bool Debugger::render() {
|
|||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::TextColored(ImColor(0xffeaefb6), "%s", std::format("{:016X}:", disasm.address).c_str());
|
ImGui::TextColored(ImColor(0xffeaefb6), "%s", std::format("{:016X}:", disasm.address).c_str());
|
||||||
ImGui::TableSetColumnIndex(1);
|
ImGui::TableSetColumnIndex(1);
|
||||||
ImGui::TextColored(ImColor(0xffcbf1ae), "%s", std::format("{} {}", disasm.mnemonic, op_str).c_str());
|
ImGui::TextColored(ImColor(0xffcbf1ae), "%s", std::format("{} ", disasm.mnemonic).c_str());
|
||||||
|
ImGui::SameLine(0, 0);
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
if(i < 2) {
|
||||||
|
if(!disasm.ops[i].str.empty()) {
|
||||||
|
std::string op_str = disasm.ops[i].str;
|
||||||
|
if(!disasm.ops[i+1].str.empty()) op_str += ", ";
|
||||||
|
ImGui::TextColored(ImColor(disasm.ops[i].color), "%s", op_str.c_str());
|
||||||
|
ImGui::SameLine(0, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!disasm.ops[i].str.empty()) {
|
||||||
|
ImGui::TextColored(ImColor(disasm.ops[i].color), "%s", disasm.ops[i].str.c_str());
|
||||||
|
ImGui::SameLine(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
ImGui::TextColored(ImColor(0xff71efe5), "%s", std::format("{}", "// no comments for now!").c_str());
|
ImGui::TextColored(ImColor(0xff71efe5), "%s", std::format("{}", disasm.comment).c_str());
|
||||||
} else {
|
} else {
|
||||||
ImGui::TableSetColumnIndex(0);
|
ImGui::TableSetColumnIndex(0);
|
||||||
ImGui::TextColored(ImColor(0xffeaefb6), "????????????????");
|
ImGui::TextColored(ImColor(0xffeaefb6), "????????????????");
|
||||||
@@ -61,6 +66,11 @@ bool Debugger::render() {
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ImGui::TableGetHoveredColumn() == 2) {
|
||||||
|
// do the thing with the little fucking hover popup that shows the memory view
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
#include <EmuThread.hpp>
|
#include <EmuThread.hpp>
|
||||||
#include <KaizenGui.hpp>
|
#include <KaizenGui.hpp>
|
||||||
|
|
||||||
EmuThread::EmuThread(double &fps, RenderWidget &renderWidget,
|
EmuThread::EmuThread(double &fps, SettingsWindow &settings) noexcept : settings(settings), fps(fps) {}
|
||||||
SettingsWindow &settings) noexcept :
|
|
||||||
renderWidget(renderWidget), settings(settings), fps(fps) {}
|
|
||||||
|
|
||||||
void EmuThread::run() const noexcept {
|
void EmuThread::run() const noexcept {
|
||||||
n64::Core& core = n64::Core::GetInstance();
|
n64::Core& core = n64::Core::GetInstance();
|
||||||
@@ -45,9 +43,7 @@ void EmuThread::TogglePause() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::Reset() const noexcept {
|
void EmuThread::Reset() const noexcept {
|
||||||
n64::Core& core = n64::Core::GetInstance();
|
n64::Core::GetInstance().Reset();
|
||||||
core.Stop();
|
|
||||||
core.LoadROM(core.rom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::Stop() const noexcept {
|
void EmuThread::Stop() const noexcept {
|
||||||
|
|||||||
@@ -8,10 +8,9 @@ struct Core;
|
|||||||
}
|
}
|
||||||
|
|
||||||
class EmuThread final {
|
class EmuThread final {
|
||||||
RenderWidget &renderWidget;
|
|
||||||
bool started = false;
|
bool started = false;
|
||||||
public:
|
public:
|
||||||
explicit EmuThread(double &, RenderWidget &, SettingsWindow &) noexcept;
|
explicit EmuThread(double &, SettingsWindow &) noexcept;
|
||||||
~EmuThread() = default;
|
~EmuThread() = default;
|
||||||
void run() const noexcept;
|
void run() const noexcept;
|
||||||
void TogglePause() const noexcept;
|
void TogglePause() const noexcept;
|
||||||
|
|||||||
Reference in New Issue
Block a user