add FORBID breakpoints - regions which block breakpoints from happening if they contain the PC

This commit is contained in:
zeromus 2008-08-13 07:41:46 +00:00
parent 077f756572
commit bec2d54b54
6 changed files with 209 additions and 156 deletions

View File

@ -1,4 +1,6 @@
---version 2.0.2 released---
13-aug-2008 - zeromus - add FORBID breakpoints - regions which block breakpoints from happening if they contain the PC
13-aug-2008 - punkrockguy318 - SDL: fixed --input(1-4) options. input1 and 2 are regular inputs, input3 and 4 are famicom expansion inputs
12-aug-2008 - zeromus - fix SDL configfile woes. configfile now goes to ~/.fceux/fceux.cfg
12-aug-2008 - zeromus - SF [ 2047986 ] palflag 1 in .fm2 files crashes fceux

View File

@ -24,15 +24,15 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
return -1;
}
if (type & PPU_BREAKPOINT)
if (type & BT_P)
{
return offset & 0x3FFF;
}
else if (type & SPRITE_BREAKPOINT)
else if (type & BT_S)
{
return offset & 0x00FF;
}
else // CPU_BREAKPOINTS
else // BT_C
{
if (GameInfo->type == GIT_NSF) { //NSF Breakpoint keywords
if (strcmp(offsetBuffer,"LOAD") == 0) return (NSFHeader.LoadAddressLow | (NSFHeader.LoadAddressHigh<<8));
@ -56,6 +56,30 @@ int offsetStringToInt(unsigned int type, const char* offsetBuffer)
return offset;
}
// Returns the value of a given type or register
int getValue(int type)
{
switch (type)
{
case 'A': return _A;
case 'X': return _X;
case 'Y': return _Y;
case 'N': return _P & N_FLAG ? 1 : 0;
case 'V': return _P & V_FLAG ? 1 : 0;
case 'U': return _P & U_FLAG ? 1 : 0;
case 'B': return _P & B_FLAG ? 1 : 0;
case 'D': return _P & D_FLAG ? 1 : 0;
case 'I': return _P & I_FLAG ? 1 : 0;
case 'Z': return _P & Z_FLAG ? 1 : 0;
case 'C': return _P & C_FLAG ? 1 : 0;
case 'P': return _PC;
}
return 0;
}
/**
* Checks whether a breakpoint condition is syntactically valid
* and creates a breakpoint condition object if everything's OK.
@ -146,14 +170,15 @@ unsigned int NewBreak(const char* name, int start, int end, unsigned int type, c
// Get the breakpoint flags
watchpoint[num].flags = 0;
if (enable) watchpoint[num].flags|=WP_E;
if (type & READ_BREAKPOINT) watchpoint[num].flags|=WP_R;
if (type & WRITE_BREAKPOINT) watchpoint[num].flags|=WP_W;
if (type & EXECUTE_BREAKPOINT) watchpoint[num].flags|=WP_X;
if (type & PPU_BREAKPOINT) {
if (type & WP_R) watchpoint[num].flags|=WP_R;
if (type & WP_F) watchpoint[num].flags|=WP_F;
if (type & WP_W) watchpoint[num].flags|=WP_W;
if (type & WP_X) watchpoint[num].flags|=WP_X;
if (type & BT_P) {
watchpoint[num].flags|=BT_P;
watchpoint[num].flags&=~WP_X; //disable execute flag!
}
if (type & SPRITE_BREAKPOINT) {
if (type & BT_S) {
watchpoint[num].flags|=BT_S;
watchpoint[num].flags&=~WP_X; //disable execute flag!
}
@ -227,6 +252,82 @@ uint8 GetPPUMem(uint8 A) {
return vnapage[(tmp>>10)&0x3][tmp&0x3FF];
}
//---------------------
// Evaluates a condition
int evaluate(Condition* c)
{
int f = 0;
int value1, value2;
if (c->lhs)
{
value1 = evaluate(c->lhs);
}
else
{
switch(c->type1)
{
case TYPE_ADDR:
case TYPE_NUM: value1 = c->value1; break;
default: value1 = getValue(c->value1);
}
}
if (c->type1 == TYPE_ADDR)
{
value1 = GetMem(value1);
}
f = value1;
if (c->op)
{
if (c->rhs)
{
value2 = evaluate(c->rhs);
}
else
{
switch(c->type2)
{
case TYPE_ADDR:
case TYPE_NUM: value2 = c->value2; break;
default: value2 = getValue(c->type2);
}
}
if (c->type2 == TYPE_ADDR)
{
value2 = GetMem(value2);
}
switch (c->op)
{
case OP_EQ: f = value1 == value2; break;
case OP_NE: f = value1 != value2; break;
case OP_GE: f = value1 >= value2; break;
case OP_LE: f = value1 <= value2; break;
case OP_G: f = value1 > value2; break;
case OP_L: f = value1 < value2; break;
case OP_MULT: f = value1 * value2; break;
case OP_DIV: f = value1 / value2; break;
case OP_PLUS: f = value1 + value2; break;
case OP_MINUS: f = value1 - value2; break;
case OP_OR: f = value1 || value2; break;
case OP_AND: f = value1 && value2; break;
}
}
return f;
}
int condition(watchpointinfo* wp)
{
return wp->cond == 0 || evaluate(wp->cond);
}
//---------------------
@ -333,7 +434,29 @@ static DebuggerState dbgstate;
DebuggerState &FCEUI_Debugger() { return dbgstate; }
void BreakHit() {
void BreakHit(bool force = false) {
if(!force) {
//check to see whether we fall in any forbid zone
for (int i = 0; i < numWPs; i++) {
watchpointinfo& wp = watchpoint[i];
if(!(wp.flags & WP_F))
continue;
if (condition(&wp))
{
if (wp.endaddress) {
if( (wp.address <= _PC) && (wp.endaddress >= _PC) )
return; //forbid
} else {
if(wp.address == _PC)
return; //forbid
}
}
}
}
FCEUI_SetEmulationPaused(1); //mbg merge 7/19/06 changed to use EmulationPaused()
//MBG TODO - was this commented out before the gnu refactoring?
@ -377,108 +500,6 @@ void BreakHit() {
}
*/
// ################################## Start of SP CODE ###########################
// Returns the value of a given type or register
int getValue(int type)
{
switch (type)
{
case 'A': return _A;
case 'X': return _X;
case 'Y': return _Y;
case 'N': return _P & N_FLAG ? 1 : 0;
case 'V': return _P & V_FLAG ? 1 : 0;
case 'U': return _P & U_FLAG ? 1 : 0;
case 'B': return _P & B_FLAG ? 1 : 0;
case 'D': return _P & D_FLAG ? 1 : 0;
case 'I': return _P & I_FLAG ? 1 : 0;
case 'Z': return _P & Z_FLAG ? 1 : 0;
case 'C': return _P & C_FLAG ? 1 : 0;
case 'P': return _PC;
}
return 0;
}
// Evaluates a condition
int evaluate(Condition* c)
{
int f = 0;
int value1, value2;
if (c->lhs)
{
value1 = evaluate(c->lhs);
}
else
{
switch(c->type1)
{
case TYPE_ADDR:
case TYPE_NUM: value1 = c->value1; break;
default: value1 = getValue(c->value1);
}
}
if (c->type1 == TYPE_ADDR)
{
value1 = GetMem(value1);
}
f = value1;
if (c->op)
{
if (c->rhs)
{
value2 = evaluate(c->rhs);
}
else
{
switch(c->type2)
{
case TYPE_ADDR:
case TYPE_NUM: value2 = c->value2; break;
default: value2 = getValue(c->type2);
}
}
if (c->type2 == TYPE_ADDR)
{
value2 = GetMem(value2);
}
switch (c->op)
{
case OP_EQ: f = value1 == value2; break;
case OP_NE: f = value1 != value2; break;
case OP_GE: f = value1 >= value2; break;
case OP_LE: f = value1 <= value2; break;
case OP_G: f = value1 > value2; break;
case OP_L: f = value1 < value2; break;
case OP_MULT: f = value1 * value2; break;
case OP_DIV: f = value1 / value2; break;
case OP_PLUS: f = value1 + value2; break;
case OP_MINUS: f = value1 - value2; break;
case OP_OR: f = value1 || value2; break;
case OP_AND: f = value1 && value2; break;
}
}
return f;
}
int condition(watchpointinfo* wp)
{
return wp->cond == 0 || evaluate(wp->cond);
}
// ################################## End of SP CODE ###########################
///fires a breakpoint
void breakpoint() {
int i;
@ -489,7 +510,7 @@ void breakpoint() {
opcode[0] = GetMem(_PC);
//if the current instruction is bad, and we are breaking on bad opcodes, then hit the breakpoint
if(dbgstate.badopbreak && (opsize[opcode[0]] == 0)) BreakHit();
if(dbgstate.badopbreak && (opsize[opcode[0]] == 0)) BreakHit(true);
//if we're stepping out, track the nest level
if (dbgstate.stepout) {
@ -507,7 +528,7 @@ void breakpoint() {
//if we're stepping, then we'll always want to break
if (dbgstate.step) {
dbgstate.step = false;
BreakHit();
BreakHit(true);
return;
}
@ -515,7 +536,7 @@ void breakpoint() {
if ((watchpoint[64].address == _PC) && (watchpoint[64].flags)) {
watchpoint[64].address = 0;
watchpoint[64].flags = 0;
BreakHit();
BreakHit(true);
return;
}

View File

@ -10,10 +10,11 @@
#define WP_W 0x02 //watchpoint, write
#define WP_R 0x04 //watchpoint, read
#define WP_X 0x08 //watchpoint, execute
#define WP_F 0x10 //watchpoint, forbid
#define BT_C 0x00 //break type, cpu mem
#define BT_P 0x10 //break type, ppu mem
#define BT_S 0x20 //break type, sprite mem
#define BT_P 0x20 //break type, ppu mem
#define BT_S 0x40 //break type, sprite mem
//opbrktype is used to grab the breakpoint type that each instruction will cause.
//WP_X is not used because ALL opcodes will have the execute bit set.
@ -46,7 +47,7 @@ typedef struct {
Condition* cond;
char* condText;
char* desc;
// ################################## End of SP CODE ###########################
} watchpointinfo;
@ -121,12 +122,12 @@ extern NSF_HEADER NSFHeader;
///retrieves the core's DebuggerState
DebuggerState &FCEUI_Debugger();
#define CPU_BREAKPOINT 1
#define PPU_BREAKPOINT 2
#define SPRITE_BREAKPOINT 4
#define READ_BREAKPOINT 8
#define WRITE_BREAKPOINT 16
#define EXECUTE_BREAKPOINT 32
//#define CPU_BREAKPOINT 1
//#define PPU_BREAKPOINT 2
//#define SPRITE_BREAKPOINT 4
//#define READ_BREAKPOINT 8
//#define WRITE_BREAKPOINT 16
//#define EXECUTE_BREAKPOINT 32
int offsetStringToInt(unsigned int type, const char* offsetBuffer);
unsigned int NewBreak(const char* name, int start, int end, unsigned int type, const char* condition, unsigned int num, bool enable);

View File

@ -75,32 +75,24 @@ unsigned int NewBreakWindows(HWND hwndDlg, unsigned int num, bool enable)
GetDlgItemText(hwndDlg, IDC_ADDBP_ADDR_END, endOffsetBuffer, sizeof(endOffsetBuffer));
if (IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MEM_CPU))
{
type |= CPU_BREAKPOINT;
}
type |= BT_C;
else if (IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MEM_PPU))
{
type |= PPU_BREAKPOINT;
}
type |= BT_P;
else
{
type |= SPRITE_BREAKPOINT;
}
type |= BT_S;
if (IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MODE_R))
{
type |= READ_BREAKPOINT;
}
type |= WP_R;
if (IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MODE_W))
{
type |= WRITE_BREAKPOINT;
}
type |= WP_W;
if (IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MODE_X))
{
type |= EXECUTE_BREAKPOINT;
}
type |= WP_X;
//this overrides all
if (IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MODE_F))
type = WP_F;
int start = offsetStringToInt(type, startOffsetBuffer);
@ -155,6 +147,24 @@ unsigned int AddBreak(HWND hwndDlg)
return 0;
}
static void UpdateDialog(HWND hwndDlg) {
BOOL forbid = IsDlgButtonChecked(hwndDlg, IDC_ADDBP_MODE_F);
BOOL enable = !forbid;
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MODE_R),enable);
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MODE_W),enable);
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MODE_X),enable);
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MEM_CPU),enable);
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MEM_PPU),enable);
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MEM_SPR),enable);
//nah.. lets leave these checked
//CheckDlgButton(hwndDlg,IDC_ADDBP_MODE_R,BST_UNCHECKED);
//CheckDlgButton(hwndDlg,IDC_ADDBP_MODE_W,BST_UNCHECKED);
//CheckDlgButton(hwndDlg,IDC_ADDBP_MODE_X,BST_UNCHECKED);
//CheckDlgButton(hwndDlg,IDC_ADDBP_MEM_CPU,BST_UNCHECKED);
//CheckDlgButton(hwndDlg,IDC_ADDBP_MEM_PPU,BST_UNCHECKED);
//CheckDlgButton(hwndDlg,IDC_ADDBP_MEM_SPR,BST_UNCHECKED);
}
BOOL CALLBACK AddbpCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char str[8]={0};
@ -175,6 +185,7 @@ BOOL CALLBACK AddbpCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
if (watchpoint[WP_edit].flags&WP_R) CheckDlgButton(hwndDlg, IDC_ADDBP_MODE_R, BST_CHECKED);
if (watchpoint[WP_edit].flags&WP_W) CheckDlgButton(hwndDlg, IDC_ADDBP_MODE_W, BST_CHECKED);
if (watchpoint[WP_edit].flags&WP_X) CheckDlgButton(hwndDlg, IDC_ADDBP_MODE_X, BST_CHECKED);
if (watchpoint[WP_edit].flags&WP_F) CheckDlgButton(hwndDlg, IDC_ADDBP_MODE_F, BST_CHECKED);
if (watchpoint[WP_edit].flags&BT_P) {
CheckDlgButton(hwndDlg, IDC_ADDBP_MEM_PPU, BST_CHECKED);
@ -185,6 +196,8 @@ BOOL CALLBACK AddbpCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
EnableWindow(GetDlgItem(hwndDlg,IDC_ADDBP_MODE_X),FALSE);
}
else CheckDlgButton(hwndDlg, IDC_ADDBP_MEM_CPU, BST_CHECKED);
UpdateDialog(hwndDlg);
// ################################## Start of SP CODE ###########################
@ -220,6 +233,11 @@ BOOL CALLBACK AddbpCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
switch(HIWORD(wParam)) {
case BN_CLICKED:
switch(LOWORD(wParam)) {
case IDC_ADDBP_MODE_F: {
UpdateDialog(hwndDlg);
break;
}
case IDOK:
if (WP_edit >= 0) {
int tmp = NewBreakWindows(hwndDlg,WP_edit,(BOOL)(watchpoint[WP_edit].flags&WP_E));
@ -562,11 +580,12 @@ char *BreakToText(unsigned int num) {
if (watchpoint[num].flags&WP_R) strcat(str,"R"); else strcat(str,"-");
if (watchpoint[num].flags&WP_W) strcat(str,"W"); else strcat(str,"-");
if (watchpoint[num].flags&WP_X) strcat(str,"X"); else strcat(str,"-");
if (watchpoint[num].flags&WP_F) strcat(str,"F"); else strcat(str,"-");
// ################################## Start of SP CODE ###########################
if (watchpoint[num].desc)
{
strcat(str, " - ");
strcat(str, " : ");
strcat(str, watchpoint[num].desc);
}
// ################################## End of SP CODE ###########################

View File

@ -924,7 +924,7 @@ BEGIN
"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,181,196,158,10
END
ADDBP DIALOGEX 66, 83, 185, 121
ADDBP DIALOGEX 66, 83, 196, 130
STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Add Breakpoint..."
FONT 8, "MS Sans Serif", 0, 0, 0x0
@ -933,19 +933,21 @@ BEGIN
CTEXT "-",65534,78,5,8,8
EDITTEXT IDC_ADDBP_ADDR_START,48,4,30,12,ES_UPPERCASE | ES_WANTRETURN
EDITTEXT IDC_ADDBP_ADDR_END,83,4,30,12,ES_UPPERCASE | ES_WANTRETURN
CONTROL "Read",IDC_ADDBP_MODE_R,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,20,35,12
CONTROL "Write",IDC_ADDBP_MODE_W,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,45,20,35,12
CONTROL "Execute",IDC_ADDBP_MODE_X,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,20,40,12
DEFPUSHBUTTON "&OK",IDOK,47,104,42,13
PUSHBUTTON "&Cancel",IDCANCEL,95,105,42,13
GROUPBOX "Memory",108,6,34,174,24,WS_TABSTOP
CONTROL "CPU Mem",IDC_ADDBP_MEM_CPU,"Button",BS_AUTORADIOBUTTON | WS_GROUP,10,44,50,10
CONTROL "PPU Mem",IDC_ADDBP_MEM_PPU,"Button",BS_AUTORADIOBUTTON,65,44,50,10
CONTROL "Sprite Mem",IDC_ADDBP_MEM_SPR,"Button",BS_AUTORADIOBUTTON,121,44,50,10
EDITTEXT IDC_ADDBP_CONDITION,43,64,136,14,ES_AUTOHSCROLL
LTEXT "Condition",65533,7,66,30,8
LTEXT "Name",65532,8,84,20,8
EDITTEXT IDC_ADDBP_NAME,43,81,136,14,ES_AUTOHSCROLL
CONTROL "Read",IDC_ADDBP_MODE_R,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,25,35,12
CONTROL "Write",IDC_ADDBP_MODE_W,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,49,25,35,12
CONTROL "Execute",IDC_ADDBP_MODE_X,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,86,25,40,12
DEFPUSHBUTTON "&OK",IDOK,99,113,42,13
PUSHBUTTON "&Cancel",IDCANCEL,147,114,42,13
GROUPBOX "Memory",108,9,39,174,24,WS_TABSTOP
CONTROL "CPU Mem",IDC_ADDBP_MEM_CPU,"Button",BS_AUTORADIOBUTTON | WS_GROUP,13,49,50,10
CONTROL "PPU Mem",IDC_ADDBP_MEM_PPU,"Button",BS_AUTORADIOBUTTON,68,49,50,10
CONTROL "Sprite Mem",IDC_ADDBP_MEM_SPR,"Button",BS_AUTORADIOBUTTON,124,49,50,10
EDITTEXT IDC_ADDBP_CONDITION,43,72,136,14,ES_AUTOHSCROLL
LTEXT "Condition",65533,7,74,30,8
LTEXT "Name",65532,8,92,20,8
EDITTEXT IDC_ADDBP_NAME,43,89,136,14,ES_AUTOHSCROLL
CONTROL "Forbid",IDC_ADDBP_MODE_F,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,145,6,40,12
GROUPBOX "",112,3,18,185,50,WS_TABSTOP
END
NTVIEW DIALOGEX 44, 38, 355, 402
@ -1403,6 +1405,12 @@ BEGIN
RIGHTMARGIN, 547
END
"ADDBP", DIALOG
BEGIN
RIGHTMARGIN, 185
BOTTOMMARGIN, 121
END
"MONITOR", DIALOG
BEGIN
LEFTMARGIN, 7

View File

@ -102,6 +102,8 @@
#define IDC_CHEAT_VAL_GT_BY 109
#define IDC_DEBUGGER_SEEK_TO 109
#define IDC_ROMPATCHER_PATCH_DATA 109
#define IDC_ADDBP_MODE_X2 109
#define IDC_ADDBP_MODE_F 109
#define IDC_CHEAT_VAL_LT_BY 110
#define MENU_SAVE_STATE 110
#define CB_ASK_EXIT 110