mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
224 lines
4.9 KiB
C++
224 lines
4.9 KiB
C++
// console init code.
|
|
//
|
|
// recommended console font size is 6x9.
|
|
#include "pch.h"
|
|
|
|
// all console important variables are here
|
|
CONControl con;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
static BOOL CALLBACK WndEnumProc(HWND hWnd, LPARAM lpParam)
|
|
{
|
|
TCHAR szClassName[1024];
|
|
DWORD dwPid = 0;
|
|
|
|
ZeroMemory(szClassName, sizeof(szClassName));
|
|
|
|
if(!GetClassName(hWnd, szClassName, sizeof(szClassName))) return TRUE;
|
|
if(lstrcmp(szClassName, TEXT("tty")) != 0) return TRUE;
|
|
|
|
GetWindowThreadProcessId(hWnd, &dwPid);
|
|
if(dwPid == GetCurrentProcessId())
|
|
{
|
|
*(HWND*)lpParam = hWnd;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static HWND MyGetConsoleWindow(void)
|
|
{
|
|
HWND hwnd = NULL;
|
|
EnumWindows((WNDENUMPROC)WndEnumProc, (LPARAM)&hwnd);
|
|
return hwnd;
|
|
}
|
|
|
|
void con_open()
|
|
{
|
|
DWORD flags;
|
|
COORD coord;
|
|
SMALL_RECT rect;
|
|
RECT wndrect;
|
|
|
|
if(con.active) return;
|
|
|
|
// clear internal structures
|
|
memset(&roll, 0, sizeof(ROLLControl));
|
|
memset(&wind, 0, sizeof(WINDControl));
|
|
memset(con.buf, 0, sizeof(con.buf));
|
|
|
|
cmd_init_handlers();
|
|
|
|
// prepare console structures
|
|
con_set_autoscroll(TRUE);
|
|
roll.rollpos = con_wraproll(0, -1);
|
|
con_memorize_cpu_regs();
|
|
|
|
wind.full = 0;
|
|
wind.visible |= CON_UPDATE_ALL;
|
|
wind.focus = WCONSOLE;
|
|
wind.regs_h = 17;
|
|
wind.data_h = 8;
|
|
wind.disa_h = 28;
|
|
wind.disa_sub_h = 0;
|
|
con_recalc_wnds();
|
|
|
|
con.data = 0x80000000;
|
|
con.text = Gekko::Gekko->regs.pc;
|
|
con_set_disa_cur(con.text);
|
|
strcpy_s (con.logfile, sizeof(con.logfile), CON_LOG_FILE);
|
|
|
|
// create console
|
|
AllocConsole();
|
|
con.hwnd = MyGetConsoleWindow();
|
|
|
|
// get input/ouput handles
|
|
con.input = GetStdHandle(STD_INPUT_HANDLE);
|
|
assert(con.input != INVALID_HANDLE_VALUE);
|
|
con.output = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
assert(con.output != INVALID_HANDLE_VALUE);
|
|
|
|
// setup console window
|
|
GetConsoleCursorInfo(con.output, &con.curinfo);
|
|
GetConsoleMode(con.input, &flags);
|
|
flags &= ~ENABLE_MOUSE_INPUT;
|
|
SetConsoleMode(con.input, flags);
|
|
|
|
rect.Top = rect.Left = 0;
|
|
rect.Right = CON_WIDTH - 1;
|
|
rect.Bottom = CON_HEIGHT - 1;
|
|
|
|
coord.X = CON_WIDTH;
|
|
coord.Y = CON_HEIGHT;
|
|
|
|
SetConsoleWindowInfo(con.output, TRUE, &rect);
|
|
SetConsoleScreenBufferSize(con.output, coord);
|
|
|
|
// change window layout
|
|
if(con.hwnd)
|
|
while(1)
|
|
{
|
|
GetWindowRect(con.hwnd, &wndrect);
|
|
if(wndrect.right >= GetSystemMetrics(SM_CXSCREEN)) break;
|
|
SetWindowPos(
|
|
con.hwnd,
|
|
HWND_TOP,
|
|
GetSystemMetrics(SM_CXSCREEN) - (wndrect.right - wndrect.left),
|
|
0, 0, 0, SWP_NOSIZE);
|
|
}
|
|
SetConsoleTitleA("Dolwin Debug Console");
|
|
|
|
con.active = TRUE;
|
|
con.update |= CON_UPDATE_ALL;
|
|
|
|
DBReport("Debugger is running. Type help for quick reference.\n");
|
|
|
|
con_refresh();
|
|
}
|
|
|
|
void con_close()
|
|
{
|
|
if(!con.active) return;
|
|
|
|
con.cmds.clear();
|
|
|
|
// clear NOP history
|
|
if(con.nopHist)
|
|
{
|
|
free(con.nopHist);
|
|
con.nopHist = NULL;
|
|
con.nopNum = 0;
|
|
}
|
|
|
|
// close console
|
|
// Don't touch console handles, they can be used by Visual Studio or by other parasites.
|
|
FreeConsole();
|
|
|
|
// close log file
|
|
if(con.logf)
|
|
{
|
|
fclose(con.logf);
|
|
con.logf = NULL;
|
|
}
|
|
|
|
con.active = FALSE;
|
|
}
|
|
|
|
static void dummy(const char* text, ...) {}
|
|
static void dummy2(DbgChannel chan, const char* text, ...) {}
|
|
|
|
void con_start()
|
|
{
|
|
uint32_t main = SYMAddress("main");
|
|
if(main) con_set_disa_cur(main);
|
|
else con_set_disa_cur(Gekko::Gekko->regs.pc);
|
|
|
|
con.update = CON_UPDATE_ALL;
|
|
con_refresh();
|
|
|
|
while (!con.exitPending)
|
|
{
|
|
con_read_input(1);
|
|
con_refresh();
|
|
Sleep(10);
|
|
}
|
|
|
|
con_close();
|
|
|
|
DBHalt = dummy;
|
|
DBReport = dummy;
|
|
DBReport2 = dummy2;
|
|
|
|
con.exitPending = false;
|
|
}
|
|
|
|
void con_break(const char *reason)
|
|
{
|
|
if(reason) con_print(ConColor::GREEN, "\ndebugger breaks%s. press F5 to continue.\n", reason);
|
|
if (Gekko::Gekko) Gekko::Gekko->Suspend();
|
|
con_set_disa_cur(Gekko::Gekko->regs.pc);
|
|
}
|
|
|
|
void con_command(std::vector<std::string>& args, int lnum)
|
|
{
|
|
// Poke Jdi
|
|
|
|
if (Debug::Hub.CommandExists(args))
|
|
{
|
|
Json::Value * output = Debug::Hub.Execute(args);
|
|
if (output != nullptr)
|
|
{
|
|
delete output;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Legacy commands (will be migrated to Jdi afterwards)
|
|
|
|
auto it = con.cmds.find(args[0]);
|
|
|
|
if (it != con.cmds.end())
|
|
{
|
|
it->second(args);
|
|
}
|
|
else
|
|
{
|
|
if (lnum) con_print(ConColor::NORM, "unknown script command in line %i, see \'help\'", lnum);
|
|
else con_print(ConColor::NORM, "unknown command, try \'help\'");
|
|
}
|
|
}
|
|
|
|
// execution
|
|
|
|
// step into instruction
|
|
void con_step_into()
|
|
{
|
|
if (Gekko::Gekko)
|
|
{
|
|
Gekko::Gekko->Step();
|
|
con.text = Gekko::Gekko->regs.pc - 4 * wind.disa_h / 2 + 4;
|
|
con.update |= CON_UPDATE_ALL;
|
|
}
|
|
}
|