// cpu view (disassembly) #include "pch.h" static int con_disa_line(int line, uint32_t opcode, uint32_t addr) { int bg, fg, bgcur, bgbp; char *symbol; int addend = 1; bgcur = (addr == con.disa_cursor) ? (8) : (0); bgbp = (Gekko::Gekko->IsBreakpoint(addr)) ? (4) : (0); bg = (addr == Gekko::Gekko->regs.pc) ? (1) : (0); bg = bg ^ bgcur ^ bgbp; fg = 7; con_attr(fg, bg); con_clear_line(line, con.attr); symbol = SYMName(addr); if(symbol) { con_printf_at(0, line, "\x1%c%s\n", ConColor::GREEN, symbol); line++; addend++; con_clear_line(line, con.attr); } if(opcode == 1 /* no memory */) { con_printf_at( 0, line, "\x1%c%08X ", ConColor::NORM, addr); con_printf_at(10, line, "\x1%c%08X ", ConColor::CYAN, 0); con_printf_at(20, line, "\x1%c???", ConColor::NORM); return addend; } Gekko::AnalyzeInfo info = { 0 }; Gekko::Analyzer::Analyze(addr, opcode, &info); std::string text = Gekko::GekkoDisasm::Disasm(addr, &info); if(info.flow && info.Imm.Address != 0) { const char* dir; if (info.Imm.Address > addr) dir = " \x19"; else if (info.Imm.Address < addr) dir = " \x18"; else dir = " \x1b"; con_printf_at(0, line, "\x1%c%s\x1%c%s", ConColor::GREEN, text.c_str(), ConColor::CYAN, dir); symbol = SYMName(info.Imm.Address); if(symbol) { con_printf_at(47, line, "\x1%c ; %s", ConColor::BROWN, symbol); } } else con_printf_at(0, line, "\x1%c%s", ConColor::NORM, text.c_str()); if (text[0] == 'r' && text[1] == 'l') { int mb = info.paramBits[3]; int me = info.paramBits[4]; uint32_t mask = ((uint32_t)-1 >> mb) ^ ((me >= 31) ? 0 : ((uint32_t)-1) >> (me + 1)); con_printf_at (60, line, "\x1%cmask:0x%08X", ConColor::NORM, mask); } return addend; } void con_update_disa_window() { uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { int WIMG; pa = Gekko::Gekko->EffectiveToPhysical(con.disa_cursor, Gekko::MmuAccess::Execute, WIMG); } con_attr(0, 3); con_fill_line(wind.disa_y, 0xc4); if(wind.focus == WDISA) con_printf_at(0, wind.disa_y, "\x1%c\x1f", ConColor::WHITE); con_attr(0, 3); con_print_at(2, wind.disa_y, "F3"); con_printf_at( 6, wind.disa_y, " cursor:%08X phys:%08X pc:%08X", pa, Gekko::Gekko->regs.pc); con_attr(7, 0); uint32_t op, addr = con.text & ~3; wind.disa_sub_h = 0; for(int line=wind.disa_y+1; lineEffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG); if (pa != Gekko::BadAddress) { MIReadWord(pa, &op); } } int n = con_disa_line(line, op, addr); if(n > 1) wind.disa_sub_h += n - 1; line += n - 1; } } static BOOL disa_cur_visible() { DWORD limit; limit = con.text + (wind.disa_h - 1) * 4; return ((con.disa_cursor < limit) && (con.disa_cursor >= con.text)); } static void disa_goto(uint32_t addr) { if(wind.disa_nav_last < 256) { wind.disa_nav_hist[++wind.disa_nav_last] = con.disa_cursor; con.text = addr - 4 * wind.disa_h / 2 + 4; con.disa_cursor = addr; con.update |= CON_UPDATE_DISA; } } static void disa_return() { if(wind.disa_nav_last > 0) { con.disa_cursor = con.text = wind.disa_nav_hist[wind.disa_nav_last--]; con.text -= 4 * wind.disa_h / 2; con.update |= CON_UPDATE_DISA; } } static void disa_navigate() { uint32_t op = 0, addr = con.disa_cursor; uint32_t pa = Gekko::BadAddress; if (Gekko::Gekko) { int WIMG; pa = Gekko::Gekko->EffectiveToPhysical(addr, Gekko::MmuAccess::Execute, WIMG); } if (pa != Gekko::BadAddress) { MIReadWord(pa, &op); } if(op == 0) return; Gekko::AnalyzeInfo info = { 0 }; Gekko::Analyzer::Analyze(addr, op, &info); std::string text = Gekko::GekkoDisasm::Disasm(addr, &info); if(info.flow && info.Imm.Address != 0) disa_goto(info.Imm.Address); } void con_disa_key(char ascii, int vkey, int ctrl) { UNREFERENCED_PARAMETER(ascii); UNREFERENCED_PARAMETER(ctrl); switch(vkey) { case VK_HOME: con_set_disa_cur(con.disa_cursor); break; case VK_END: break; case VK_UP: if(con.disa_cursor < con.text) { con.disa_cursor = con.text; break; } if(con.disa_cursor >= (con.text + 4 * wind.disa_h - 4)) { con.disa_cursor = con.text + 4 * wind.disa_h - 8; break; } con.disa_cursor -= 4; if(con.disa_cursor < con.text) con.text -= 4; break; case VK_DOWN: if(con.disa_cursor < con.text) { con.disa_cursor = con.text; break; } if(con.disa_cursor >= (con.text + 4 * (wind.disa_h - wind.disa_sub_h) - 4)) { con.disa_cursor = con.text + 4 * (wind.disa_h - wind.disa_sub_h) - 8; break; } con.disa_cursor += 4; if(con.disa_cursor >= (con.text + ((wind.disa_h - wind.disa_sub_h) - 1) * 4)) con.text += 4; break; case VK_PRIOR: con.text -= 4 * wind.disa_h - 4; if(!disa_cur_visible()) con.disa_cursor = con.text; break; case VK_NEXT: con.text += 4 * (wind.disa_h - wind.disa_sub_h) - 4; if(!disa_cur_visible()) con.disa_cursor = con.text + ((wind.disa_h - wind.disa_sub_h) - 2) * 4; break; case VK_RETURN: disa_navigate(); // browse functions break; case VK_ESCAPE: disa_return(); break; } con.update |= CON_UPDATE_DISA; }