NESemu/src/debugger/Disassembler.cpp
2022-02-28 17:04:20 +01:00

183 lines
3.8 KiB
C++

#include "Disassembler.hpp"
#include <iomanip>
#include <imgui/imgui.h>
#include "../Mapper.hpp"
#include "../CPU.hpp"
#define FORMAT std::setfill('0') << std::setw(4) << std::hex << std::uppercase
Disassembler::Disassembler(CPU* cpu) :
DebugWindow("Disassembler"), cpu(cpu)
{
}
void Disassembler::OnRender()
{
static bool scrollCenter = true;
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title.c_str(), &isOpen))
{
ImGui::End();
return;
}
std::string disassembly;
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 0.8f, 0.8f, 0.8f, 1.0f });
if (cpu->pastInstructions.size() < 50)
{
for (int i = 0; i < 50 - cpu->pastInstructions.size(); i++)
{
ImGui::Text("-");
}
}
for (auto pair : cpu->pastInstructions)
{
Disassemble(disassembly, pair.first, pair.second);
ImGui::Text("- %s", disassembly.c_str());
}
ImGui::PopStyleColor();
ImGui::Separator();
uint16_t pc = cpu->pc.Raw;
Disassemble(disassembly, pc);
ImGui::Text("> %s", disassembly.c_str());
if (scrollCenter)
{
ImGui::SetScrollHereY(0.5f);
scrollCenter = false;
}
ImGui::Separator();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4{ 0.8f, 0.8f, 0.8f, 1.0f });
for (int i = 0; i < 50; i++)
{
Disassemble(disassembly, pc);
ImGui::Text("+ %s", disassembly.c_str());
}
ImGui::PopStyleColor();
ImGui::End();
}
void Disassembler::Disassemble(std::string& target, uint16_t& pc)
{
Instruction* currentInstr = &cpu->InstructionTable[cpu->Read(pc)];
Disassemble(target, pc, currentInstr);
pc += currentInstr->Size;
}
void Disassembler::Disassemble(std::string& target, uint16_t pc, const Instruction* instr)
{
std::stringstream ss;
ss << FORMAT << pc << ": ";
for (int i = 0; i < instr->Size; i++)
{
ss << FORMAT << std::setw(2) << (Word)cpu->Read(pc + i) << " ";
}
ss << std::string(15 - ss.str().size(), ' ') << instr->Mnemonic << " ";
Address absoluteAddress;
switch (instr->AddrType)
{
case Addressing::ACC:
ss << "A";
break;
case Addressing::ABS:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
absoluteAddress.Bytes.hi = cpu->Read(pc + 2);
ss << "$" << FORMAT << absoluteAddress.Raw;
} break;
case Addressing::ABX:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
absoluteAddress.Bytes.hi = cpu->Read(pc + 2);
ss << "$" << FORMAT << absoluteAddress.Raw << ",X";
} break;
case Addressing::ABY:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
absoluteAddress.Bytes.hi = cpu->Read(pc + 2);
ss << "$" << FORMAT << absoluteAddress.Raw << ",Y";
} break;
case Addressing::IMM:
{
Word value = cpu->Read(pc + 1);
ss << "#$" << FORMAT << std::setw(2) << value;
} break;
case Addressing::IMP:
break;
case Addressing::IND:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
absoluteAddress.Bytes.hi = cpu->Read(pc + 2);
ss << "($" << FORMAT << absoluteAddress.Raw << ")";
} break;
case Addressing::IDX:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
ss << "($" << FORMAT << std::setw(2) << (Word)absoluteAddress.Bytes.lo << ",X)";
} break;
case Addressing::IDY:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
ss << "($" << FORMAT << std::setw(2) << (Word)absoluteAddress.Bytes.lo << "),Y";
} break;
case Addressing::REL:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
ss << "$" << FORMAT << std::setw(2) << (Word)absoluteAddress.Bytes.lo;
} break;
case Addressing::ZPG:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
ss << "$" << FORMAT << std::setw(2) << (Word)absoluteAddress.Bytes.lo;
} break;
case Addressing::ZPX:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
ss << "$" << FORMAT << std::setw(2) << (Word)absoluteAddress.Bytes.lo << ",X";
} break;
case Addressing::ZPY:
{
absoluteAddress.Bytes.lo = cpu->Read(pc + 1);
ss << "$" << FORMAT << std::setw(2) << (Word)absoluteAddress.Bytes.lo << ",Y";
} break;
}
target = ss.str();
}