Things to neat up that I noticed with Hazel <3

This commit is contained in:
SimoZ64
2025-07-29 22:46:34 +02:00
parent 01d05ca8fd
commit ff4cd66bdb
14 changed files with 104 additions and 72 deletions

View File

@@ -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); }

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
}*/

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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;