diff --git a/src/debug.cpp b/src/debug.cpp index 0cc3ae53..3d3b2b1b 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -17,6 +17,7 @@ int vblankScanLines = 0; //Used to calculate scanlines 240-261 (vblank) int vblankPixel = 0; //Used to calculate the pixels in vblank + int offsetStringToInt(unsigned int type, const char* offsetBuffer) { int offset = 0; @@ -458,10 +459,36 @@ int u; //deleteme int skipdebug; //deleteme int numWPs; +// for CPU cycles and Instructions counters +unsigned long int total_cycles_base = 0; +unsigned long int delta_cycles_base = 0; +bool break_on_cycles = false; +unsigned long int break_cycles_limit = 0; +unsigned long int total_instructions = 0; +unsigned long int delta_instructions = 0; +bool break_on_instructions = false; +unsigned long int break_instructions_limit = 0; + static DebuggerState dbgstate; DebuggerState &FCEUI_Debugger() { return dbgstate; } +void ResetDebugStatisticsCounters() +{ + total_cycles_base = delta_cycles_base = timestampbase + timestamp; + total_instructions = delta_instructions = 0; +} +void ResetDebugStatisticsDeltaCounters() +{ + delta_cycles_base = timestampbase + timestamp; + delta_instructions = 0; +} +void IncrementInstructionsCounters() +{ + total_instructions++; + delta_instructions++; +} + void BreakHit(int bp_num, bool force = false) { if(!force) { @@ -498,18 +525,25 @@ uint8 StackAddrBackup = X.S; uint16 StackNextIgnorePC = 0xFFFF; ///fires a breakpoint -void breakpoint() { +void breakpoint() +{ int i,j; uint16 A=0; uint8 brk_type,opcode[3] = {0}; uint8 stackop=0; uint8 stackopstartaddr,stackopendaddr; + if (break_on_cycles && (timestampbase + timestamp - total_cycles_base > break_cycles_limit)) + BreakHit(BREAK_TYPE_CYCLES_EXCEED, true); + if (break_on_instructions && (total_instructions > break_instructions_limit)) + BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED, true); + //inspect the current opcode 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(-1, true); + if(dbgstate.badopbreak && (opsize[opcode[0]] == 0)) + BreakHit(BREAK_TYPE_STEP, true); //if we're stepping out, track the nest level if (dbgstate.stepout) { @@ -527,7 +561,7 @@ void breakpoint() { //if we're stepping, then we'll always want to break if (dbgstate.step) { dbgstate.step = false; - BreakHit(-1, true); + BreakHit(BREAK_TYPE_STEP, true); return; } //if we're running for a scanline, we want to check if we've hit the cycle limit @@ -539,7 +573,7 @@ void breakpoint() { if (diff<=0) { dbgstate.runline=false; - BreakHit(-1, true); + BreakHit(BREAK_TYPE_STEP, true); return; } } @@ -547,7 +581,7 @@ void breakpoint() { if ((watchpoint[64].address == _PC) && (watchpoint[64].flags)) { watchpoint[64].address = 0; watchpoint[64].flags = 0; - BreakHit(-1, true); + BreakHit(BREAK_TYPE_STEP, true); return; } @@ -674,8 +708,14 @@ void breakpoint() { int debug_tracing; -void DebugCycle() { - +void DebugCycle() +{ + +#ifdef WIN32 + // since this function is called once for every instruction, we can use it for keeping statistics + IncrementInstructionsCounters(); +#endif + if (scanline == 240) { vblankScanLines = (PAL?int((double)timestamp / ((double)341 / (double)3.2)):timestamp / 114); //114 approximates the number of timestamps per scanline during vblank. Approx 2508. NTSC: (341 / 3.0) PAL: (341 / 3.2). Uses (3.? * cpu_cycles) / 341.0, and assumes 1 cpu cycle. @@ -691,8 +731,9 @@ void DebugCycle() { if ((_PC >= 0x3801) && (_PC <= 0x3824)) return; } - if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak) + if (numWPs || dbgstate.step || dbgstate.runline || dbgstate.stepout || watchpoint[64].flags || dbgstate.badopbreak || break_on_cycles || break_on_instructions) breakpoint(); + if(debug_loggingCD) LogCDData(); //mbg 6/30/06 - this was commented out when i got here. i dont understand it anyway @@ -704,4 +745,5 @@ void DebugCycle() { extern volatile int logging; //UGETAB: This is required to be an extern, because the info isn't set here if(logging) FCEUD_TraceInstruction(); #endif + } diff --git a/src/debug.h b/src/debug.h index 35f34a15..ee133e09 100644 --- a/src/debug.h +++ b/src/debug.h @@ -16,6 +16,10 @@ #define BT_P 0x20 //break type, ppu mem #define BT_S 0x40 //break type, sprite mem +#define BREAK_TYPE_STEP -1 +#define BREAK_TYPE_CYCLES_EXCEED -2 +#define BREAK_TYPE_INSTRUCTIONS_EXCEED -3 + //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. static const uint8 opbrktype[256] = { diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp index b84e241a..9114c695 100644 --- a/src/drivers/win/debugger.cpp +++ b/src/drivers/win/debugger.cpp @@ -54,6 +54,17 @@ extern int vblankScanLines; extern int vblankPixel; extern bool DebuggerWasUpdated; +extern unsigned long int total_cycles_base; +extern unsigned long int delta_cycles_base; +extern bool break_on_cycles; +extern unsigned long int break_cycles_limit; +extern unsigned long int total_instructions; +extern unsigned long int delta_instructions; +extern bool break_on_instructions; +extern unsigned long int break_instructions_limit; +extern void ResetDebugStatisticsCounters(); +extern void ResetDebugStatisticsDeltaCounters(); + int childwnd; extern readfunc ARead[0x10000]; @@ -529,21 +540,30 @@ bool inDebugger = false; void FCEUD_DebugBreakpoint(int bp_num) { UpdateDebugger(); - // highlight bp_num item in IDC_DEBUGGER_BP_LIST + if (bp_num >= 0) { + // highlight bp_num item in IDC_DEBUGGER_BP_LIST SendDlgItemMessage(hDebug, IDC_DEBUGGER_BP_LIST, LB_SETCURSEL, (WPARAM)bp_num, 0); EnableWindow(GetDlgItem(hDebug, IDC_DEBUGGER_BP_DEL), TRUE); EnableWindow(GetDlgItem(hDebug, IDC_DEBUGGER_BP_EDIT), TRUE); } else { + // remove any selection from IDC_DEBUGGER_BP_LIST SendDlgItemMessage(hDebug, IDC_DEBUGGER_BP_LIST, LB_SETCURSEL, (WPARAM)(-1), 0); EnableWindow(GetDlgItem(hDebug, IDC_DEBUGGER_BP_DEL), FALSE); EnableWindow(GetDlgItem(hDebug, IDC_DEBUGGER_BP_EDIT), FALSE); + // select IDC_DEBUGGER_VAL_CYCLES_COUNT or IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT if needed + if (bp_num == BREAK_TYPE_CYCLES_EXCEED) + SendMessage(GetDlgItem(hDebug, IDC_DEBUGGER_VAL_CYCLES_COUNT), EM_SETSEL, 0, -1); + else if (bp_num == BREAK_TYPE_INSTRUCTIONS_EXCEED) + SendMessage(GetDlgItem(hDebug, IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT), EM_SETSEL, 0, -1); } UpdateOtherDebuggingDialogs(); // Keeps the debugging windows updating smoothly when stepping void win_debuggerLoop(); // HACK to let user interact with the Debugger while emulator isn't updating win_debuggerLoop(); + // since we unfreezed emulation, reset delta_cycles counter + ResetDebugStatisticsDeltaCounters(); } void UpdateDebugger() @@ -555,7 +575,7 @@ void UpdateDebugger() //but if the debugger IS visible, then focus it SetActiveWindow(hDebug); - char str[256]={0},chr[8]; + char str[512] = {0}, str2[512] = {0}, chr[8]; int tmp,ret,i; Disassemble(hDebug, IDC_DEBUGGER_DISASSEMBLY, IDC_DEBUGGER_DISASSEMBLY_VSCR, X.PC); @@ -582,27 +602,60 @@ void UpdateDebugger() if (ppupixel>341) //maximum number of pixels per scanline ppupixel = 0; //Currently pixel display is borked until Run 128 lines is clicked, this keeps garbage from displaying - //If not in the 0-239 pixel range, make special cases for display + // If not in the 0-239 pixel range, make special cases for display if (scanline == 240 && vblankScanLines < (PAL?72:22)) { - if (!vblankScanLines) //Idle scanline (240) - sprintf(str, "Idle %d\t %d",scanline,vblankPixel); - else if (scanline + vblankScanLines == (PAL?311:261)) - sprintf(str, "Prerender -1 %d", vblankPixel); //Pre-render - else - sprintf(str, "Vblank %d %d", scanline+vblankScanLines,vblankPixel); //Vblank lines (241-260/310) + if (!vblankScanLines) + { + // Idle scanline (240) + sprintf(str, "%d", scanline); // was "Idle %d" + } else if (scanline + vblankScanLines == (PAL?311:261)) + { + // Pre-render + sprintf(str, "-1"); // was "Prerender -1" + } else + { + // Vblank lines (241-260/310) + sprintf(str, "%d", scanline + vblankScanLines); // was "Vblank %d" + } + sprintf(str2, "%d", vblankPixel); + } else + { + // Scanlines 0 - 239 + sprintf(str, "%d", scanline); + sprintf(str2, "%d", ppupixel); } - else - sprintf(str, "%d\t %d", scanline,ppupixel); //Scanlines 0 - 239 - SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_SLINE, str); + SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_PPUPIXEL, str2); + + // update counters + unsigned long int counter_value = timestampbase + timestamp - total_cycles_base; + if (counter_value < 0) // sanity check + { + ResetDebugStatisticsCounters(); + counter_value = 0; + } + sprintf(str, "%lu", counter_value); + SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_CYCLES_COUNT, str); + counter_value = timestampbase + timestamp - delta_cycles_base; + if (counter_value < 0) // sanity check + { + ResetDebugStatisticsCounters(); + counter_value = 0; + } + sprintf(str, "(+%lu)", counter_value); + SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_CYCLES_COUNT2, str); + sprintf(str, "%lu", total_instructions); + SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT, str); + sprintf(str, "(+%lu)", delta_instructions); + SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT2, str); tmp = X.S|0x0100; sprintf(str, "Stack $%04X", tmp); SetDlgItemText(hDebug, IDC_DEBUGGER_VAL_S, str); tmp = ((tmp+1)|0x0100)&0x01FF; sprintf(str, "%02X", GetMem(tmp)); - for (i = 1; i < 28; i++) { + for (i = 1; i < 128; i++) { tmp = ((tmp+1)|0x0100)&0x01FF; //increment and fix pointer to $0100-$01FF range if ((i%4) == 0) sprintf(chr, ",\r\n%02X", GetMem(tmp)); else sprintf(chr, ",%02X", GetMem(tmp)); @@ -788,9 +841,13 @@ BOOL CALLBACK AssemblerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar EndDialog(hwndDlg,0); break; case WM_COMMAND: - switch (HIWORD(wParam)) { + { + switch (HIWORD(wParam)) + { case BN_CLICKED: - switch (LOWORD(wParam)) { + { + switch (LOWORD(wParam)) + { case IDC_ASSEMBLER_APPLY: if (patchlen) { ptr = GetNesPRGPointer(GetNesFileAddress(iaPC)-16); @@ -867,8 +924,10 @@ BOOL CALLBACK AssemblerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPar } SetFocus(GetDlgItem(hwndDlg,IDC_ASSEMBLER_HISTORY)); //set focus to combo box after anything is pressed! break; + } } break; + } } return FALSE; } @@ -1038,15 +1097,26 @@ void LoadGameDebuggerData(HWND hwndDlg = hDebug) { BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { RECT wrect; - char str[256]={0},*ptr,dotdot[4]; + char str[256] = {0}, *ptr, dotdot[4]; int tmp,tmp2; int mouse_x,mouse_y; int ret,i; //FILE *fp; //these messages get handled at any time - switch(uMsg) { - case WM_INITDIALOG: { + switch(uMsg) + { + case WM_INITDIALOG: + { + CheckDlgButton(hwndDlg, IDC_DEBUGGER_BREAK_ON_CYCLES, break_on_cycles ? MF_CHECKED : MF_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_DEBUGGER_BREAK_ON_INSTRUCTIONS, break_on_instructions ? MF_CHECKED : MF_UNCHECKED); + sprintf(str, "%d", break_cycles_limit); + SetDlgItemText(hwndDlg, IDC_DEBUGGER_CYCLES_EXCEED, str); + sprintf(str, "%d", break_instructions_limit); + SetDlgItemText(hwndDlg, IDC_DEBUGGER_INSTRUCTIONS_EXCEED, str); + + CheckDlgButton(hwndDlg, IDC_DEBUGGER_BREAK_ON_BAD_OP, FCEUI_Debugger().badopbreak ? MF_CHECKED : MF_UNCHECKED); + CheckDlgButton(hwndDlg, DEBUGLOADDEB, debuggerSaveLoadDEBFiles ? MF_CHECKED : MF_UNCHECKED); CheckDlgButton(hwndDlg, DEBUGAUTOLOAD, debuggerAutoload ? MF_CHECKED : MF_UNCHECKED); if (DbgPosX==-32000) DbgPosX=0; //Just in case @@ -1071,15 +1141,15 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PC,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_STACK_CONTENTS,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PCSEEK,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); - SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PPU,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); - SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_SPR,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); + //SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PPU,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); + //SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_SPR,WM_SETFONT,(WPARAM)debugSystem->hFixedFont,FALSE); //text limits SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_A,EM_SETLIMITTEXT,2,0); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_X,EM_SETLIMITTEXT,2,0); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_Y,EM_SETLIMITTEXT,2,0); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PC,EM_SETLIMITTEXT,4,0); - SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_STACK_CONTENTS,EM_SETLIMITTEXT,83,0); + SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_STACK_CONTENTS,EM_SETLIMITTEXT,383,0); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PCSEEK,EM_SETLIMITTEXT,4,0); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PPU,EM_SETLIMITTEXT,4,0); SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_SPR,EM_SETLIMITTEXT,2,0); @@ -1101,7 +1171,6 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara // Enable Context Sub-Menus hDebugcontext = LoadMenu(fceu_hInstance,"DEBUGCONTEXTMENUS"); - FCEUI_Debugger().badopbreak = false; debugger_open = 1; inDebugger = true; break; @@ -1162,6 +1231,7 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara //adelikat: Buttons that don't need a rom loaded to do something, such as autoload case WM_COMMAND: + { switch(LOWORD(wParam)) { case DEBUGAUTOLOAD: @@ -1170,8 +1240,27 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case DEBUGLOADDEB: debuggerSaveLoadDEBFiles = !debuggerSaveLoadDEBFiles; break; - + case IDC_DEBUGGER_CYCLES_EXCEED: + { + if (HIWORD(wParam) == EN_CHANGE) + { + GetDlgItemText(hwndDlg, IDC_DEBUGGER_CYCLES_EXCEED, str, 16); + break_cycles_limit = strtoul(str, NULL, 10); + } + break; + } + case IDC_DEBUGGER_INSTRUCTIONS_EXCEED: + { + if (HIWORD(wParam) == EN_CHANGE) + { + GetDlgItemText(hwndDlg, IDC_DEBUGGER_INSTRUCTIONS_EXCEED, str, 16); + break_instructions_limit = strtoul(str, NULL, 10); + } + break; + } } + break; + } } //these messages only get handled when a game is loaded @@ -1283,19 +1372,24 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara } tmp--; } - if (i >= 0x8000) { + if (i >= 0x8000) + { dotdot[0] = 0; if (!(ptr = iNesShortFName())) ptr = "..."; if (strlen(ptr) > 60) strcpy(dotdot,"..."); if (GetNesFileAddress(i) == -1) sprintf(str,"CPU Address $%04X, Error retreiving ROM File Address!",i); // ################################## Start of SP CODE ########################### - else sprintf(str,"CPU Address %02X:%04X, Offset 0x%06X in file \"%.20s%s\" (NL file: %X)",getBank(i),i,GetNesFileAddress(i),ptr,dotdot,getBank(i)); + else sprintf(str,"CPU Address %02X:%04X, Offset 0x%06X in file \"%.40s%s\" (NL file: %X)",getBank(i),i,GetNesFileAddress(i),ptr,dotdot,getBank(i)); // ################################## End of SP CODE ########################### SetDlgItemText(hwndDlg,IDC_DEBUGGER_ADDR_LINE,str); + } else + { + SetDlgItemText(hwndDlg,IDC_DEBUGGER_ADDR_LINE,"..."); } - else SetDlgItemText(hwndDlg,IDC_DEBUGGER_ADDR_LINE,""); + } else + { + SetDlgItemText(hwndDlg,IDC_DEBUGGER_ADDR_LINE,"Hover the mouse over the left pane to see the ROM address of the data. Also leftclick/rightclick."); } - else SetDlgItemText(hwndDlg,IDC_DEBUGGER_ADDR_LINE,""); break; } @@ -1484,7 +1578,7 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara break; case IDC_DEBUGGER_BREAK_ON_BAD_OP: //Break on bad opcode - FCEUI_Debugger().badopbreak ^=1; + FCEUI_Debugger().badopbreak ^= 1; break; case IDC_DEBUGGER_FLAG_N: X.P^=N_FLAG; UpdateDebugger(); break; case IDC_DEBUGGER_FLAG_V: X.P^=V_FLAG; UpdateDebugger(); break; @@ -1494,6 +1588,24 @@ BOOL CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara case IDC_DEBUGGER_FLAG_I: X.P^=I_FLAG; UpdateDebugger(); break; case IDC_DEBUGGER_FLAG_Z: X.P^=Z_FLAG; UpdateDebugger(); break; case IDC_DEBUGGER_FLAG_C: X.P^=C_FLAG; UpdateDebugger(); break; + + case IDC_DEBUGGER_RESET_COUNTERS: + { + ResetDebugStatisticsCounters(); + UpdateDebugger(); + break; + } + case IDC_DEBUGGER_BREAK_ON_CYCLES: + { + break_on_cycles ^= 1; + break; + } + case IDC_DEBUGGER_BREAK_ON_INSTRUCTIONS: + { + break_on_instructions ^= 1; + break; + } + // ################################## Start of SP CODE ########################### case IDC_DEBUGGER_RELOAD_SYMS: lastBank = loadedBank = -1; loadNameFiles(); UpdateDebugger(); break; @@ -1604,7 +1716,7 @@ void updateGameDependentMenusDebugger(unsigned int enable) { if (!hDebug) return; - EnableWindow(GetDlgItem(hDebug,DEBUGLOADDEB),(enable ? 0 : 1)); + //EnableWindow(GetDlgItem(hDebug,DEBUGLOADDEB),(enable ? 0 : 1)); } void DoDebug(uint8 halt) { diff --git a/src/drivers/win/main.cpp b/src/drivers/win/main.cpp index 9e771ce2..463ecaa0 100644 --- a/src/drivers/win/main.cpp +++ b/src/drivers/win/main.cpp @@ -884,11 +884,12 @@ void win_debuggerLoop() // HACK: break when Frame Advance is pressed extern bool frameAdvanceRequested; extern int frameAdvanceDelay; - if (frameAdvanceRequested && frameAdvanceDelay==0) + if (frameAdvanceRequested) { - //FCEUI_SetEmulationPaused(0); - frameAdvanceDelay++; - break; + if (frameAdvanceDelay==0 || frameAdvanceDelay >= 10) + FCEUI_SetEmulationPaused(2); + if (frameAdvanceDelay < 10) + frameAdvanceDelay++; } } int zzz=9; diff --git a/src/drivers/win/pref.cpp b/src/drivers/win/pref.cpp index fd6f68f8..ca2d21f4 100644 --- a/src/drivers/win/pref.cpp +++ b/src/drivers/win/pref.cpp @@ -28,6 +28,11 @@ #include "debugger.h" #include "../../debug.h" +extern bool break_on_cycles; +extern unsigned long int break_cycles_limit; +extern bool break_on_instructions; +extern unsigned long int break_instructions_limit; + extern char symbDebugEnabled; /** @@ -39,6 +44,7 @@ extern char symbDebugEnabled; int storeDebuggerPreferences(FILE* f) { int i; + uint8 tmp; // Flag that says whether symbolic debugging should be enabled if (fwrite(&symbDebugEnabled, 1, 1, f) != 1) return 1; @@ -81,6 +87,26 @@ int storeDebuggerPreferences(FILE* f) if (fwrite(watchpoint[i].desc, 1, len, f) != len) return 1; } } + + // write "Break on Bad Opcode" flag + if (FCEUI_Debugger().badopbreak) + tmp = 1; + else + tmp = 0; + if (fwrite(&tmp, 1, 1, f) != 1) return 1; + // write "Break when exceed" data + if (break_on_cycles) + tmp = 1; + else + tmp = 0; + if (fwrite(&tmp, 1, 1, f) != 1) return 1; + if (fwrite(&break_cycles_limit, sizeof(break_cycles_limit), 1, f) != 1) return 1; + if (break_on_instructions) + tmp = 1; + else + tmp = 0; + if (fwrite(&tmp, 1, 1, f) != 1) return 1; + if (fwrite(&break_instructions_limit, sizeof(break_instructions_limit), 1, f) != 1) return 1; return 0; } @@ -204,6 +230,7 @@ int loadDebugDataFailed = 0; int loadDebuggerPreferences(FILE* f) { unsigned int i; + uint8 tmp; // Read flag that says if symbolic debugging is enabled if (fread(&symbDebugEnabled, sizeof(symbDebugEnabled), 1, f) != 1) return 1; @@ -294,9 +321,19 @@ int loadDebuggerPreferences(FILE* f) myNumWPs++; } - } + // Read "Break on Bad Opcode" flag + if (fread(&tmp, 1, 1, f) != 1) return 1; + FCEUI_Debugger().badopbreak = (tmp != 0); + // Read "Break when exceed" data + if (fread(&tmp, 1, 1, f) != 1) return 1; + break_on_cycles = (tmp != 0); + if (fread(&break_cycles_limit, sizeof(break_cycles_limit), 1, f) != 1) return 1; + if (fread(&tmp, 1, 1, f) != 1) return 1; + break_on_instructions = (tmp != 0); + if (fread(&break_instructions_limit, sizeof(break_instructions_limit), 1, f) != 1) return 1; + return 0; } diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 6e2c04eb..4ffe0891 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -1070,68 +1070,83 @@ BEGIN PUSHBUTTON "<",MEMW_EXPANDCOLLAPSE,1,259,11,10 END -DEBUGGER DIALOGEX 54, 74, 542, 321 +DEBUGGER DIALOGEX 54, 74, 539, 319 STYLE DS_SETFONT | DS_3DLOOK | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "6502 Debugger" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - EDITTEXT IDC_DEBUGGER_DISASSEMBLY,15,6,318,300,ES_MULTILINE | ES_READONLY | WS_HSCROLL - SCROLLBAR IDC_DEBUGGER_DISASSEMBLY_VSCR,336,6,10,300,SBS_VERT - GROUPBOX "Status Flags",401,430,151,104,38,WS_TABSTOP - CONTROL "N",IDC_DEBUGGER_FLAG_N,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,435,163,22,12 - CONTROL "V",IDC_DEBUGGER_FLAG_V,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,460,163,22,12 - CONTROL "U",IDC_DEBUGGER_FLAG_U,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,485,163,22,12 - CONTROL "B",IDC_DEBUGGER_FLAG_B,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,510,163,22,12 - CONTROL "D",IDC_DEBUGGER_FLAG_D,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,435,174,22,12 - CONTROL "I",IDC_DEBUGGER_FLAG_I,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,460,174,22,12 - CONTROL "Z",IDC_DEBUGGER_FLAG_Z,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,485,174,22,12 - CONTROL "C",IDC_DEBUGGER_FLAG_C,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,510,174,22,12 - GROUPBOX "BreakPoints",402,430,3,104,143,WS_TABSTOP - LISTBOX IDC_DEBUGGER_BP_LIST,437,16,90,91,LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL - PUSHBUTTON "Add...",IDC_DEBUGGER_BP_ADD,437,111,30,15 - PUSHBUTTON "Delete",IDC_DEBUGGER_BP_DEL,469,111,30,15,WS_DISABLED - PUSHBUTTON "Edit",IDC_DEBUGGER_BP_EDIT,501,111,26,15,WS_DISABLED - PUSHBUTTON "Run",IDC_DEBUGGER_RUN,349,7,37,14 - PUSHBUTTON "Step Into",IDC_DEBUGGER_STEP_IN,389,7,38,14 - PUSHBUTTON "Step Out",IDC_DEBUGGER_STEP_OUT,349,23,37,14 - PUSHBUTTON "Step Over",IDC_DEBUGGER_STEP_OVER,389,23,38,14 - LTEXT "A:",IDC_STATIC,349,96,10,8 - LTEXT "X:",65534,376,96,10,8 - LTEXT "Y:",65533,404,96,10,8 - LTEXT "PC:",65532,349,78,13,8 - EDITTEXT IDC_DEBUGGER_VAL_A,357,94,15,12,ES_UPPERCASE | ES_WANTRETURN - EDITTEXT IDC_DEBUGGER_VAL_X,385,94,15,12,ES_UPPERCASE | ES_WANTRETURN - EDITTEXT IDC_DEBUGGER_VAL_Y,412,94,15,12,ES_UPPERCASE | ES_WANTRETURN - EDITTEXT IDC_DEBUGGER_VAL_PC,361,76,25,12,ES_UPPERCASE | ES_WANTRETURN - GROUPBOX "Stack",IDC_DEBUGGER_VAL_S,349,112,79,78,WS_TABSTOP - EDITTEXT IDC_DEBUGGER_STACK_CONTENTS,354,123,69,62,ES_MULTILINE | ES_UPPERCASE | ES_READONLY - PUSHBUTTON "Seek PC",IDC_DEBUGGER_SEEK_PC,389,75,38,14 - PUSHBUTTON "Seek To:",IDC_DEBUGGER_SEEK_TO,349,56,37,14 - EDITTEXT IDC_DEBUGGER_VAL_PCSEEK,389,57,38,12,ES_UPPERCASE | ES_WANTRETURN - LTEXT "PPU:",65531,349,196,19,10 - LTEXT "Sprite:",65530,394,196,21,10 - EDITTEXT IDC_DEBUGGER_VAL_PPU,367,195,25,12,ES_UPPERCASE | ES_WANTRETURN - EDITTEXT IDC_DEBUGGER_VAL_SPR,415,195,15,12,ES_UPPERCASE | ES_WANTRETURN - LTEXT "",IDC_DEBUGGER_VAL_SLINE,436,202,102,10 - CONTROL "",IDC_DEBUGGER_ADDR_LINE,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,5,307,328,10 + EDITTEXT IDC_DEBUGGER_DISASSEMBLY,15,5,318,299,ES_MULTILINE | ES_NOHIDESEL | ES_READONLY | WS_HSCROLL + SCROLLBAR IDC_DEBUGGER_DISASSEMBLY_VSCR,334,5,11,299,SBS_VERT + GROUPBOX "Status Flags",401,433,139,99,35,WS_TABSTOP + CONTROL "N",IDC_DEBUGGER_FLAG_N,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,439,148,18,12 + CONTROL "V",IDC_DEBUGGER_FLAG_V,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,463,148,18,12 + CONTROL "U",IDC_DEBUGGER_FLAG_U,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,486,148,18,12 + CONTROL "B",IDC_DEBUGGER_FLAG_B,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,509,148,18,12 + CONTROL "D",IDC_DEBUGGER_FLAG_D,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,439,160,18,12 + CONTROL "I",IDC_DEBUGGER_FLAG_I,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,463,160,18,12 + CONTROL "Z",IDC_DEBUGGER_FLAG_Z,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,486,160,18,12 + CONTROL "C",IDC_DEBUGGER_FLAG_C,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,509,160,18,12 + GROUPBOX "BreakPoints",402,433,3,100,135,WS_TABSTOP + LISTBOX IDC_DEBUGGER_BP_LIST,437,13,92,91,LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL + PUSHBUTTON "Add",IDC_DEBUGGER_BP_ADD,437,107,30,15 + PUSHBUTTON "Delete",IDC_DEBUGGER_BP_DEL,469,107,29,15,WS_DISABLED + PUSHBUTTON "Edit",IDC_DEBUGGER_BP_EDIT,500,107,29,15,WS_DISABLED + PUSHBUTTON "Run",IDC_DEBUGGER_RUN,350,5,38,14 + PUSHBUTTON "Step Into",IDC_DEBUGGER_STEP_IN,391,5,39,14 + PUSHBUTTON "Step Out",IDC_DEBUGGER_STEP_OUT,350,21,38,14 + PUSHBUTTON "Step Over",IDC_DEBUGGER_STEP_OVER,391,21,39,14 + LTEXT "A:",IDC_STATIC,350,92,10,8 + LTEXT "X:",65534,377,92,10,8 + LTEXT "Y:",65533,405,92,10,8 + LTEXT "PC:",65532,350,74,13,8 + EDITTEXT IDC_DEBUGGER_VAL_A,358,90,15,12,ES_UPPERCASE | ES_WANTRETURN + EDITTEXT IDC_DEBUGGER_VAL_X,386,90,15,12,ES_UPPERCASE | ES_WANTRETURN + EDITTEXT IDC_DEBUGGER_VAL_Y,414,90,15,12,ES_UPPERCASE | ES_WANTRETURN + EDITTEXT IDC_DEBUGGER_VAL_PC,362,72,25,12,ES_UPPERCASE | ES_WANTRETURN + GROUPBOX "Stack",IDC_DEBUGGER_VAL_S,349,104,80,71,WS_TABSTOP + EDITTEXT IDC_DEBUGGER_STACK_CONTENTS,353,113,72,58,ES_MULTILINE | ES_UPPERCASE | ES_NOHIDESEL | ES_READONLY | WS_VSCROLL + PUSHBUTTON "Seek PC",IDC_DEBUGGER_SEEK_PC,391,71,39,14 + PUSHBUTTON "Seek To:",IDC_DEBUGGER_SEEK_TO,350,54,38,14 + EDITTEXT IDC_DEBUGGER_VAL_PCSEEK,391,55,38,12,ES_UPPERCASE | ES_WANTRETURN + GROUPBOX "",IDC_DEBUGGER_VAL_S2,349,174,50,53,WS_TABSTOP + EDITTEXT IDC_DEBUGGER_VAL_SLINE,383,203,14,11,ES_UPPERCASE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + EDITTEXT IDC_DEBUGGER_VAL_PPUPIXEL,372,216,14,11,ES_UPPERCASE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + EDITTEXT IDC_DEBUGGER_VAL_CYCLES_COUNT,442,178,46,11,ES_UPPERCASE | ES_NOHIDESEL | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + EDITTEXT IDC_DEBUGGER_VAL_CYCLES_COUNT2,488,178,51,11,ES_UPPERCASE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + EDITTEXT IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT,441,204,46,11,ES_UPPERCASE | ES_NOHIDESEL | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + EDITTEXT IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT2,488,204,51,11,ES_UPPERCASE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + LTEXT "PPU:",65531,352,179,17,10 + LTEXT "Sprite:",65530,352,191,20,10 + EDITTEXT IDC_DEBUGGER_VAL_PPU,371,179,25,12,ES_UPPERCASE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + EDITTEXT IDC_DEBUGGER_VAL_SPR,374,191,15,12,ES_UPPERCASE | ES_READONLY | ES_WANTRETURN | NOT WS_BORDER,WS_EX_TRANSPARENT + CONTROL "",IDC_DEBUGGER_ADDR_LINE,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,4,306,341,10 CONTROL "Break on Bad Opcode",IDC_DEBUGGER_BREAK_ON_BAD_OP, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,437,132,90,10 - CONTROL "Symbolic debugging",IDC_DEBUGGER_ENABLE_SYMBOLIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,347,215,79,10 - PUSHBUTTON "Reload Symbols",IDC_DEBUGGER_RELOAD_SYMS,427,215,55,14 - GROUPBOX "Bookmarks",45535,348,227,119,80 - LISTBOX LIST_DEBUGGER_BOOKMARKS,351,236,67,66,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - EDITTEXT IDC_DEBUGGER_BOOKMARK,421,236,40,14,ES_AUTOHSCROLL - PUSHBUTTON "Add",IDC_DEBUGGER_BOOKMARK_ADD,421,252,40,14 - PUSHBUTTON "Delete",IDC_DEBUGGER_BOOKMARK_DEL,421,268,40,14 - PUSHBUTTON "Rom Patcher",IDC_DEBUGGER_ROM_PATCHER,487,215,46,14 - CONTROL "",IDC_DEBUGGER_ICONTRAY,"Static",SS_BLACKFRAME,5,6,10,301 - PUSHBUTTON "",IDC_DEBUGGER_RESTORESIZE,348,308,9,7 - LTEXT "Restore original window size",IDC_STATIC,359,308,90,8 - PUSHBUTTON "Run Line",IDC_DEBUGGER_RUN_LINE,349,39,37,14 - PUSHBUTTON "128 Lines",IDC_DEBUGGER_RUN_FRAME2,389,39,37,14 - LTEXT "Scanline: PPU Pixel:",IDC_STATIC,436,191,78,8 - CONTROL "Load .DEB",DEBUGLOADDEB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,495,297,46,10 - CONTROL "Auto-load",DEBUGAUTOLOAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,495,308,46,10 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,438,125,90,10 + CONTROL "Symbolic debugging",IDC_DEBUGGER_ENABLE_SYMBOLIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,448,260,77,10 + PUSHBUTTON "Reload Symbols",IDC_DEBUGGER_RELOAD_SYMS,447,272,62,14 + GROUPBOX "Address Bookmarks",45535,349,227,94,75 + LISTBOX LIST_DEBUGGER_BOOKMARKS,353,236,50,62,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_DEBUGGER_BOOKMARK,407,236,32,14,ES_AUTOHSCROLL + PUSHBUTTON "Add",IDC_DEBUGGER_BOOKMARK_ADD,406,252,34,14 + PUSHBUTTON "Delete",IDC_DEBUGGER_BOOKMARK_DEL,406,268,34,14 + PUSHBUTTON "Rom Patcher",IDC_DEBUGGER_ROM_PATCHER,447,288,62,14 + CONTROL "",IDC_DEBUGGER_ICONTRAY,"Static",SS_BLACKFRAME,4,5,11,299 + PUSHBUTTON "-",IDC_DEBUGGER_RESTORESIZE,349,305,13,9 + LTEXT "Default window size",IDC_STATIC,364,306,68,9 + PUSHBUTTON "Run Line",IDC_DEBUGGER_RUN_LINE,350,37,38,14 + PUSHBUTTON "128 Lines",IDC_DEBUGGER_RUN_FRAME2,391,37,39,14 + LTEXT "Scanline:",IDC_STATIC,352,203,31,8 + CONTROL "Load .DEB",DEBUGLOADDEB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,488,305,48,10 + CONTROL "Auto-open",DEBUGAUTOLOAD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,438,305,46,10 + LTEXT "CPU cycles:",IDC_STATIC,402,178,39,8 + PUSHBUTTON "Reset counters",IDC_DEBUGGER_RESET_COUNTERS,447,230,62,14 + CONTROL "Break when exceed",IDC_DEBUGGER_BREAK_ON_CYCLES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,405,190,77,10 + LTEXT "Pixel:",IDC_STATIC,352,216,17,8 + EDITTEXT IDC_DEBUGGER_CYCLES_EXCEED,483,189,50,12,ES_UPPERCASE | ES_NOHIDESEL | ES_WANTRETURN | ES_NUMBER + LTEXT "Instructions:",IDC_STATIC,402,204,40,8 + CONTROL "Break when exceed",IDC_DEBUGGER_BREAK_ON_INSTRUCTIONS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,405,217,77,10 + EDITTEXT IDC_DEBUGGER_INSTRUCTIONS_EXCEED,483,216,50,12,ES_UPPERCASE | ES_NOHIDESEL | ES_WANTRETURN | ES_NUMBER END TRACER DIALOGEX 65527, 65513, 423, 319 @@ -1950,8 +1965,6 @@ BEGIN "DEBUGGER", DIALOG BEGIN - RIGHTMARGIN, 541 - BOTTOMMARGIN, 318 END "ADDBP", DIALOG diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 1cb65d25..ca08ab9e 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -134,9 +134,15 @@ #define IDC_DEBUGGER_RUN_FRAME2 115 #define LBL_CLEAR_AH 116 #define IDC_CHECK_LOG_UPDATE_WINDOW 116 +#define IDC_DEBUGGER_RESET_CYCLES_COUNTER 116 +#define IDC_DEBUGGER_RESET_COUNTERS 116 #define CHEAT_CONTEXT_TOGGLECHEAT 117 +#define IDC_DEBUGGER_RESET_ON_STEP 117 +#define IDC_DEBUGGER_BREAK_ON_CYCLES 117 #define CHEAT_CONTEXT_POKECHEATVALUE 118 +#define IDC_DEBUGGER_RESET_ON_BP0 118 #define CHEAT_CONTEXT_GOTOINHEXEDITOR 119 +#define IDC_DEBUGGER_BREAK_ON_INSTRUCTIONS 119 #define CHECK_SOUND_8BIT 122 #define IDD_DIALOG3 123 #define CHECK_SOUND_GLOBAL_FOCUS 124 @@ -376,6 +382,8 @@ #define IDC_DEBUGGER_VAL_SPR 311 #define IDC_LABEL_TWEAKCOUNT 311 #define IDC_DEBUGGER_BOOKMARK 312 +#define IDC_DEBUGGER_CYCLES_EXCEED 313 +#define IDC_DEBUGGER_INSTRUCTIONS_EXCEED 314 #define MENU_DIRECTORIES 320 #define MENU_INPUT 321 #define MENU_GUI_OPTIONS 327 @@ -392,6 +400,7 @@ #define IDC_DEBUGGER_VAL_S 403 #define IDC_VIDEOCONFIG_ASPECT_X 404 #define IDC_VIDEOCONFIG_ASPECT_Y 405 +#define IDC_DEBUGGER_VAL_S2 405 #define IDC_VIDEOCONFIG_SCALER_WIN 406 #define CHECK_ENABLE_MICROPHONE 407 #define CTL_TINT_TRACKBAR 500 @@ -406,9 +415,15 @@ #define CTL_VOLUME_TRACKBAR_SQUARE1 502 #define IDC_SCANLINE_LAST_PAL 503 #define CTL_VOLUME_TRACKBAR_SQUARE2 503 +#define IDC_DEBUGGER_VAL_CYCLES_COUNT 503 #define CTL_VOLUME_TRACKBAR_NOISE 504 +#define IDC_DEBUGGER_VAL_PPUPIXEL 504 #define CTL_VOLUME_TRACKBAR_NOISE2 505 #define CTL_VOLUME_TRACKBAR_PCM 505 +#define IDC_DEBUGGER_VAL_CYCLES_COUNT2 505 +#define IDC_DEBUGGER_VAL_CYCLES_COUNT3 506 +#define IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT 506 +#define IDC_DEBUGGER_VAL_INSTRUCTIONS_COUNT2 507 #define IDC_VIDEOCONFIG_NO8LIM 600 #define IDC_DEBUGGER_ROM_PATCHER 602 #define LIST_DEBUGGER_BOOKMARKS 701 diff --git a/src/drivers/win/taseditor/taseditor_window.cpp b/src/drivers/win/taseditor/taseditor_window.cpp index 1caf7632..d7ad7f8f 100644 --- a/src/drivers/win/taseditor/taseditor_window.cpp +++ b/src/drivers/win/taseditor/taseditor_window.cpp @@ -1177,9 +1177,9 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara break; case ACCEL_CTRL_A: if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_UPPER) - SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1); + SendMessage(playback.hwndPlaybackMarkerEdit, EM_SETSEL, 0, -1); else if (markers_manager.marker_note_edit == MARKER_NOTE_EDIT_LOWER) - SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1); + SendMessage(selection.hwndSelectionMarkerEdit, EM_SETSEL, 0, -1); else if (piano_roll.drag_mode != DRAG_MODE_SELECTION) selection.SelectBetweenMarkers(); break; diff --git a/src/fceu.cpp b/src/fceu.cpp index 318b92c0..e4242bbf 100644 --- a/src/fceu.cpp +++ b/src/fceu.cpp @@ -53,6 +53,8 @@ #ifdef WIN32 #include "drivers/win/pref.h" +extern void ResetDebugStatisticsCounters(); + extern bool TaseditorIsRecording(); #endif @@ -802,12 +804,11 @@ void PowerNES(void) if(disableBatteryLoading) GameInterface(GI_RESETSAVE); - - timestampbase=0; - LagCounterReset(); - + timestampbase = 0; X6502_Power(); + ResetDebugStatisticsCounters(); FCEU_PowerCheats(); + LagCounterReset(); // clear back baffer extern uint8 *XBackBuf; memset(XBackBuf,0,256*256); @@ -815,6 +816,7 @@ void PowerNES(void) #ifdef WIN32 Update_RAM_Search(); // Update_RAM_Watch() is also called. #endif + FCEU_DispMessage("Power on", 0); }