pcsx2/windows/Debugger.c

563 lines
16 KiB
C

/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2003 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <windows.h>
#include <commctrl.h>
#include <windowsx.h>
#include <stdio.h>
#include "resource.h"
#include "Debugger.h"
#include "Common.h"
#include "win32.h"
#include "PsxMem.h"
#include "R3000A.h"
extern void (*IOP_DEBUG_BSC[64])(char *buf);
extern void UpdateR5900op();
void RefreshIOPDebugger(void);
extern int ISR3000A;//for disasm
HWND hWnd_debugdisasm, hWnd_debugscroll,hWnd_IOP_debugdisasm, hWnd_IOP_debugscroll;
unsigned long DebuggerPC = 0;
HWND hRegDlg;//for debug registers..
HWND debughWnd;
unsigned long DebuggerIOPPC=0;
HWND hIOPDlg;//IOP debugger
void RefreshDebugAll()//refresh disasm and register window
{
RefreshDebugger();
RefreshIOPDebugger();
UpdateRegs();
}
void MakeDebugOpcode(void)
{
memRead32( opcode_addr, &cpuRegs.code );
}
void MakeIOPDebugOpcode(void)
{
psxRegs.code = PSXMu32( opcode_addr);
}
BOOL HasBreakpoint()
{
int t;
for (t = 0; t < NUM_BREAKPOINTS; t++)
{
switch (bkpt_regv[t].type) {
case 1: // exec
if (cpuRegs.pc == bkpt_regv[t].value) return TRUE;
break;
case 2: // count
if ((cpuRegs.cycle - 10) <= bkpt_regv[t].value &&
(cpuRegs.cycle + 10) >= bkpt_regv[t].value) return TRUE;
break;
}
}
return FALSE;
}
BOOL APIENTRY JumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[16];
unsigned long temp;
switch (message)
{
case WM_INITDIALOG:
sprintf(buf, "%08X", cpuRegs.pc);
SetDlgItemText(hDlg, IDC_JUMP_PC, buf);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
GetDlgItemText(hDlg, IDC_JUMP_PC, buf, 9);
buf[8] = 0;
sscanf(buf, "%x", &temp);
temp &= 0xFFFFFFFC;
DebuggerPC = temp - 0x00000038;
EndDialog(hDlg, TRUE);
} else if (LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, TRUE);
}
return TRUE;
}
return FALSE;
}
extern void EEDumpRegs(FILE * fp);
extern void IOPDumpRegs(FILE * fp);
BOOL APIENTRY DumpProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char start[16], end[16], fname[128], tmp[128], buf[128];
unsigned long start_pc, end_pc, temp;
FILE *fp;
switch (message)
{
case WM_INITDIALOG:
sprintf(buf, "%08X", cpuRegs.pc);
SetDlgItemText(hDlg, IDC_DUMP_START, buf);
SetDlgItemText(hDlg, IDC_DUMP_END, buf);
SetDlgItemText(hDlg, IDC_DUMP_FNAME, "EEdisasm.txt");
sprintf(buf, "%08X", psxRegs.pc);
SetDlgItemText(hDlg, IDC_DUMP_STARTIOP, buf);
SetDlgItemText(hDlg, IDC_DUMP_ENDIOP, buf);
SetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, "IOPdisasm.txt");
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
GetDlgItemText(hDlg, IDC_DUMP_START, start, 9);
start[8] = 0;
sscanf(start, "%x", &start_pc);
start_pc &= 0xFFFFFFFC;
GetDlgItemText(hDlg, IDC_DUMP_END, end, 9);
end[8] = 0;
sscanf(end, "%x", &end_pc);
end_pc &= 0xFFFFFFFC;
GetDlgItemText(hDlg, IDC_DUMP_FNAME, fname, 128);
fp = fopen(fname, "wt");
if (fp == NULL)
{
//MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK);
}
else
{
fprintf(fp,"----------------------------------\n");
fprintf(fp,"EE DISASM TEXT DOCUMENT BY PCSX2 \n");
fprintf(fp,"----------------------------------\n");
for (temp = start_pc; temp <= end_pc; temp += 4)
{
opcode_addr=temp;
MakeDebugOpcode();
OpcodePrintTable[(cpuRegs.code) >> 26](tmp);
if (HasBreakpoint(temp))
{
sprintf(buf, "*%08X %08X: %s", temp, cpuRegs.code, tmp);
}
else
{
sprintf(buf, "%08X %08X: %s", temp, cpuRegs.code, tmp);
}
fprintf(fp, "%s\n", buf);
}
fprintf(fp,"\n\n\n----------------------------------\n");
fprintf(fp,"EE REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n");
fprintf(fp,"----------------------------------\n");
EEDumpRegs(fp);
fclose(fp);
}
GetDlgItemText(hDlg, IDC_DUMP_STARTIOP, start, 9);
start[8] = 0;
sscanf(start, "%x", &start_pc);
start_pc &= 0xFFFFFFFC;
GetDlgItemText(hDlg, IDC_DUMP_ENDIOP, end, 9);
end[8] = 0;
sscanf(end, "%x", &end_pc);
end_pc &= 0xFFFFFFFC;
GetDlgItemText(hDlg, IDC_DUMP_FNAMEIOP, fname, 128);
fp = fopen(fname, "wt");
if (fp == NULL)
{
//MessageBox(MainhWnd, "Can't open file for writing!", NULL, MB_OK);
}
else
{
fprintf(fp,"----------------------------------\n");
fprintf(fp,"IOP DISASM TEXT DOCUMENT BY PCSX2 \n");
fprintf(fp,"----------------------------------\n");
for (temp = start_pc; temp <= end_pc; temp += 4)
{
opcode_addr=temp;
MakeIOPDebugOpcode();
IOP_DEBUG_BSC[(psxRegs.code) >> 26](tmp);
sprintf(buf, "%08X %08X: %s", temp, psxRegs.code, tmp);
fprintf(fp, "%s\n", buf);
}
fprintf(fp,"\n\n\n----------------------------------\n");
fprintf(fp,"IOP REGISTER DISASM TEXT DOCUMENT BY PCSX2 \n");
fprintf(fp,"----------------------------------\n");
IOPDumpRegs(fp);
fclose(fp);
}
EndDialog(hDlg, TRUE);
} else if (LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, TRUE);
}
return TRUE;
}
return FALSE;
}
BOOL APIENTRY BpexecProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[16];
switch (message)
{
case WM_INITDIALOG:
sprintf(buf, "%08X", bkpt_regv[0].value);
SetDlgItemText(hDlg, IDC_EXECBP, buf);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
GetDlgItemText(hDlg, IDC_EXECBP, buf, 9);
buf[8] = 0;
sscanf(buf, "%x", &bkpt_regv[0].value);
bkpt_regv[0].type = 1;
EndDialog(hDlg, TRUE);
} else if (LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, TRUE);
}
return TRUE;
}
return FALSE;
}
BOOL APIENTRY BpcntProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
char buf[16];
switch (message)
{
case WM_INITDIALOG:
sprintf(buf, "%08X", bkpt_regv[1].value);
SetDlgItemText(hDlg, IDC_CNTBP, buf);
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
GetDlgItemText(hDlg, IDC_CNTBP, buf, 9);
buf[8] = 0;
sscanf(buf, "%x", &bkpt_regv[1].value);
bkpt_regv[1].type = 2;
EndDialog(hDlg, TRUE);
} else if (LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, TRUE);
}
return TRUE;
}
return FALSE;
}
HINSTANCE m2_hInst;
HWND m2_hWnd;
HWND hIopDlg;
LRESULT CALLBACK IOP_DISASM(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
hWnd_IOP_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM_IOP);
hWnd_IOP_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL_IOP);
SendMessage(hWnd_IOP_debugdisasm, LB_INITSTORAGE, 29, 1131);
SendMessage(hWnd_IOP_debugscroll, SBM_SETRANGE, 0, MAXLONG);
SendMessage(hWnd_IOP_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE);
RefreshIOPDebugger();
return (TRUE);
case WM_VSCROLL:
switch ((int) LOWORD(wParam))
{
case SB_LINEDOWN: DebuggerIOPPC += 0x00000004; RefreshIOPDebugger(); break;
case SB_LINEUP: DebuggerIOPPC -= 0x00000004; RefreshIOPDebugger(); break;
case SB_PAGEDOWN: DebuggerIOPPC += 0x00000029; RefreshIOPDebugger(); break;
case SB_PAGEUP: DebuggerIOPPC -= 0x00000029; RefreshIOPDebugger(); break;
}
return TRUE;
break;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case (IDOK || IDCANCEL):
EndDialog(hDlg,TRUE);
return(TRUE);
break;
}
break;
}
return(FALSE);
}
int CreatePropertySheet2(HWND hwndOwner)
{
PROPSHEETPAGE psp[1];
PROPSHEETHEADER psh;
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USETITLE;
psp[0].hInstance = m2_hInst;
psp[0].pszTemplate = MAKEINTRESOURCE( IDD_IOP_DEBUG);
psp[0].pszIcon = NULL;
psp[0].pfnDlgProc =(DLGPROC)IOP_DISASM;
psp[0].pszTitle = "Iop Disasm";
psp[0].lParam = 0;
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS;
psh.hwndParent =hwndOwner;
psh.hInstance = m2_hInst;
psh.pszIcon = NULL;
psh.pszCaption = (LPSTR) "IOP Debugger";
psh.nStartPage = 0;
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
return (PropertySheet(&psh));
}
BOOL APIENTRY DebuggerProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
FARPROC jmpproc, dumpproc;
FARPROC bpexecproc, bpcntproc;
u32 oldpc = 0;
switch (message)
{
case WM_INITDIALOG:
// if (OpenPlugins() == -1) return TRUE;//moved to WinMain.c
ShowCursor(TRUE);
SetWindowText(hDlg, "R5900 Debugger");
debughWnd=hDlg;
DebuggerPC = 0;
// Clear all breakpoints.
memset(bkpt_regv, 0, sizeof(bkpt_regv));
hWnd_debugdisasm = GetDlgItem(hDlg, IDC_DEBUG_DISASM);
hWnd_debugscroll = GetDlgItem(hDlg, IDC_DEBUG_SCROLL);
SendMessage(hWnd_debugdisasm, LB_INITSTORAGE, 29, 1131);
SendMessage(hWnd_debugscroll, SBM_SETRANGE, 0, MAXLONG);
SendMessage(hWnd_debugscroll, SBM_SETPOS, MAXLONG / 2, TRUE);
hRegDlg = (HWND)CreatePropertySheet(hDlg);
hIopDlg = (HWND)CreatePropertySheet2(hDlg);
UpdateRegs();
SetWindowPos(hRegDlg, NULL, 425, 0, 600, 515,0 );
SetWindowPos(hIopDlg, NULL, 0 ,515,600,230,0);
RefreshDebugger();
RefreshIOPDebugger();
return TRUE;
case WM_VSCROLL:
switch ((int) LOWORD(wParam))
{
case SB_LINEDOWN: DebuggerPC += 0x00000004; RefreshDebugAll(); break;
case SB_LINEUP: DebuggerPC -= 0x00000004; RefreshDebugAll(); break;
case SB_PAGEDOWN: DebuggerPC += 0x00000074; RefreshDebugAll(); break;
case SB_PAGEUP: DebuggerPC -= 0x00000074; RefreshDebugAll(); break;
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_DEBUG_STEP:
oldpc = psxRegs.pc;
Cpu->Step();
while(oldpc == psxRegs.pc) Cpu->Step();
DebuggerPC = 0;
RefreshDebugAll();
return TRUE;
case IDC_DEBUG_SKIP:
cpuRegs.pc+= 4;
DebuggerPC = 0;
RefreshDebugAll();
return TRUE;
case IDC_DEBUG_GO:
for (;;) {
if (HasBreakpoint()) {
Cpu->Step();
break;
}
Cpu->Step();
}
DebuggerPC = 0;
RefreshDebugAll();
return TRUE;
case IDC_DEBUG_LOG:
#ifdef PCSX2_DEVBUILD
Log = 1 - Log;
#endif
return TRUE;
case IDC_DEBUG_RESETTOPC:
DebuggerPC = 0;
RefreshDebugAll();
return TRUE;
case IDC_DEBUG_JUMP:
jmpproc = MakeProcInstance((FARPROC)JumpProc, MainhInst);
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_JUMP), debughWnd, (DLGPROC)jmpproc);
FreeProcInstance(jmpproc);
RefreshDebugAll();
return TRUE;
case IDC_CPUOP:
UpdateR5900op();
return TRUE;
case IDC_DEBUG_BP_EXEC:
bpexecproc = MakeProcInstance((FARPROC)BpexecProc, MainhInst);
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPEXEC), debughWnd, (DLGPROC)bpexecproc);
FreeProcInstance(bpexecproc);
return TRUE;
case IDC_DEBUG_BP_COUNT:
bpcntproc = MakeProcInstance((FARPROC)BpcntProc, MainhInst);
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_BPCNT), debughWnd, (DLGPROC)bpcntproc);
FreeProcInstance(bpcntproc);
return TRUE;
case IDC_DEBUG_BP_CLEAR:
memset(bkpt_regv, 0, sizeof(bkpt_regv));
return TRUE;
case IDC_DEBUG_DUMP:
dumpproc = MakeProcInstance((FARPROC)DumpProc, MainhInst);
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_DUMP), debughWnd, (DLGPROC)dumpproc);
FreeProcInstance(dumpproc);
return TRUE;
case IDC_DEBUG_MEMORY:
DialogBox(gApp.hInstance, MAKEINTRESOURCE(IDD_MEMORY), debughWnd, (DLGPROC)MemoryProc);
return TRUE;
case IDC_DEBUG_CLOSE:
EndDialog(hRegDlg ,TRUE);
EndDialog(hDlg,TRUE);
EndDialog(hIopDlg,TRUE);
ClosePlugins();
return TRUE;
}
break;
}
return FALSE;
}
void RefreshDebugger(void)
{
unsigned long t;
int cnt;
if (DebuggerPC == 0)
DebuggerPC = cpuRegs.pc; //- 0x00000038;
SendMessage(hWnd_debugdisasm, LB_RESETCONTENT, 0, 0);
for (t = DebuggerPC, cnt = 0; t < (DebuggerPC + 0x00000074); t += 0x00000004, cnt++)
{
// Make the opcode.
u32 *mem = (u32*)PSM(t);
char *str;
if (mem == NULL) {
char nullAddr[256];
sprintf(nullAddr, "%8.8lx 00000000: NULL MEMORY", t); str = nullAddr;
} else {
str = disR5900Fasm(*mem, t);
}
SendMessage(hWnd_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str);
}
}
void RefreshIOPDebugger(void)
{
unsigned long t;
int cnt;
DebuggerIOPPC = psxRegs.pc; //- 0x00000038;
SendMessage(hWnd_IOP_debugdisasm, LB_RESETCONTENT, 0, 0);
for (t = DebuggerIOPPC, cnt = 0; t < (DebuggerIOPPC + 0x00000029); t += 0x00000004, cnt++)
{
// Make the opcode.
u32 mem = PSXMu32(t);
char *str = disR3000Fasm(mem, t);
SendMessage(hWnd_IOP_debugdisasm, LB_ADDSTRING, 0, (LPARAM)str);
}
}