Things to neat up that I noticed with Hazel <3
This commit is contained in:
@@ -22,7 +22,12 @@ Core::Core() {
|
||||
void Core::Stop() {
|
||||
pause = true;
|
||||
romLoaded = false;
|
||||
Reset();
|
||||
}
|
||||
|
||||
void Core::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); }
|
||||
|
||||
@@ -20,6 +20,7 @@ struct Core {
|
||||
}
|
||||
|
||||
void Stop();
|
||||
void Reset();
|
||||
void LoadROM(const std::string &);
|
||||
[[nodiscard]] bool LoadTAS(const fs::path &) const;
|
||||
void Run(float volumeL, float volumeR);
|
||||
|
||||
@@ -10,6 +10,5 @@ struct BaseCPU {
|
||||
virtual void Reset() = 0;
|
||||
virtual Mem &GetMem() = 0;
|
||||
virtual Registers &GetRegs() = 0;
|
||||
[[nodiscard]] virtual Disassembler::DisassemblyResult Disassemble(u32) = 0;
|
||||
};
|
||||
} // namespace n64
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include <Disassembler.hpp>
|
||||
#include <Core.hpp>
|
||||
|
||||
Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 address, const u32 instruction) const {
|
||||
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);
|
||||
|
||||
if (count <= 0)
|
||||
@@ -15,9 +16,21 @@ Disassembler::DisassemblyResult Disassembler::DisassembleSimple(const u32 addres
|
||||
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 {
|
||||
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);
|
||||
|
||||
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 += result.mnemonic + "\t";
|
||||
result.comment = "// ";
|
||||
|
||||
const cs_detail *details = insn[0].detail;
|
||||
auto formatOperand = [&](const cs_mips_op &operand) {
|
||||
switch (operand.type) {
|
||||
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:
|
||||
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:
|
||||
return std::format("{}", cs_reg_name(handle, operand.reg));
|
||||
return DisassemblyResult::Operand{
|
||||
0xffaef1eb,
|
||||
std::format("{}", cs_reg_name(handle, operand.reg))
|
||||
};
|
||||
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++) {
|
||||
result.ops[i] = formatOperand(details->mips.operands[i]);
|
||||
result.full += result.ops[i] + "\t";
|
||||
result.full += result.ops[i].str + "\t";
|
||||
}
|
||||
|
||||
result.full += "\t// ";
|
||||
|
||||
// TODO: generate a comment
|
||||
result.full += result.comment;
|
||||
|
||||
cs_free(insn, count);
|
||||
|
||||
|
||||
@@ -10,24 +10,25 @@ struct Disassembler {
|
||||
std::string full;
|
||||
u64 address;
|
||||
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 ret(rsp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[[nodiscard]] DisassemblyResult Disassemble(const u32 address, const u32 instruction) const {
|
||||
return details ? DisassembleDetailed(address, instruction) : DisassembleSimple(address, instruction);
|
||||
}
|
||||
|
||||
~Disassembler() { cs_close(&handle); }
|
||||
|
||||
private:
|
||||
[[nodiscard]] DisassemblyResult Disassemble(const u32 address) const;
|
||||
[[nodiscard]] DisassemblyResult DisassembleDetailed(u32 address, u32 instruction) const;
|
||||
[[nodiscard]] DisassemblyResult DisassembleSimple(u32 address, u32 instruction) const;
|
||||
|
||||
private:
|
||||
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) !=
|
||||
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() {
|
||||
CheckCompareInterrupt();
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ struct Interpreter : BaseCPU {
|
||||
Mem &GetMem() override { return mem; }
|
||||
|
||||
Registers &GetRegs() override { return regs; }
|
||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override;
|
||||
|
||||
private:
|
||||
Registers regs;
|
||||
Mem mem;
|
||||
|
||||
@@ -107,8 +107,26 @@ int JIT::Step() {
|
||||
trace("\tMIPS code (guest PC = 0x{:016X}):", blockPC);
|
||||
while (!instrEndsBlock) {
|
||||
// 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++;
|
||||
|
||||
blockOldPC = blockPC;
|
||||
@@ -118,17 +136,9 @@ int JIT::Step() {
|
||||
if((instrEndsBlock = InstrEndsBlock(instruction)))
|
||||
continue;
|
||||
|
||||
/*u32 bswapped = std::byteswap(instruction);
|
||||
auto count = cs_disasm(disassemblerMips, reinterpret_cast<const u8 *>(&bswapped), 4, blockPC, 0, &insn);
|
||||
trace("{}", Disassembler::GetInstance().DisassembleSimple(paddr, instruction).full);
|
||||
|
||||
if (count > 0) {
|
||||
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()) {
|
||||
/*if(ShouldServiceInterrupt()) {
|
||||
regs.cop0.FireException(ExceptionCode::Interrupt, 0, blockPC);
|
||||
return 1;
|
||||
}*/
|
||||
|
||||
@@ -39,9 +39,6 @@ struct JIT : BaseCPU {
|
||||
Mem &GetMem() override { return mem; }
|
||||
|
||||
Registers &GetRegs() override { return regs; }
|
||||
|
||||
[[nodiscard]] Disassembler::DisassemblyResult Disassemble(u32) override { return {}; }
|
||||
|
||||
private:
|
||||
Xbyak::CodeGenerator code{kCodeCacheAllocSize};
|
||||
Registers regs;
|
||||
|
||||
@@ -13,7 +13,6 @@ Mem::Mem(JIT *jit) : flash(saveData), jit(jit) {
|
||||
}
|
||||
|
||||
void Mem::Reset() {
|
||||
std::ranges::fill(rom.cart, 0);
|
||||
std::ranges::fill(isviewer, 0);
|
||||
flash.Reset();
|
||||
if (saveData.is_mapped()) {
|
||||
@@ -454,7 +453,7 @@ void Mem::Write<u32>(const u32 paddr, const u32 val) {
|
||||
}
|
||||
|
||||
#ifndef __aarch64__
|
||||
void Mem::WriteJIT(const const u32 paddr, const u64 val) {
|
||||
void Mem::WriteJIT(const u32 paddr, const u64 val) {
|
||||
WriteInterpreter(paddr, val);
|
||||
if (jit)
|
||||
jit->InvalidateBlock(paddr);
|
||||
|
||||
@@ -76,7 +76,7 @@ void Cop0::tlbw(const int index_) {
|
||||
|
||||
void Cop0::tlbp() {
|
||||
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;
|
||||
} else {
|
||||
index.raw = 0;
|
||||
|
||||
@@ -14,28 +14,17 @@ bool Debugger::render() {
|
||||
ImGui::SameLine();
|
||||
ImGui::Checkbox("Follow program counter:", &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)) {
|
||||
ImGui::TableSetupColumn("Address");
|
||||
ImGui::TableSetupColumn("Mnemonic");
|
||||
ImGui::TableSetupColumn("Instruction");
|
||||
ImGui::TableSetupColumn("Comment");
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
for(u64 addr = startAddr; addr < startAddr + MAX_LINES_OF_DISASM * sizeof(u32); addr += sizeof(u32)) {
|
||||
auto disasm = core.cpu->Disassemble(addr);
|
||||
std::string op_str;
|
||||
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;
|
||||
auto disasm = Disassembler::GetInstance().Disassemble(addr);
|
||||
auto isPc = addr == core.cpu->GetRegs().pc;
|
||||
if(isPc) {
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBg, 0x809a9ade);
|
||||
ImGui::PushStyleColor(ImGuiCol_TableRowBgAlt, 0x807777bf);
|
||||
@@ -45,9 +34,25 @@ bool Debugger::render() {
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::TextColored(ImColor(0xffeaefb6), "%s", std::format("{:016X}:", disasm.address).c_str());
|
||||
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::TextColored(ImColor(0xff71efe5), "%s", std::format("{}", "// no comments for now!").c_str());
|
||||
ImGui::TextColored(ImColor(0xff71efe5), "%s", std::format("{}", disasm.comment).c_str());
|
||||
} else {
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::TextColored(ImColor(0xffeaefb6), "????????????????");
|
||||
@@ -61,6 +66,11 @@ bool Debugger::render() {
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
}
|
||||
|
||||
if(ImGui::TableGetHoveredColumn() == 2) {
|
||||
// do the thing with the little fucking hover popup that shows the memory view
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
#include <EmuThread.hpp>
|
||||
#include <KaizenGui.hpp>
|
||||
|
||||
EmuThread::EmuThread(double &fps, RenderWidget &renderWidget,
|
||||
SettingsWindow &settings) noexcept :
|
||||
renderWidget(renderWidget), settings(settings), fps(fps) {}
|
||||
EmuThread::EmuThread(double &fps, SettingsWindow &settings) noexcept : settings(settings), fps(fps) {}
|
||||
|
||||
void EmuThread::run() const noexcept {
|
||||
n64::Core& core = n64::Core::GetInstance();
|
||||
@@ -45,9 +43,7 @@ void EmuThread::TogglePause() const noexcept {
|
||||
}
|
||||
|
||||
void EmuThread::Reset() const noexcept {
|
||||
n64::Core& core = n64::Core::GetInstance();
|
||||
core.Stop();
|
||||
core.LoadROM(core.rom);
|
||||
n64::Core::GetInstance().Reset();
|
||||
}
|
||||
|
||||
void EmuThread::Stop() const noexcept {
|
||||
|
||||
@@ -8,10 +8,9 @@ struct Core;
|
||||
}
|
||||
|
||||
class EmuThread final {
|
||||
RenderWidget &renderWidget;
|
||||
bool started = false;
|
||||
public:
|
||||
explicit EmuThread(double &, RenderWidget &, SettingsWindow &) noexcept;
|
||||
explicit EmuThread(double &, SettingsWindow &) noexcept;
|
||||
~EmuThread() = default;
|
||||
void run() const noexcept;
|
||||
void TogglePause() const noexcept;
|
||||
|
||||
Reference in New Issue
Block a user