DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 #include "dosbox.h" 00021 #if C_DEBUG 00022 00023 #include <string.h> 00024 #include <list> 00025 #include <vector> 00026 #include <ctype.h> 00027 #include <fstream> 00028 #include <iomanip> 00029 #include <string> 00030 #include <sstream> 00031 using namespace std; 00032 00033 #include "debug.h" 00034 #include "cross.h" //snprintf 00035 #include "cpu.h" 00036 #include "fpu.h" 00037 #include "video.h" 00038 #include "pic.h" 00039 #include "vga.h" 00040 #include "mapper.h" 00041 #include "cpu.h" 00042 #include "pc98_gdc.h" 00043 #include "callback.h" 00044 #include "inout.h" 00045 #include "mixer.h" 00046 #include "timer.h" 00047 #include "paging.h" 00048 #include "support.h" 00049 #include "shell.h" 00050 #include "programs.h" 00051 #include "debug_inc.h" 00052 #include "../cpu/lazyflags.h" 00053 #include "keyboard.h" 00054 #include "setup.h" 00055 00056 #ifdef WIN32 00057 void WIN32_Console(); 00058 #else 00059 #include <termios.h> 00060 #include <unistd.h> 00061 static struct termios consolesettings; 00062 #endif 00063 int old_cursor_state; 00064 00065 const char *egc_fgc_modes[4] = { 00066 "pattern", 00067 "background", 00068 "foreground", 00069 "(invalid)", 00070 }; 00071 00072 bool pc98_pegc_linear_framebuffer_enabled(void); 00073 void GFX_SetTitle(Bit32s cycles,Bits frameskip,Bits timing,bool paused); 00074 00075 extern bool dos_kernel_disabled; 00076 extern bool is_paused; 00077 extern bool pc98_crt_mode; 00078 extern uint8_t GDC_display_plane; 00079 extern uint8_t GDC_display_plane_pending; 00080 extern bool pc98_256kb_boundary; 00081 extern bool gdc_5mhz_mode; 00082 extern bool enable_pc98_egc; 00083 extern bool enable_pc98_grcg; 00084 extern bool enable_pc98_16color; 00085 extern bool enable_pc98_256color; 00086 extern bool enable_pc98_256color_planar; 00087 extern bool enable_pc98_188usermod; 00088 extern bool GDC_vsync_interrupt; 00089 extern bool pc98_graphics_hide_odd_raster_200line; 00090 extern bool pc98_attr4_graphic; 00091 extern bool egc_enable_enable; 00092 extern uint8_t pc98_gdc_tile_counter; 00093 extern uint8_t pc98_gdc_modereg; 00094 extern egc_quad pc98_gdc_tiles; 00095 00096 extern uint16_t pc98_egc_raw_values[8]; 00097 00098 extern uint16_t a1_font_load_addr; 00099 extern uint8_t a1_font_char_offset; 00100 00101 extern egc_quad pc98_egc_bgcm; 00102 extern egc_quad pc98_egc_fgcm; 00103 00104 extern uint8_t pc98_egc_access; 00105 extern uint8_t pc98_egc_srcmask[2]; /* host given (Neko: egc.srcmask) */ 00106 extern uint8_t pc98_egc_maskef[2]; /* effective (Neko: egc.mask2) */ 00107 extern uint8_t pc98_egc_mask[2]; /* host given (Neko: egc.mask) */ 00108 00109 extern uint8_t pc98_egc_fgc; 00110 extern uint8_t pc98_egc_lead_plane; 00111 extern uint8_t pc98_egc_compare_lead; 00112 extern uint8_t pc98_egc_lightsource; 00113 extern uint8_t pc98_egc_shiftinput; 00114 extern uint8_t pc98_egc_regload; 00115 extern uint8_t pc98_egc_rop; 00116 extern uint8_t pc98_egc_foreground_color; 00117 extern uint8_t pc98_egc_background_color; 00118 00119 extern bool pc98_egc_shift_descend; 00120 extern uint8_t pc98_egc_shift_destbit; 00121 extern uint8_t pc98_egc_shift_srcbit; 00122 extern uint16_t pc98_egc_shift_length; 00123 00124 extern unsigned char pc98_text_first_row_scanline_start; /* port 70h */ 00125 extern unsigned char pc98_text_first_row_scanline_end; /* port 72h */ 00126 extern unsigned char pc98_text_row_scanline_blank_at; /* port 74h */ 00127 extern unsigned char pc98_text_row_scroll_lines; /* port 76h */ 00128 extern unsigned char pc98_text_row_scroll_count_start; /* port 78h */ 00129 extern unsigned char pc98_text_row_scroll_num_lines; /* port 7Ah */ 00130 00131 extern bool logBuffSuppressConsole; 00132 extern bool logBuffSuppressConsoleNeedUpdate; 00133 00134 // Forwards 00135 static void DrawCode(void); 00136 static void DrawInput(void); 00137 static void DEBUG_RaiseTimerIrq(void); 00138 static void SaveMemory(Bit16u seg, Bit32u ofs1, Bit32u num); 00139 static void SaveMemoryBin(Bit16u seg, Bit32u ofs1, Bit32u num); 00140 static void LogMCBS(void); 00141 static void LogGDT(void); 00142 static void LogLDT(void); 00143 static void LogIDT(void); 00144 static void LogXMS(void); 00145 static void LogEMS(void); 00146 static void LogFNKEY(void); 00147 static void LogPages(char* selname); 00148 static void LogCPUInfo(void); 00149 static void OutputVecTable(char* filename); 00150 static void DrawVariables(void); 00151 static void LogDOSKernMem(void); 00152 static void LogBIOSMem(void); 00153 00154 bool inhibit_int_breakpoint=false; 00155 00156 void DEBUG_DrawInput(void) { 00157 DrawInput(); 00158 } 00159 00160 void DEBUG_BeginPagedContent(void); 00161 void DEBUG_EndPagedContent(void); 00162 Bitu MEM_PageMaskActive(void); 00163 Bit32u MEM_get_address_bits(); 00164 Bitu MEM_TotalPages(void); 00165 Bitu MEM_PageMask(void); 00166 00167 static void LogEMUMachine(void) { 00168 DEBUG_BeginPagedContent(); 00169 00170 DEBUG_ShowMsg("Emulator machine:"); 00171 00172 { 00173 const char *m = "?"; 00174 const char *cardName = ""; 00175 00176 switch (machine) { 00177 case MCH_HERC: m="Hercules"; break; 00178 case MCH_CGA: m="CGA"; break; 00179 case MCH_TANDY: m="Tandy"; break; 00180 case MCH_PCJR: m="PCjr"; break; 00181 case MCH_EGA: m="EGA"; break; 00182 case MCH_VGA: m="VGA"; break; 00183 case MCH_AMSTRAD: m="Amstrad"; break; 00184 case MCH_PC98: m="PC-98"; break; 00185 case MCH_FM_TOWNS: m="FM Towns"; break; 00186 case MCH_MCGA: m="MCGA"; break; 00187 case MCH_MDA: m="MDA"; break; 00188 default: break; 00189 } 00190 00191 switch (svgaCard) { 00192 case SVGA_None: cardName =""; break; 00193 case SVGA_S3Trio: cardName ="S3 Trio"; break; 00194 case SVGA_TsengET4K: cardName ="Tseng ET4000"; break; 00195 case SVGA_TsengET3K: cardName ="Tseng ET3000"; break; 00196 case SVGA_ParadisePVGA1A: cardName ="Paradise PVGA1A"; break; 00197 } 00198 00199 DEBUG_ShowMsg("Machine: %s %s",m, cardName); 00200 } 00201 00202 DEBUG_EndPagedContent(); 00203 } 00204 00205 static void LogEMUMem(void) { 00206 DEBUG_BeginPagedContent(); 00207 00208 DEBUG_ShowMsg("Emulator memory:"); 00209 DEBUG_ShowMsg("A20 gate: %s",MEM_A20_Enabled() ? "ON" : "OFF"); 00210 DEBUG_ShowMsg("CPU address bits: %u",(unsigned int)MEM_get_address_bits()); 00211 DEBUG_ShowMsg("CPU address mask: 0x%lx",((unsigned long)MEM_PageMask() << 12UL) | 0xFFFUL); 00212 DEBUG_ShowMsg("CPU address mask current: 0x%lx",((unsigned long)MEM_PageMaskActive() << 12UL) | 0xFFFUL); 00213 DEBUG_ShowMsg("Memory reported size: %lu bytes",(unsigned long)MEM_TotalPages() << 12UL); 00214 00215 DEBUG_EndPagedContent(); 00216 } 00217 00218 bool XMS_Active(void); 00219 00220 Bitu XMS_GetTotalHandles(void); 00221 bool XMS_GetHandleInfo(Bitu &phys_location,Bitu &size,Bitu &lockcount,bool &free,Bitu handle); 00222 00223 LoopHandler *old_loop = NULL; 00224 00225 char* AnalyzeInstruction(char* inst, bool saveSelector); 00226 Bit32u GetHexValue(char* const str, char* &hex,bool *parsed=NULL); 00227 void SkipSpace(char*& hex); 00228 00229 #if 0 00230 class DebugPageHandler : public PageHandler { 00231 public: 00232 Bit8u readb(PhysPt /*addr*/) { 00233 } 00234 Bit16u readw(PhysPt /*addr*/) { 00235 } 00236 Bit32u readd(PhysPt /*addr*/) { 00237 } 00238 void writeb(PhysPt /*addr*/,Bit8u /*val*/) { 00239 } 00240 void writew(PhysPt /*addr*/,Bit16u /*val*/) { 00241 } 00242 void writed(PhysPt /*addr*/,Bit32u /*val*/) { 00243 } 00244 }; 00245 #endif 00246 00247 00248 class DEBUG; 00249 00250 //DEBUG* pDebugcom = 0; 00251 bool exitLoop = false; 00252 00253 00254 // Heavy Debugging Vars for logging 00255 #if C_HEAVY_DEBUG 00256 static ofstream cpuLogFile; 00257 static bool cpuLog = false; 00258 static int cpuLogCounter = 0; 00259 static int cpuLogType = 1; // log detail 00260 static bool zeroProtect = false; 00261 bool logHeavy = false; 00262 #endif 00263 00264 00265 00266 static struct { 00267 Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip; 00268 } oldregs; 00269 00270 static char curSelectorName[3] = { 0,0,0 }; 00271 00272 static Segment oldsegs[6]; 00273 static Bitu oldflags,oldcpucpl; 00274 DBGBlock dbg; 00275 extern Bitu cycle_count; 00276 static bool debugging = false; 00277 static bool debug_running = false; 00278 static bool check_rescroll = false; 00279 00280 bool IsDebuggerActive(void) { 00281 return debugging; 00282 } 00283 00284 bool IsDebuggerRunwatch(void) { 00285 return debug_running; 00286 } 00287 00288 static void SetColor(Bitu test) { 00289 if (test) { 00290 if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));} 00291 } else { 00292 if (has_colors()) { wattrset(dbg.win_reg,0);} 00293 } 00294 } 00295 00296 #define MAXCMDLEN 254 00297 struct SCodeViewData { 00298 int cursorPos; 00299 Bit16u firstInstSize; 00300 Bit16u useCS; 00301 Bit32u useEIPlast, useEIPmid; 00302 Bit32u useEIP; 00303 Bit16u cursorSeg; 00304 Bit32u cursorOfs; 00305 bool ovrMode; 00306 char inputStr[MAXCMDLEN+1]; 00307 char suspInputStr[MAXCMDLEN+1]; 00308 int inputPos; 00309 } codeViewData; 00310 00311 static Bit16u dataSeg; 00312 static Bit32u dataOfs; 00313 static bool showExtend = true; 00314 00315 static void ClearInputLine(void) { 00316 codeViewData.inputStr[0] = 0; 00317 codeViewData.inputPos = 0; 00318 } 00319 00320 // History stuff 00321 #define MAX_HIST_BUFFER 50 00322 static list<string> histBuff; 00323 static list<string>::iterator histBuffPos = histBuff.end(); 00324 00325 /***********/ 00326 /* Helpers */ 00327 /***********/ 00328 00329 static const Bit64u mem_no_address = (Bit64u)(~0ULL); 00330 00331 Bit64u LinMakeProt(Bit16u selector, Bit32u offset) 00332 { 00333 Descriptor desc; 00334 00335 if (cpu.gdt.GetDescriptor(selector,desc)) { 00336 if (selector >= 8 && desc.Type() != 0) { 00337 if (offset <= desc.GetLimit()) 00338 return desc.GetBase()+(Bit64u)offset; 00339 } 00340 } 00341 00342 return mem_no_address; 00343 } 00344 00345 Bit64u GetAddress(Bit16u seg, Bit32u offset) 00346 { 00347 if (cpu.pmode && !(reg_flags & FLAG_VM)) 00348 return LinMakeProt(seg,offset); 00349 00350 if (seg==SegValue(cs)) return SegPhys(cs)+(Bit64u)offset; 00351 return ((Bit64u)seg<<4u)+offset; 00352 } 00353 00354 static char empty_sel[] = { ' ',' ',0 }; 00355 00356 bool GetDescriptorInfo(char* selname, char* out1, char* out2) 00357 { 00358 Bitu sel; 00359 Descriptor desc; 00360 00361 if (strstr(selname,"cs") || strstr(selname,"CS")) sel = SegValue(cs); 00362 else if (strstr(selname,"ds") || strstr(selname,"DS")) sel = SegValue(ds); 00363 else if (strstr(selname,"es") || strstr(selname,"ES")) sel = SegValue(es); 00364 else if (strstr(selname,"fs") || strstr(selname,"FS")) sel = SegValue(fs); 00365 else if (strstr(selname,"gs") || strstr(selname,"GS")) sel = SegValue(gs); 00366 else if (strstr(selname,"ss") || strstr(selname,"SS")) sel = SegValue(ss); 00367 else { 00368 sel = GetHexValue(selname,selname); 00369 if (*selname==0) selname=empty_sel; 00370 } 00371 if (cpu.gdt.GetDescriptor(sel,desc)) { 00372 switch (desc.Type()) { 00373 case DESC_TASK_GATE: 00374 sprintf(out1,"%s: s:%08lX type:%02X p",selname,(unsigned long)desc.GetSelector(),(int)desc.saved.gate.type); 00375 sprintf(out2," TaskGate dpl : %01X %1X",desc.saved.gate.dpl,desc.saved.gate.p); 00376 return true; 00377 case DESC_LDT: 00378 case DESC_286_TSS_A: 00379 case DESC_286_TSS_B: 00380 case DESC_386_TSS_A: 00381 case DESC_386_TSS_B: 00382 sprintf(out1,"%s: b:%08lX type:%02X pag",selname,(unsigned long)desc.GetBase(),(int)desc.saved.seg.type); 00383 sprintf(out2," l:%08lX dpl : %01X %1X%1X%1X",(unsigned long)desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.g); 00384 return true; 00385 case DESC_286_CALL_GATE: 00386 case DESC_386_CALL_GATE: 00387 sprintf(out1,"%s: s:%08lX type:%02X p params: %02X",selname,(unsigned long)desc.GetSelector(),desc.saved.gate.type,desc.saved.gate.paramcount); 00388 sprintf(out2," o:%08lX dpl : %01X %1X",(unsigned long)desc.GetOffset(),desc.saved.gate.dpl,desc.saved.gate.p); 00389 return true; 00390 case DESC_286_INT_GATE: 00391 case DESC_286_TRAP_GATE: 00392 case DESC_386_INT_GATE: 00393 case DESC_386_TRAP_GATE: 00394 sprintf(out1,"%s: s:%08lX type:%02X p",selname,(unsigned long)desc.GetSelector(),desc.saved.gate.type); 00395 sprintf(out2," o:%08lX dpl : %01X %1X",(unsigned long)desc.GetOffset(),desc.saved.gate.dpl,desc.saved.gate.p); 00396 return true; 00397 } 00398 sprintf(out1,"%s: b:%08lX type:%02X parbg",selname,(unsigned long)desc.GetBase(),desc.saved.seg.type); 00399 sprintf(out2," l:%08lX dpl : %01X %1X%1X%1X%1X%1X",(unsigned long)desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.r,desc.saved.seg.big,desc.saved.seg.g); 00400 return true; 00401 } else { 00402 strcpy(out1," "); 00403 strcpy(out2," "); 00404 } 00405 return false; 00406 } 00407 00408 /********************/ 00409 /* DebugVar stuff */ 00410 /********************/ 00411 00412 class CDebugVar 00413 { 00414 public: 00415 CDebugVar(char* _name, PhysPt _adr) { adr=_adr; safe_strncpy(name,_name,16); hasvalue = false; value = 0; }; 00416 00417 char* GetName (void) { return name; }; 00418 PhysPt GetAdr (void) { return adr; }; 00419 void SetValue(bool has, Bit16u val) { hasvalue = has; value=val; }; 00420 Bit16u GetValue(void) { return value; }; 00421 bool HasValue(void) { return hasvalue; }; 00422 00423 private: 00424 PhysPt adr; 00425 char name[16]; 00426 bool hasvalue; 00427 Bit16u value; 00428 00429 public: 00430 static void InsertVariable(char* name, PhysPt adr); 00431 static CDebugVar* FindVar (PhysPt pt); 00432 static void DeleteAll (); 00433 static bool SaveVars (char* name); 00434 static bool LoadVars (char* name); 00435 00436 static std::vector<CDebugVar*> varList; 00437 }; 00438 00439 std::vector<CDebugVar*> CDebugVar::varList; 00440 00441 00442 /********************/ 00443 /* Breakpoint stuff */ 00444 /********************/ 00445 00446 bool mustCompleteInstruction = false; 00447 bool skipFirstInstruction = false; 00448 00449 enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT, BKPNT_MEMORY, BKPNT_MEMORY_PROT, BKPNT_MEMORY_LINEAR }; 00450 00451 #define BPINT_ALL 0x100 00452 00453 class CBreakpoint 00454 { 00455 public: 00456 00457 CBreakpoint(void); 00458 void SetAddress (Bit16u seg, Bit32u off) { location = (PhysPt)GetAddress(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; }; 00459 void SetAddress (PhysPt adr) { location = adr; type = BKPNT_PHYSICAL; }; 00460 void SetInt (Bit8u _intNr, Bit16u ah, Bit16u al) { intNr = _intNr, ahValue = ah; alValue = al; type = BKPNT_INTERRUPT; }; 00461 void SetOnce (bool _once) { once = _once; }; 00462 void SetType (EBreakpoint _type) { type = _type; }; 00463 void SetValue (Bit8u value) { ahValue = value; }; 00464 void SetOther (Bit8u other) { alValue = other; }; 00465 00466 bool IsActive (void) { return active; }; 00467 void Activate (bool _active); 00468 00469 EBreakpoint GetType (void) { return type; }; 00470 bool GetOnce (void) { return once; }; 00471 PhysPt GetLocation (void) { return location; }; 00472 Bit16u GetSegment (void) { return segment; }; 00473 Bit32u GetOffset (void) { return offset; }; 00474 Bit8u GetIntNr (void) { return intNr; }; 00475 Bit16u GetValue (void) { return ahValue; }; 00476 Bit16u GetOther (void) { return alValue; }; 00477 00478 // statics 00479 static CBreakpoint* AddBreakpoint (Bit16u seg, Bit32u off, bool once); 00480 static CBreakpoint* AddIntBreakpoint (Bit8u intNum, Bit16u ah, Bit16u al, bool once); 00481 static CBreakpoint* AddMemBreakpoint (Bit16u seg, Bit32u off); 00482 static void DeactivateBreakpoints(); 00483 static void ActivateBreakpoints (); 00484 static void ActivateBreakpointsExceptAt(PhysPt adr); 00485 static bool CheckBreakpoint (Bit16u seg, Bit32u off); 00486 static bool CheckIntBreakpoint (PhysPt adr, Bit8u intNr, Bit16u ahValue, Bit16u alValue); 00487 static CBreakpoint* FindPhysBreakpoint (Bit16u seg, Bit32u off, bool once); 00488 static CBreakpoint* FindOtherActiveBreakpoint(PhysPt adr, CBreakpoint* skip); 00489 static bool IsBreakpoint (Bit16u seg, Bit32u off); 00490 static bool DeleteBreakpoint (Bit16u seg, Bit32u off); 00491 static bool DeleteByIndex (Bit16u index); 00492 static void DeleteAll (void); 00493 static void ShowList (void); 00494 00495 00496 private: 00497 EBreakpoint type; 00498 // Physical 00499 PhysPt location; 00500 #if !C_HEAVY_DEBUG 00501 Bit8u oldData; 00502 #endif 00503 Bit16u segment; 00504 Bit32u offset; 00505 // Int 00506 Bit8u intNr; 00507 Bit16u ahValue; 00508 Bit16u alValue; 00509 // Shared 00510 bool active; 00511 bool once; 00512 00513 static std::list<CBreakpoint*> BPoints; 00514 }; 00515 00516 CBreakpoint::CBreakpoint(void):type(BKPNT_UNKNOWN),location(0), 00517 #if !C_HEAVY_DEBUG 00518 oldData(0xCC), 00519 #endif 00520 segment(0),offset(0),intNr(0),ahValue(0),alValue(0),active(false),once(false) { } 00521 00522 void CBreakpoint::Activate(bool _active) 00523 { 00524 #if !C_HEAVY_DEBUG 00525 if (GetType() == BKPNT_PHYSICAL) { 00526 if (_active) { 00527 // Set 0xCC and save old value 00528 Bit8u data = mem_readb(location); 00529 if (data != 0xCC) { 00530 oldData = data; 00531 mem_writeb(location,0xCC); 00532 } else if (!active) { 00533 // Another activate breakpoint is already here. 00534 // Find it, and copy its oldData value 00535 CBreakpoint *bp = FindOtherActiveBreakpoint(location, this); 00536 00537 if (!bp || bp->oldData == 0xCC) { 00538 // This might also happen if there is a real 0xCC instruction here 00539 DEBUG_ShowMsg("DEBUG: Internal error while activating breakpoint.\n"); 00540 oldData = 0xCC; 00541 } else 00542 oldData = bp->oldData; 00543 }; 00544 } else { 00545 if (mem_readb(location) == 0xCC) { 00546 if (oldData == 0xCC) 00547 DEBUG_ShowMsg("DEBUG: Internal error while deactivating breakpoint.\n"); 00548 00549 // Check if we are the last active breakpoint at this location 00550 bool otherActive = (FindOtherActiveBreakpoint(location, this) != 0); 00551 00552 // If so, remove 0xCC and set old value 00553 if (!otherActive) 00554 mem_writeb(location, oldData); 00555 }; 00556 } 00557 } 00558 #endif 00559 active = _active; 00560 } 00561 00562 // Statics 00563 std::list<CBreakpoint*> CBreakpoint::BPoints; 00564 00565 CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once) 00566 { 00567 CBreakpoint* bp = new CBreakpoint(); 00568 bp->SetAddress (seg,off); 00569 bp->SetOnce (once); 00570 BPoints.push_front (bp); 00571 return bp; 00572 } 00573 00574 CBreakpoint* CBreakpoint::AddIntBreakpoint(Bit8u intNum, Bit16u ah, Bit16u al, bool once) 00575 { 00576 CBreakpoint* bp = new CBreakpoint(); 00577 bp->SetInt (intNum,ah,al); 00578 bp->SetOnce (once); 00579 BPoints.push_front (bp); 00580 return bp; 00581 } 00582 00583 CBreakpoint* CBreakpoint::AddMemBreakpoint(Bit16u seg, Bit32u off) 00584 { 00585 CBreakpoint* bp = new CBreakpoint(); 00586 bp->SetAddress (seg,off); 00587 bp->SetOnce (false); 00588 bp->SetType (BKPNT_MEMORY); 00589 BPoints.push_front (bp); 00590 return bp; 00591 } 00592 00593 void CBreakpoint::ActivateBreakpoints() 00594 { 00595 // activate all breakpoints 00596 std::list<CBreakpoint*>::iterator i; 00597 for (i = BPoints.begin(); i != BPoints.end(); ++i) 00598 (*i)->Activate(true); 00599 } 00600 00601 void CBreakpoint::DeactivateBreakpoints() 00602 { 00603 // deactivate all breakpoints 00604 std::list<CBreakpoint*>::iterator i; 00605 for (i = BPoints.begin(); i != BPoints.end(); ++i) 00606 (*i)->Activate(false); 00607 } 00608 00609 void CBreakpoint::ActivateBreakpointsExceptAt(PhysPt adr) 00610 { 00611 // activate all breakpoints, except those at adr 00612 std::list<CBreakpoint*>::iterator i; 00613 for (i = BPoints.begin(); i != BPoints.end(); ++i) { 00614 CBreakpoint* bp = (*i); 00615 // Do not activate breakpoints at adr 00616 if (bp->GetType() == BKPNT_PHYSICAL && bp->GetLocation() == adr) 00617 continue; 00618 bp->Activate(true); 00619 } 00620 } 00621 00622 bool CBreakpoint::CheckBreakpoint(Bit16u seg, Bit32u off) 00623 // Checks if breakpoint is valid and should stop execution 00624 { 00625 // Quick exit if there are no breakpoints 00626 if (BPoints.empty()) return false; 00627 00628 // Search matching breakpoint 00629 std::list<CBreakpoint*>::iterator i; 00630 CBreakpoint* bp; 00631 for(i=BPoints.begin(); i != BPoints.end(); ++i) { 00632 bp = (*i); 00633 if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetSegment()==seg) && (bp->GetOffset()==off)) { 00634 // Found, 00635 if (bp->GetOnce()) { 00636 // delete it, if it should only be used once 00637 (BPoints.erase)(i); 00638 bp->Activate(false); 00639 delete bp; 00640 } else { 00641 // Also look for once-only breakpoints at this address 00642 bp = FindPhysBreakpoint(seg, off, true); 00643 if (bp) { 00644 BPoints.remove(bp); 00645 bp->Activate(false); 00646 delete bp; 00647 } 00648 } 00649 return true; 00650 } 00651 #if C_HEAVY_DEBUG 00652 // Memory breakpoint support 00653 else if (bp->IsActive()) { 00654 if ((bp->GetType()==BKPNT_MEMORY) || (bp->GetType()==BKPNT_MEMORY_PROT) || (bp->GetType()==BKPNT_MEMORY_LINEAR)) { 00655 // Watch Protected Mode Memoryonly in pmode 00656 if (bp->GetType()==BKPNT_MEMORY_PROT) { 00657 // Check if pmode is active 00658 if (!cpu.pmode) return false; 00659 // Check if descriptor is valid 00660 Descriptor desc; 00661 if (!cpu.gdt.GetDescriptor(bp->GetSegment(),desc)) return false; 00662 if (desc.GetLimit()==0) return false; 00663 } 00664 00665 Bitu address; 00666 if (bp->GetType()==BKPNT_MEMORY_LINEAR) address = bp->GetOffset(); 00667 else address = (Bitu)GetAddress(bp->GetSegment(),bp->GetOffset()); 00668 Bit8u value=0; 00669 if (mem_readb_checked((PhysPt)address,&value)) return false; 00670 if (bp->GetValue() != value) { 00671 // Yup, memory value changed 00672 DEBUG_ShowMsg("DEBUG: Memory breakpoint %s: %04X:%04X - %02X -> %02X\n",(bp->GetType()==BKPNT_MEMORY_PROT)?"(Prot)":"",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value); 00673 bp->SetValue(value); 00674 return true; 00675 } 00676 } 00677 } 00678 #endif 00679 } 00680 return false; 00681 } 00682 00683 bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue, Bit16u alValue) 00684 // Checks if interrupt breakpoint is valid and should stop execution 00685 { 00686 if (BPoints.empty()) return false; 00687 00688 // unused 00689 (void)adr; 00690 00691 // Search matching breakpoint 00692 std::list<CBreakpoint*>::iterator i; 00693 for(i=BPoints.begin(); i != BPoints.end(); ++i) { 00694 CBreakpoint* bp = (*i); 00695 if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) { 00696 if (((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) && ((bp->GetOther()==BPINT_ALL) || (bp->GetOther()==alValue))) { 00697 // Ignore it once ? 00698 // Found 00699 if (bp->GetOnce()) { 00700 // delete it, if it should only be used once 00701 (BPoints.erase)(i); 00702 bp->Activate(false); 00703 delete bp; 00704 } 00705 return true; 00706 } 00707 } 00708 } 00709 return false; 00710 } 00711 00712 void CBreakpoint::DeleteAll() 00713 { 00714 std::list<CBreakpoint*>::iterator i; 00715 for(i=BPoints.begin(); i != BPoints.end(); ++i) { 00716 CBreakpoint* bp = (*i); 00717 bp->Activate(false); 00718 delete bp; 00719 } 00720 (BPoints.clear)(); 00721 } 00722 00723 00724 bool CBreakpoint::DeleteByIndex(Bit16u index) 00725 { 00726 // Search matching breakpoint 00727 int nr = 0; 00728 std::list<CBreakpoint*>::iterator i; 00729 CBreakpoint* bp; 00730 for(i=BPoints.begin(); i != BPoints.end(); ++i) { 00731 if (nr==index) { 00732 bp = (*i); 00733 (BPoints.erase)(i); 00734 bp->Activate(false); 00735 delete bp; 00736 return true; 00737 } 00738 nr++; 00739 } 00740 return false; 00741 } 00742 00743 CBreakpoint* CBreakpoint::FindPhysBreakpoint(Bit16u seg, Bit32u off, bool once) 00744 { 00745 if (BPoints.empty()) return 0; 00746 #if !C_HEAVY_DEBUG 00747 PhysPt adr = GetAddress(seg, off); 00748 #endif 00749 // Search for matching breakpoint 00750 std::list<CBreakpoint*>::iterator i; 00751 CBreakpoint* bp; 00752 for(i=BPoints.begin(); i != BPoints.end(); ++i) { 00753 bp = (*i); 00754 #if C_HEAVY_DEBUG 00755 // Heavy debugging breakpoints are triggered by matching seg:off 00756 bool atLocation = bp->GetSegment() == seg && bp->GetOffset() == off; 00757 #else 00758 // Normal debugging breakpoints are triggered at an address 00759 bool atLocation = bp->GetLocation() == adr; 00760 #endif 00761 00762 if (bp->GetType() == BKPNT_PHYSICAL && atLocation && bp->GetOnce() == once) 00763 return bp; 00764 } 00765 00766 return 0; 00767 } 00768 00769 CBreakpoint* CBreakpoint::FindOtherActiveBreakpoint(PhysPt adr, CBreakpoint* skip) 00770 { 00771 std::list<CBreakpoint*>::iterator i; 00772 for (i = BPoints.begin(); i != BPoints.end(); ++i) { 00773 CBreakpoint* bp = (*i); 00774 if (bp != skip && bp->GetType() == BKPNT_PHYSICAL && bp->GetLocation() == adr && bp->IsActive()) 00775 return bp; 00776 } 00777 return 0; 00778 } 00779 00780 // is there a permanent breakpoint at address ? 00781 bool CBreakpoint::IsBreakpoint(Bit16u seg, Bit32u off) 00782 { 00783 return FindPhysBreakpoint(seg, off, false) != 0; 00784 } 00785 00786 bool CBreakpoint::DeleteBreakpoint(Bit16u seg, Bit32u off) 00787 { 00788 CBreakpoint* bp = FindPhysBreakpoint(seg, off, false); 00789 if (bp) { 00790 BPoints.remove(bp); 00791 delete bp; 00792 return true; 00793 } 00794 00795 return false; 00796 } 00797 00798 00799 void CBreakpoint::ShowList(void) 00800 { 00801 // iterate list 00802 int nr = 0; 00803 std::list<CBreakpoint*>::iterator i; 00804 for(i=BPoints.begin(); i != BPoints.end(); ++i) { 00805 CBreakpoint* bp = (*i); 00806 if (bp->GetType()==BKPNT_PHYSICAL) { 00807 DEBUG_ShowMsg("%02X. BP %04X:%04X\n",nr,bp->GetSegment(),bp->GetOffset()); 00808 } else if (bp->GetType()==BKPNT_INTERRUPT) { 00809 if (bp->GetValue()==BPINT_ALL) DEBUG_ShowMsg("%02X. BPINT %02X\n",nr,bp->GetIntNr()); 00810 else if (bp->GetOther()==BPINT_ALL) DEBUG_ShowMsg("%02X. BPINT %02X AH=%02X\n",nr,bp->GetIntNr(),bp->GetValue()); 00811 else DEBUG_ShowMsg("%02X. BPINT %02X AH=%02X AL=%02X\n",nr,bp->GetIntNr(),bp->GetValue(),bp->GetOther()); 00812 } else if (bp->GetType()==BKPNT_MEMORY) { 00813 DEBUG_ShowMsg("%02X. BPMEM %04X:%04X (%02X)\n",nr,bp->GetSegment(),bp->GetOffset(),bp->GetValue()); 00814 } else if (bp->GetType()==BKPNT_MEMORY_PROT) { 00815 DEBUG_ShowMsg("%02X. BPPM %04X:%08X (%02X)\n",nr,bp->GetSegment(),bp->GetOffset(),bp->GetValue()); 00816 } else if (bp->GetType()==BKPNT_MEMORY_LINEAR ) { 00817 DEBUG_ShowMsg("%02X. BPLM %08X (%02X)\n",nr,bp->GetOffset(),bp->GetValue()); 00818 } 00819 nr++; 00820 } 00821 } 00822 00823 bool DEBUG_Breakpoint(void) 00824 { 00825 /* First get the physical address and check for a set Breakpoint */ 00826 if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false; 00827 // Found. Breakpoint is valid 00828 // PhysPt where=(PhysPt)GetAddress(SegValue(cs),reg_eip); 00829 CBreakpoint::DeactivateBreakpoints(); // Deactivate all breakpoints 00830 return true; 00831 } 00832 00833 bool DEBUG_IntBreakpoint(Bit8u intNum) 00834 { 00835 if (inhibit_int_breakpoint) return false; /* or else stepping over INT 21h when BPINT 21h does nothing */ 00836 /* First get the physical address and check for a set Breakpoint */ 00837 PhysPt where=(PhysPt)GetAddress(SegValue(cs),reg_eip); 00838 if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah,reg_al)) return false; 00839 // Found. Breakpoint is valid 00840 CBreakpoint::DeactivateBreakpoints(); // Deactivate all breakpoints 00841 return true; 00842 } 00843 00844 static bool StepOver() 00845 { 00846 exitLoop = false; 00847 PhysPt start=(PhysPt)GetAddress(SegValue(cs),reg_eip); 00848 char dline[200];Bitu size; 00849 size=DasmI386(dline, start, reg_eip, cpu.code.big); 00850 00851 if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) { 00852 // Don't add a temporary breakpoint if there's already one here 00853 if (!CBreakpoint::FindPhysBreakpoint(SegValue(cs), (Bit32u)(reg_eip+size), true)) 00854 CBreakpoint::AddBreakpoint(SegValue(cs),(Bit32u)(reg_eip+size), true); 00855 debugging=false; 00856 00857 logBuffSuppressConsole = false; 00858 if (logBuffSuppressConsoleNeedUpdate) { 00859 logBuffSuppressConsoleNeedUpdate = false; 00860 DEBUG_RefreshPage(0); 00861 } 00862 00863 DrawCode(); 00864 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu); 00865 return true; 00866 } 00867 return false; 00868 } 00869 00870 bool DEBUG_ExitLoop(void) 00871 { 00872 #if C_HEAVY_DEBUG 00873 DrawVariables(); 00874 #endif 00875 00876 if (exitLoop) { 00877 exitLoop = false; 00878 return true; 00879 } 00880 return false; 00881 } 00882 00883 /********************/ 00884 /* Draw windows */ 00885 /********************/ 00886 00887 static void DrawData(void) { 00888 if (dbg.win_main == NULL || dbg.win_data == NULL) 00889 return; 00890 00891 Bit8u ch; 00892 Bit32u add = dataOfs; 00893 Bit64u address; 00894 int w,h,y; 00895 00896 /* Data win */ 00897 getmaxyx(dbg.win_data,h,w); 00898 00899 if ((paging.enabled || cpu.pmode) && dbg.data_view != DBGBlock::DATV_PHYSICAL) h--; 00900 00901 for (y=0;y<h;y++) { 00902 // Address 00903 if (dbg.data_view == DBGBlock::DATV_SEGMENTED) { 00904 wattrset (dbg.win_data,0); 00905 mvwprintw (dbg.win_data,y,0,"%04X:%08X ",dataSeg,add); 00906 } 00907 else { 00908 wattrset (dbg.win_data,0); 00909 mvwprintw (dbg.win_data,y,0," %08X ",add); 00910 } 00911 00912 if (dbg.data_view == DBGBlock::DATV_PHYSICAL) { 00913 for (int x=0; x<16; x++) { 00914 address = add; 00915 00916 /* save the original page addr. 00917 * we must hack the phys page tlb to make the hardware handler map 1:1 the page for this call. */ 00918 PhysPt opg = paging.tlb.phys_page[address>>12]; 00919 00920 paging.tlb.phys_page[address>>12] = (Bit32u)(address>>12); 00921 00922 PageHandler *ph = MEM_GetPageHandler((Bitu)(address>>12)); 00923 00924 if (ph->flags & PFLAG_READABLE) 00925 ch = ph->GetHostReadPt((Bitu)(address>>12))[address&0xFFF]; 00926 else 00927 ch = ph->readb((PhysPt)address); 00928 00929 paging.tlb.phys_page[address>>12] = opg; 00930 00931 wattrset (dbg.win_data,0); 00932 mvwprintw (dbg.win_data,y,14+3*x,"%02X",ch); 00933 if (ch<32 || !isprint(*reinterpret_cast<unsigned char*>(&ch))) ch='.'; 00934 mvwprintw (dbg.win_data,y,63+x,"%c",ch); 00935 00936 add++; 00937 } 00938 } 00939 else { 00940 for (int x=0; x<16; x++) { 00941 if (dbg.data_view == DBGBlock::DATV_SEGMENTED) 00942 address = GetAddress(dataSeg,add); 00943 else 00944 address = add; 00945 00946 if (address != mem_no_address) { 00947 if (!mem_readb_checked((PhysPt)address,&ch)) { 00948 wattrset (dbg.win_data,0); 00949 mvwprintw (dbg.win_data,y,14+3*x,"%02X",ch); 00950 if (ch<32 || !isprint(*reinterpret_cast<unsigned char*>(&ch))) ch='.'; 00951 mvwprintw (dbg.win_data,y,63+x,"%c",ch); 00952 } 00953 else { 00954 wattrset (dbg.win_data, COLOR_PAIR(PAIR_BYELLOW_BLACK)); 00955 mvwprintw (dbg.win_data,y,14+3*x,"pf"); 00956 mvwprintw (dbg.win_data,y,63+x,"."); 00957 } 00958 } 00959 else { 00960 wattrset (dbg.win_data, COLOR_PAIR(PAIR_BYELLOW_BLACK)); 00961 mvwprintw (dbg.win_data,y,14+3*x,"na"); 00962 mvwprintw (dbg.win_data,y,63+x,"."); 00963 } 00964 00965 add++; 00966 } 00967 } 00968 } 00969 00970 if ((paging.enabled || cpu.pmode) && dbg.data_view != DBGBlock::DATV_PHYSICAL) { 00971 /* one line was set aside for this information */ 00972 wattrset (dbg.win_data,0); 00973 if (dbg.data_view == DBGBlock::DATV_SEGMENTED) { 00974 address = GetAddress(dataSeg,dataOfs); 00975 if (address != mem_no_address) 00976 mvwprintw (dbg.win_data,y,0," LIN=%08X ",(unsigned int)address); 00977 else 00978 mvwprintw (dbg.win_data,y,0," LIN=XXXXXXXX "); 00979 } 00980 else { 00981 address = dataOfs; 00982 mvwprintw (dbg.win_data,y,0," "); 00983 } 00984 00985 if (!mem_readb_checked((PhysPt)address,&ch)) { 00986 Bitu naddr = PAGING_GetPhysicalAddress((PhysPt)address); 00987 mvwprintw (dbg.win_data,y,14,"PHY=%08X ",(unsigned int)naddr); 00988 } 00989 else { 00990 mvwprintw (dbg.win_data,y,14,"PHY=XXXXXXXX "); 00991 } 00992 00993 wclrtoeol(dbg.win_data); 00994 00995 y++; 00996 } 00997 00998 wrefresh(dbg.win_data); 00999 } 01000 01001 void DrawRegistersUpdateOld(void) { 01002 /* Main Registers */ 01003 oldregs.eax=reg_eax; 01004 oldregs.ebx=reg_ebx; 01005 oldregs.ecx=reg_ecx; 01006 oldregs.edx=reg_edx; 01007 01008 oldregs.esi=reg_esi; 01009 oldregs.edi=reg_edi; 01010 oldregs.ebp=reg_ebp; 01011 oldregs.esp=reg_esp; 01012 oldregs.eip=reg_eip; 01013 01014 oldsegs[ds].val=SegValue(ds); 01015 oldsegs[es].val=SegValue(es); 01016 oldsegs[fs].val=SegValue(fs); 01017 oldsegs[gs].val=SegValue(gs); 01018 oldsegs[ss].val=SegValue(ss); 01019 oldsegs[cs].val=SegValue(cs); 01020 01021 /*Individual flags*/ 01022 oldflags = reg_flags; 01023 01024 oldcpucpl=cpu.cpl; 01025 } 01026 01027 static void DrawRegisters(void) { 01028 if (dbg.win_main == NULL || dbg.win_reg == NULL) 01029 return; 01030 01031 /* Main Registers */ 01032 SetColor(reg_eax!=oldregs.eax);mvwprintw (dbg.win_reg,0,4,"%08X",reg_eax); 01033 SetColor(reg_ebx!=oldregs.ebx);mvwprintw (dbg.win_reg,1,4,"%08X",reg_ebx); 01034 SetColor(reg_ecx!=oldregs.ecx);mvwprintw (dbg.win_reg,2,4,"%08X",reg_ecx); 01035 SetColor(reg_edx!=oldregs.edx);mvwprintw (dbg.win_reg,3,4,"%08X",reg_edx); 01036 01037 SetColor(reg_esi!=oldregs.esi);mvwprintw (dbg.win_reg,0,18,"%08X",reg_esi); 01038 SetColor(reg_edi!=oldregs.edi);mvwprintw (dbg.win_reg,1,18,"%08X",reg_edi); 01039 SetColor(reg_ebp!=oldregs.ebp);mvwprintw (dbg.win_reg,2,18,"%08X",reg_ebp); 01040 SetColor(reg_esp!=oldregs.esp);mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp); 01041 SetColor(reg_eip!=oldregs.eip);mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip); 01042 01043 SetColor(SegValue(ds)!=oldsegs[ds].val);mvwprintw (dbg.win_reg,0,31,"%04X",SegValue(ds)); 01044 SetColor(SegValue(es)!=oldsegs[es].val);mvwprintw (dbg.win_reg,0,41,"%04X",SegValue(es)); 01045 SetColor(SegValue(fs)!=oldsegs[fs].val);mvwprintw (dbg.win_reg,0,51,"%04X",SegValue(fs)); 01046 SetColor(SegValue(gs)!=oldsegs[gs].val);mvwprintw (dbg.win_reg,0,61,"%04X",SegValue(gs)); 01047 SetColor(SegValue(ss)!=oldsegs[ss].val);mvwprintw (dbg.win_reg,0,71,"%04X",SegValue(ss)); 01048 SetColor(SegValue(cs)!=oldsegs[cs].val);mvwprintw (dbg.win_reg,1,31,"%04X",SegValue(cs)); 01049 01050 /*Individual flags*/ 01051 Bitu changed_flags = reg_flags ^ oldflags; 01052 01053 SetColor(changed_flags&FLAG_CF); 01054 mvwprintw (dbg.win_reg,1,53,"%01X",GETFLAG(CF) ? 1:0); 01055 SetColor(changed_flags&FLAG_ZF); 01056 mvwprintw (dbg.win_reg,1,56,"%01X",GETFLAG(ZF) ? 1:0); 01057 SetColor(changed_flags&FLAG_SF); 01058 mvwprintw (dbg.win_reg,1,59,"%01X",GETFLAG(SF) ? 1:0); 01059 SetColor(changed_flags&FLAG_OF); 01060 mvwprintw (dbg.win_reg,1,62,"%01X",GETFLAG(OF) ? 1:0); 01061 SetColor(changed_flags&FLAG_AF); 01062 mvwprintw (dbg.win_reg,1,65,"%01X",GETFLAG(AF) ? 1:0); 01063 SetColor(changed_flags&FLAG_PF); 01064 mvwprintw (dbg.win_reg,1,68,"%01X",GETFLAG(PF) ? 1:0); 01065 01066 01067 SetColor(changed_flags&FLAG_DF); 01068 mvwprintw (dbg.win_reg,1,71,"%01X",GETFLAG(DF) ? 1:0); 01069 SetColor(changed_flags&FLAG_IF); 01070 mvwprintw (dbg.win_reg,1,74,"%01X",GETFLAG(IF) ? 1:0); 01071 SetColor(changed_flags&FLAG_TF); 01072 mvwprintw (dbg.win_reg,1,77,"%01X",GETFLAG(TF) ? 1:0); 01073 01074 SetColor(changed_flags&FLAG_IOPL); 01075 mvwprintw (dbg.win_reg,2,72,"%01X",GETFLAG(IOPL)>>12); 01076 01077 01078 SetColor(cpu.cpl ^ oldcpucpl); 01079 mvwprintw (dbg.win_reg,2,78,"%01X",cpu.cpl); 01080 01081 if (cpu.pmode) { 01082 if (reg_flags & FLAG_VM) mvwprintw(dbg.win_reg,0,76,"VM86"); 01083 else if (cpu.code.big) mvwprintw(dbg.win_reg,0,76,"Pr32"); 01084 else mvwprintw(dbg.win_reg,0,76,"Pr16"); 01085 mvwprintw(dbg.win_reg,2,62,paging.enabled ? "PAGE" : "NOPG"); 01086 } else { 01087 mvwprintw(dbg.win_reg,0,76,"Real"); 01088 mvwprintw(dbg.win_reg,2,62,"NOPG"); 01089 } 01090 01091 // Selector info, if available 01092 if ((cpu.pmode) && curSelectorName[0]) { 01093 char out1[200], out2[200]; 01094 GetDescriptorInfo(curSelectorName,out1,out2); 01095 mvwprintw(dbg.win_reg,2,28,out1); 01096 mvwprintw(dbg.win_reg,3,28,out2); 01097 } 01098 01099 wattrset(dbg.win_reg,0); 01100 mvwprintw(dbg.win_reg,3,60,"%u ",cycle_count); 01101 wrefresh(dbg.win_reg); 01102 } 01103 01104 bool DEBUG_IsPagingOutput(void); 01105 01106 static void DrawInput(void) { 01107 if (!debugging) { 01108 if (has_colors()) 01109 { 01110 wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK)); 01111 wattrset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK)); 01112 } 01113 01114 mvwprintw(dbg.win_inp,0,0,"%s","(Running)"); 01115 wclrtoeol(dbg.win_inp); 01116 } else if (debug_running) { 01117 if (has_colors()) 01118 { 01119 wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK)); 01120 wattrset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK)); 01121 } 01122 01123 mvwprintw(dbg.win_inp,0,0,"%s","(Running/watching)"); 01124 wclrtoeol(dbg.win_inp); 01125 } else if (DEBUG_IsPagingOutput()) { 01126 if (has_colors()) 01127 { 01128 wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK)); 01129 wattrset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK)); 01130 } 01131 01132 mvwprintw(dbg.win_inp,0,0,"%s","^ Paged content: Hit ENTER to continue, Q to exit paging"); 01133 wclrtoeol(dbg.win_inp); 01134 } else { 01135 //TODO long lines 01136 char* dispPtr = codeViewData.inputStr; 01137 char* curPtr = &codeViewData.inputStr[codeViewData.inputPos]; 01138 01139 wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_BLACK_GREY)); 01140 wattrset(dbg.win_inp,COLOR_PAIR(PAIR_BLACK_GREY)); 01141 mvwprintw(dbg.win_inp,0,0,"%c-> %s%c", 01142 (codeViewData.ovrMode?'O':'I'),dispPtr,(*curPtr?' ':'_')); 01143 wclrtoeol(dbg.win_inp); // not correct in pdcurses if full line 01144 mvwchgat(dbg.win_inp,10,0,3,0,(PAIR_BLACK_GREY),NULL); 01145 if (*curPtr) { 01146 mvwchgat(dbg.win_inp,0,(int)(curPtr-dispPtr+4),1,0,(PAIR_BLACK_GREY),NULL); 01147 } 01148 } 01149 01150 wattrset(dbg.win_inp,0); 01151 wrefresh(dbg.win_inp); 01152 } 01153 01154 static void DrawCode(void) { 01155 if (dbg.win_main == NULL || dbg.win_code == NULL) 01156 return; 01157 01158 Bit32u disEIP = codeViewData.useEIP; 01159 char dline[200];Bitu size;Bitu c; 01160 static char line20[21] = " "; 01161 int w,h; 01162 01163 getmaxyx(dbg.win_code,h,w); 01164 for (int i=0;i<h;i++) { 01165 Bit64u start = GetAddress(codeViewData.useCS,disEIP); 01166 01167 bool saveSel = false; 01168 if (has_colors()) { 01169 if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) { 01170 if (codeViewData.cursorPos==-1) { 01171 codeViewData.cursorPos = i; // Set Cursor 01172 } 01173 if (i == codeViewData.cursorPos) { 01174 codeViewData.cursorSeg = SegValue(cs); 01175 codeViewData.cursorOfs = disEIP; 01176 } 01177 saveSel = (i == codeViewData.cursorPos); 01178 01179 if (i == codeViewData.cursorPos) { 01180 wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREEN)); 01181 wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREEN)); 01182 } 01183 else { 01184 wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK)); 01185 wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK)); 01186 } 01187 } else if (i == codeViewData.cursorPos) { 01188 wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY)); 01189 wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY)); 01190 codeViewData.cursorSeg = codeViewData.useCS; 01191 codeViewData.cursorOfs = disEIP; 01192 saveSel = true; 01193 } else if (CBreakpoint::IsBreakpoint(codeViewData.useCS, disEIP)) { 01194 wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED)); 01195 wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED)); 01196 } else { 01197 wbkgdset(dbg.win_code,0); 01198 wattrset(dbg.win_code,0); 01199 } 01200 } 01201 01202 01203 bool toolarge = false; 01204 bool no_bytes = false; 01205 Bitu drawsize; 01206 01207 if (start != mem_no_address) { 01208 drawsize=size=DasmI386(dline, (PhysPt)start, disEIP, cpu.code.big); 01209 } 01210 else { 01211 drawsize=size=1; 01212 dline[0]=0; 01213 } 01214 mvwprintw(dbg.win_code,i,0,"%04X:%08X ",codeViewData.useCS,disEIP); 01215 01216 if (drawsize>10) { toolarge = true; drawsize = 9; } 01217 01218 if (start != mem_no_address) { 01219 for (c=0;c<drawsize;c++) { 01220 Bit8u value; 01221 if (!mem_readb_checked((PhysPt)(start+c),&value)) { 01222 wattrset (dbg.win_code,0); 01223 wprintw(dbg.win_code,"%02X",value); 01224 } 01225 else { 01226 no_bytes = true; 01227 wattrset (dbg.win_code, COLOR_PAIR(PAIR_BYELLOW_BLACK)); 01228 wprintw(dbg.win_code,"pf"); 01229 } 01230 } 01231 } 01232 else { 01233 wattrset (dbg.win_code, COLOR_PAIR(PAIR_BYELLOW_BLACK)); 01234 wprintw(dbg.win_code,"na"); 01235 } 01236 01237 wattrset (dbg.win_code,0); 01238 if (toolarge) { waddstr(dbg.win_code,".."); drawsize++; } 01239 // Spacepad up to 20 characters 01240 if(drawsize && (drawsize < 11)) { 01241 line20[20 - drawsize*2] = 0; 01242 waddstr(dbg.win_code,line20); 01243 line20[20 - drawsize*2] = ' '; 01244 } else waddstr(dbg.win_code,line20); 01245 01246 char empty_res[] = { 0 }; 01247 char* res = empty_res; 01248 wattrset (dbg.win_code,0); 01249 if (showExtend) res = AnalyzeInstruction(dline, saveSel); 01250 // Spacepad it up to 28 characters 01251 if (no_bytes) dline[0] = 0; 01252 size_t dline_len = strlen(dline); 01253 if (dline_len < 28) { 01254 for (c = (Bitu)dline_len; c < 28; c++) dline[c] = ' '; 01255 dline[28] = 0; 01256 } 01257 waddstr(dbg.win_code,dline); 01258 // Spacepad it up to 20 characters 01259 size_t res_len = strlen(res); 01260 if(res_len && (res_len < 21)) { 01261 waddstr(dbg.win_code,res); 01262 line20[20-res_len] = 0; 01263 waddstr(dbg.win_code,line20); 01264 line20[20-res_len] = ' '; 01265 } else waddstr(dbg.win_code,line20); 01266 01267 wclrtoeol(dbg.win_code); 01268 01269 disEIP+=(Bit32u)size; 01270 01271 if (i==0) codeViewData.firstInstSize = (Bit16u)size; 01272 if (i==4) codeViewData.useEIPmid = disEIP; 01273 } 01274 01275 codeViewData.useEIPlast = disEIP; 01276 01277 wrefresh(dbg.win_code); 01278 } 01279 01280 static void SetCodeWinStart() 01281 { 01282 if ((SegValue(cs)==codeViewData.useCS) && (reg_eip>=codeViewData.useEIP) && (reg_eip<=codeViewData.useEIPlast)) { 01283 // in valid window - scroll ? 01284 if (reg_eip>=codeViewData.useEIPmid) codeViewData.useEIP += codeViewData.firstInstSize; 01285 01286 } else { 01287 // totally out of range. 01288 codeViewData.useCS = SegValue(cs); 01289 codeViewData.useEIP = reg_eip; 01290 } 01291 codeViewData.cursorPos = -1; // Recalc Cursor position 01292 } 01293 01294 void DEBUG_CheckCSIP() { 01295 SetCodeWinStart(); 01296 } 01297 01298 /********************/ 01299 /* User input */ 01300 /********************/ 01301 01302 void SkipSpace(char*& hex) { 01303 while (*hex == ' ') hex++; 01304 } 01305 01306 Bit32u GetHexValue(char* const str, char* &hex,bool *parsed) 01307 { 01308 Bit32u value = 0; 01309 Bit32u regval = 0; 01310 hex = str; 01311 while (*hex == ' ') hex++; 01312 01313 // The user can enclose a value in double quotations to enter hex values that 01314 // would collide with a flag name (AC, AF, CF, and DF). 01315 if (*hex == '\"') { hex++; } 01316 else if (strncmp(hex, "EFLAGS", 6) == 0) { hex += 6; regval = (Bit32u)reg_flags; } 01317 else if (strncmp(hex, "FLAGS", 5) == 0) { hex += 5; regval = (Bit32u)reg_flags; } 01318 else if (strncmp(hex, "IOPL", 4) == 0) { hex += 4; regval = (reg_flags & FLAG_IOPL) >> 12u; } 01319 else if (strncmp(hex, "CR0", 3) == 0) { hex += 3; regval = (Bit32u)cpu.cr0; } 01320 else if (strncmp(hex, "CR2", 3) == 0) { hex += 3; regval = (Bit32u)paging.cr2; } 01321 else if (strncmp(hex, "CR3", 3) == 0) { hex += 3; regval = (Bit32u)paging.cr3; } 01322 else if (strncmp(hex, "EAX", 3) == 0) { hex += 3; regval = reg_eax; } 01323 else if (strncmp(hex, "EBX", 3) == 0) { hex += 3; regval = reg_ebx; } 01324 else if (strncmp(hex, "ECX", 3) == 0) { hex += 3; regval = reg_ecx; } 01325 else if (strncmp(hex, "EDX", 3) == 0) { hex += 3; regval = reg_edx; } 01326 else if (strncmp(hex, "ESI", 3) == 0) { hex += 3; regval = reg_esi; } 01327 else if (strncmp(hex, "EDI", 3) == 0) { hex += 3; regval = reg_edi; } 01328 else if (strncmp(hex, "EBP", 3) == 0) { hex += 3; regval = reg_ebp; } 01329 else if (strncmp(hex, "ESP", 3) == 0) { hex += 3; regval = reg_esp; } 01330 else if (strncmp(hex, "EIP", 3) == 0) { hex += 3; regval = reg_eip; } 01331 else if (strncmp(hex, "AX", 2) == 0) { hex += 2; regval = reg_ax; } 01332 else if (strncmp(hex, "BX", 2) == 0) { hex += 2; regval = reg_bx; } 01333 else if (strncmp(hex, "CX", 2) == 0) { hex += 2; regval = reg_cx; } 01334 else if (strncmp(hex, "DX", 2) == 0) { hex += 2; regval = reg_dx; } 01335 else if (strncmp(hex, "SI", 2) == 0) { hex += 2; regval = reg_si; } 01336 else if (strncmp(hex, "DI", 2) == 0) { hex += 2; regval = reg_di; } 01337 else if (strncmp(hex, "BP", 2) == 0) { hex += 2; regval = reg_bp; } 01338 else if (strncmp(hex, "SP", 2) == 0) { hex += 2; regval = reg_sp; } 01339 else if (strncmp(hex, "IP", 2) == 0) { hex += 2; regval = reg_ip; } 01340 else if (strncmp(hex, "AL", 2) == 0) { hex += 2; regval = reg_al; } 01341 else if (strncmp(hex, "BL", 2) == 0) { hex += 2; regval = reg_bl; } 01342 else if (strncmp(hex, "CL", 2) == 0) { hex += 2; regval = reg_cl; } 01343 else if (strncmp(hex, "DL", 2) == 0) { hex += 2; regval = reg_dl; } 01344 else if (strncmp(hex, "AH", 2) == 0) { hex += 2; regval = reg_ah; } 01345 else if (strncmp(hex, "BH", 2) == 0) { hex += 2; regval = reg_bh; } 01346 else if (strncmp(hex, "CH", 2) == 0) { hex += 2; regval = reg_ch; } 01347 else if (strncmp(hex, "DH", 2) == 0) { hex += 2; regval = reg_dh; } 01348 else if (strncmp(hex, "CS", 2) == 0) { hex += 2; regval = SegValue(cs); } 01349 else if (strncmp(hex, "DS", 2) == 0) { hex += 2; regval = SegValue(ds); } 01350 else if (strncmp(hex, "ES", 2) == 0) { hex += 2; regval = SegValue(es); } 01351 else if (strncmp(hex, "FS", 2) == 0) { hex += 2; regval = SegValue(fs); } 01352 else if (strncmp(hex, "GS", 2) == 0) { hex += 2; regval = SegValue(gs); } 01353 else if (strncmp(hex, "SS", 2) == 0) { hex += 2; regval = SegValue(ss); } 01354 else if (strncmp(hex, "AC", 2) == 0) { hex += 2; regval = GETFLAG(AC); } 01355 else if (strncmp(hex, "AF", 2) == 0) { hex += 2; regval = GETFLAG(AF); } 01356 else if (strncmp(hex, "CF", 2) == 0) { hex += 2; regval = GETFLAG(CF); } 01357 else if (strncmp(hex, "DF", 2) == 0) { hex += 2; regval = GETFLAG(DF); } 01358 else if (strncmp(hex, "ID", 2) == 0) { hex += 2; regval = GETFLAG(ID); } 01359 else if (strncmp(hex, "IF", 2) == 0) { hex += 2; regval = GETFLAG(IF); } 01360 else if (strncmp(hex, "NT", 2) == 0) { hex += 2; regval = GETFLAG(NT); } 01361 else if (strncmp(hex, "OF", 2) == 0) { hex += 2; regval = GETFLAG(OF); } 01362 else if (strncmp(hex, "PF", 2) == 0) { hex += 2; regval = GETFLAG(PF); } 01363 else if (strncmp(hex, "SF", 2) == 0) { hex += 2; regval = GETFLAG(SF); } 01364 else if (strncmp(hex, "TF", 2) == 0) { hex += 2; regval = GETFLAG(TF); } 01365 else if (strncmp(hex, "VM", 2) == 0) { hex += 2; regval = GETFLAG(VM); } 01366 else if (strncmp(hex, "ZF", 2) == 0) { hex += 2; regval = GETFLAG(ZF); } 01367 01368 else if (strncmp(hex,"DTASEG", 6) == 0) { hex += 6; regval = (!dos_kernel_disabled) ? (dos.dta() >> 16u) : 0; } 01369 else if (strncmp(hex,"DTAOFF", 6) == 0) { hex += 6; regval = (!dos_kernel_disabled) ? (dos.dta() & 0xFFFFu) : 0; } 01370 else if (strncmp(hex,"PSPSEG", 6) == 0) { hex += 6; regval = (!dos_kernel_disabled) ? dos.psp() : 0; } 01371 01372 while (*hex && *hex != '\"') { 01373 if ((*hex >= '0') && (*hex <= '9')) value = (value << 4u) + ((Bit32u)(*hex)) - '0'; 01374 else if ((*hex >= 'A') && (*hex <= 'F')) value = (value << 4u) + ((Bit32u)(*hex)) - 'A' + 10u; 01375 else { 01376 if (*hex == '+') { hex++; return regval + value + GetHexValue(hex, hex, parsed); } 01377 else 01378 if (*hex == '-') { hex++; return regval + value - GetHexValue(hex, hex, parsed); } 01379 else break; // No valid char 01380 } 01381 hex++; 01382 } 01383 01384 // If there is a closing quote, skip over it. 01385 if (*hex == '\"') { 01386 hex++; 01387 } 01388 01389 if (parsed != NULL) 01390 *parsed = (hex != str); 01391 01392 return regval + value; 01393 } 01394 01395 bool ChangeRegister(char* const str) 01396 { 01397 char* hex = str; 01398 01399 while (*hex) { 01400 while (*hex==' ') hex++; 01401 01402 if (strstr(hex,"EFLAGS")==hex) { hex+=6; CPU_SetFlags(GetHexValue(hex,hex),FMASK_ALL); } else 01403 if (strstr(hex,"FLAGS")==hex) { hex+=5; CPU_SetFlags(GetHexValue(hex,hex),FMASK_ALL & 0xFFFFu); } else 01404 01405 // "IOPL" 01406 01407 if (strncmp(hex,"EAX",3) == 0) { hex+=3; reg_eax = GetHexValue(hex,hex); } else 01408 if (strncmp(hex,"EBX",3) == 0) { hex+=3; reg_ebx = GetHexValue(hex,hex); } else 01409 if (strncmp(hex,"ECX",3) == 0) { hex+=3; reg_ecx = GetHexValue(hex,hex); } else 01410 if (strncmp(hex,"EDX",3) == 0) { hex+=3; reg_edx = GetHexValue(hex,hex); } else 01411 if (strncmp(hex,"ESI",3) == 0) { hex+=3; reg_esi = GetHexValue(hex,hex); } else 01412 if (strncmp(hex,"EDI",3) == 0) { hex+=3; reg_edi = GetHexValue(hex,hex); } else 01413 if (strncmp(hex,"EBP",3) == 0) { hex+=3; reg_ebp = GetHexValue(hex,hex); } else 01414 if (strncmp(hex,"ESP",3) == 0) { hex+=3; reg_esp = GetHexValue(hex,hex); } else 01415 if (strncmp(hex,"EIP",3) == 0) { hex+=3; reg_eip = GetHexValue(hex,hex); } else 01416 01417 if (strncmp(hex,"AX",2) == 0) { hex+=2; reg_ax = (Bit16u)GetHexValue(hex,hex); } else 01418 if (strncmp(hex,"BX",2) == 0) { hex+=2; reg_bx = (Bit16u)GetHexValue(hex,hex); } else 01419 if (strncmp(hex,"CX",2) == 0) { hex+=2; reg_cx = (Bit16u)GetHexValue(hex,hex); } else 01420 if (strncmp(hex,"DX",2) == 0) { hex+=2; reg_dx = (Bit16u)GetHexValue(hex,hex); } else 01421 if (strncmp(hex,"SI",2) == 0) { hex+=2; reg_si = (Bit16u)GetHexValue(hex,hex); } else 01422 if (strncmp(hex,"DI",2) == 0) { hex+=2; reg_di = (Bit16u)GetHexValue(hex,hex); } else 01423 if (strncmp(hex,"BP",2) == 0) { hex+=2; reg_bp = (Bit16u)GetHexValue(hex,hex); } else 01424 if (strncmp(hex,"SP",2) == 0) { hex+=2; reg_sp = (Bit16u)GetHexValue(hex,hex); } else 01425 if (strncmp(hex,"IP",2) == 0) { hex+=2; reg_ip = (Bit16u)GetHexValue(hex,hex); } else 01426 01427 if (strncmp(hex,"AL",2) == 0) { hex+=2; reg_al = (Bit8u)GetHexValue(hex,hex); } else 01428 if (strncmp(hex,"BL",2) == 0) { hex+=2; reg_bl = (Bit8u)GetHexValue(hex,hex); } else 01429 if (strncmp(hex,"CL",2) == 0) { hex+=2; reg_cl = (Bit8u)GetHexValue(hex,hex); } else 01430 if (strncmp(hex,"DL",2) == 0) { hex+=2; reg_dl = (Bit8u)GetHexValue(hex,hex); } else 01431 01432 if (strncmp(hex,"AH",2) == 0) { hex+=2; reg_ah = (Bit8u)GetHexValue(hex,hex); } else 01433 if (strncmp(hex,"BH",2) == 0) { hex+=2; reg_bh = (Bit8u)GetHexValue(hex,hex); } else 01434 if (strncmp(hex,"CH",2) == 0) { hex+=2; reg_ch = (Bit8u)GetHexValue(hex,hex); } else 01435 if (strncmp(hex,"DH",2) == 0) { hex+=2; reg_dh = (Bit8u)GetHexValue(hex,hex); } else 01436 01437 if (strncmp(hex,"CS",2) == 0) { hex+=2; SegSet16(cs,(Bit16u)GetHexValue(hex,hex)); } else 01438 if (strncmp(hex,"DS",2) == 0) { hex+=2; SegSet16(ds,(Bit16u)GetHexValue(hex,hex)); } else 01439 if (strncmp(hex,"ES",2) == 0) { hex+=2; SegSet16(es,(Bit16u)GetHexValue(hex,hex)); } else 01440 if (strncmp(hex,"FS",2) == 0) { hex+=2; SegSet16(fs,(Bit16u)GetHexValue(hex,hex)); } else 01441 if (strncmp(hex,"GS",2) == 0) { hex+=2; SegSet16(gs,(Bit16u)GetHexValue(hex,hex)); } else 01442 if (strncmp(hex,"SS",2) == 0) { hex+=2; SegSet16(ss,(Bit16u)GetHexValue(hex,hex)); } else 01443 01444 if (strncmp(hex,"AC",2) == 0) { hex+=2; SETFLAGBIT(AC,GetHexValue(hex,hex)); } else 01445 if (strncmp(hex,"AF",2) == 0) { hex+=2; SETFLAGBIT(AF,GetHexValue(hex,hex)); } else 01446 if (strncmp(hex,"CF",2) == 0) { hex+=2; SETFLAGBIT(CF,GetHexValue(hex,hex)); } else 01447 if (strncmp(hex,"DF",2) == 0) { hex+=2; SETFLAGBIT(DF,GetHexValue(hex,hex)); } else 01448 if (strncmp(hex,"ID",2) == 0) { hex+=2; SETFLAGBIT(ID,GetHexValue(hex,hex)); } else 01449 if (strncmp(hex,"IF",2) == 0) { hex+=2; SETFLAGBIT(IF,GetHexValue(hex,hex)); } else 01450 // "NT" 01451 if (strncmp(hex,"OF",2) == 0) { hex+=2; SETFLAGBIT(OF,GetHexValue(hex,hex)); } else 01452 if (strncmp(hex,"PF",2) == 0) { hex+=2; SETFLAGBIT(PF,GetHexValue(hex,hex)); } else 01453 if (strncmp(hex,"SF",2) == 0) { hex+=2; SETFLAGBIT(SF,GetHexValue(hex,hex)); } else 01454 if (strncmp(hex,"TF",2) == 0) { hex+=2; SETFLAGBIT(TF,GetHexValue(hex,hex)); } else 01455 // "VM" 01456 if (strncmp(hex,"ZF",2) == 0) { hex+=2; SETFLAGBIT(ZF,GetHexValue(hex,hex)); } else 01457 { return false; } 01458 } 01459 01460 return true; 01461 } 01462 01463 void DEBUG_GUI_Rebuild(void); 01464 void DBGUI_NextWindowIfActiveHidden(void); 01465 01466 void DEBUG_BeginPagedContent(void); 01467 void DEBUG_EndPagedContent(void); 01468 01469 std::string pc98_egc_shift_debug_status(void); 01470 01471 static void LogFPUInfo(void); 01472 01473 bool ParseCommand(char* str) { 01474 std::string copy_str = str; 01475 for (auto &c : copy_str) c = toupper(c); 01476 copy_str += '\0'; /* paranoid */ 01477 char* found = &(copy_str[0]); /* cannot use std::string c_str(), that is const char* */ 01478 01479 found = trim(found); 01480 string s_found(found); 01481 istringstream stream(s_found); 01482 string command; 01483 stream >> command; 01484 string::size_type next = s_found.find_first_not_of(' ',command.size()); 01485 if(next == string::npos) next = command.size(); 01486 (s_found.erase)(0,next); 01487 found = const_cast<char*>(s_found.c_str()); 01488 01489 if (command == "QUIT") { 01490 void DoKillSwitch(void); 01491 DoKillSwitch(); 01492 return true; 01493 } 01494 01495 if (command == "MOVEWINDN") { // MOVE WINDOW DOWN (by swapping) 01496 int order1 = dbg.win_find_order((int)dbg.active_win); 01497 int order2 = dbg.win_next_by_order(order1); 01498 01499 if (order1 >= 0 && order2 >= 0 && order1 < order2) { 01500 dbg.swap_order(order1,order2); 01501 DEBUG_GUI_Rebuild(); 01502 DBGUI_NextWindowIfActiveHidden(); 01503 } 01504 01505 return true; 01506 } 01507 01508 if (command == "MOVEWINUP") { // MOVE WINDOW UP (by swapping) 01509 int order1 = dbg.win_find_order((int)dbg.active_win); 01510 int order2 = dbg.win_prev_by_order(order1); 01511 01512 if (order1 >= 0 && order2 >= 0 && order1 > order2) { 01513 dbg.swap_order(order1,order2); 01514 DEBUG_GUI_Rebuild(); 01515 DBGUI_NextWindowIfActiveHidden(); 01516 } 01517 01518 return true; 01519 } 01520 01521 if (command == "SHOWWIN") { // SHOW WINDOW <name> 01522 int win = dbg.name_to_win(found); 01523 if (win >= 0) { 01524 dbg.win_vis[win] = true; 01525 01526 DEBUG_GUI_Rebuild(); 01527 DBGUI_NextWindowIfActiveHidden(); 01528 return true; 01529 } 01530 else { 01531 LOG_MSG("No such window '%s'. Windows are: %s",found,dbg.windowlist_by_name().c_str()); 01532 return false; 01533 } 01534 } 01535 01536 if (command == "HIDEWIN") { // HIDE WINDOW <name> 01537 int win = dbg.name_to_win(found); 01538 if (win >= 0) { 01539 dbg.win_vis[win] = false; 01540 01541 DEBUG_GUI_Rebuild(); 01542 DBGUI_NextWindowIfActiveHidden(); 01543 return true; 01544 } 01545 else { 01546 LOG_MSG("No such window '%s'. Windows are: %s",found,dbg.windowlist_by_name().c_str()); 01547 return false; 01548 } 01549 } 01550 01551 if (command == "MEMDUMP") { // Dump memory to file 01552 Bit16u seg = (Bit16u)GetHexValue(found,found); found++; 01553 Bit32u ofs = GetHexValue(found,found); found++; 01554 Bit32u num = GetHexValue(found,found); found++; 01555 SaveMemory(seg,ofs,num); 01556 return true; 01557 } 01558 01559 if (command == "MEMDUMPBIN") { // Dump memory to file binary 01560 Bit16u seg = (Bit16u)GetHexValue(found,found); found++; 01561 Bit32u ofs = GetHexValue(found,found); found++; 01562 Bit32u num = GetHexValue(found,found); found++; 01563 SaveMemoryBin(seg,ofs,num); 01564 return true; 01565 } 01566 01567 if (command == "IV") { // Insert variable 01568 Bit16u seg = (Bit16u)GetHexValue(found,found); found++; 01569 Bit32u ofs = (Bit16u)GetHexValue(found,found); found++; 01570 char name[16]; 01571 for (int i=0; i<16; i++) { 01572 if (found[i] && (found[i]!=' ')) name[i] = found[i]; 01573 else { name[i] = 0; break; } 01574 } 01575 name[15] = 0; 01576 01577 if(!name[0]) return false; 01578 DEBUG_ShowMsg("DEBUG: Created debug var %s at %04X:%04X\n",name,seg,ofs); 01579 CDebugVar::InsertVariable(name,(PhysPt)GetAddress(seg,ofs)); 01580 return true; 01581 } 01582 01583 if (command == "SV") { // Save variables 01584 char name[13]; 01585 for (int i=0; i<12; i++) { 01586 if (found[i] && (found[i]!=' ')) name[i] = found[i]; 01587 else { name[i] = 0; break; } 01588 } 01589 name[12] = 0; 01590 if(!name[0]) return false; 01591 DEBUG_ShowMsg("DEBUG: Variable list save (%s) : %s.\n",name,(CDebugVar::SaveVars(name)?"ok":"failure")); 01592 return true; 01593 } 01594 01595 if (command == "LV") { // load variables 01596 char name[13]; 01597 for (int i=0; i<12; i++) { 01598 if (found[i] && (found[i]!=' ')) name[i] = found[i]; 01599 else { name[i] = 0; break; } 01600 } 01601 name[12] = 0; 01602 if(!name[0]) return false; 01603 DEBUG_ShowMsg("DEBUG: Variable list load (%s) : %s.\n",name,(CDebugVar::LoadVars(name)?"ok":"failure")); 01604 return true; 01605 } 01606 01607 if (command == "EV") { // echo value (for viewing contents through GetHexValue 01608 std::string cpptmp; 01609 char tmp[128]; 01610 bool parsed; 01611 01612 SkipSpace(found); 01613 DEBUG_ShowMsg("EV of '%s' is:",found); 01614 01615 while (*found) { 01616 Bit32u value = GetHexValue(found,found,&parsed); SkipSpace(found); 01617 if (!parsed) { 01618 DEBUG_ShowMsg("GetHexValue parse error at %s",found); 01619 break; 01620 } 01621 sprintf(tmp,"%lx",(unsigned long)value); 01622 if (!cpptmp.empty()) cpptmp += " "; 01623 cpptmp += tmp; 01624 } 01625 01626 DEBUG_ShowMsg("%s",cpptmp.c_str()); 01627 return true; 01628 } 01629 01630 if (command == "ADDLOG") { 01631 if(found && *found) DEBUG_ShowMsg("NOTICE: %s\n",found); 01632 return true; 01633 } 01634 01635 if (command == "SR") { // Set register value 01636 DEBUG_ShowMsg("DEBUG: Set Register %s.\n",(ChangeRegister(found)?"success":"failure")); 01637 return true; 01638 } 01639 01640 if (command == "SM") { // Set memory with following values 01641 Bit16u seg = (Bit16u)GetHexValue(found,found); 01642 if (*found == ':') { // allow seg:off syntax 01643 found++; 01644 SkipSpace(found); 01645 } 01646 Bit32u ofs = GetHexValue(found,found); SkipSpace(found); 01647 Bit16u count = 0; 01648 bool parsed; 01649 01650 while (*found) { 01651 char prefix = 'B'; 01652 Bit32u value; 01653 01654 /* allow d: w: b: prefixes */ 01655 if ((*found == 'B' || *found == 'W' || *found == 'D') && found[1] == ':') { 01656 prefix = *found; found += 2; 01657 value = GetHexValue(found,found,&parsed); 01658 } 01659 else { 01660 value = GetHexValue(found,found,&parsed); 01661 } 01662 01663 SkipSpace(found); 01664 if (!parsed) { 01665 DEBUG_ShowMsg("GetHexValue parse error at %s",found); 01666 break; 01667 } 01668 01669 if (prefix == 'D') { 01670 mem_writed_checked((PhysPt)GetAddress(seg,ofs+count),value); 01671 count += 4; 01672 } 01673 else if (prefix == 'W') { 01674 mem_writew_checked((PhysPt)GetAddress(seg,ofs+count),value); 01675 count += 2; 01676 } 01677 else if (prefix == 'B') { 01678 mem_writeb_checked((PhysPt)GetAddress(seg,ofs+count),value); 01679 count++; 01680 } 01681 } 01682 01683 if (count > 0) 01684 DEBUG_ShowMsg("DEBUG: Memory changed (%u bytes)\n",(unsigned int)count); 01685 01686 return true; 01687 } 01688 01689 if (command == "BP") { // Add new breakpoint 01690 Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" 01691 Bit32u ofs = GetHexValue(found,found); 01692 CBreakpoint::AddBreakpoint(seg,ofs,false); 01693 DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X\n",seg,ofs); 01694 return true; 01695 } 01696 01697 #if C_HEAVY_DEBUG 01698 01699 if (command == "BPM") { // Add new breakpoint 01700 Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" 01701 Bit32u ofs = GetHexValue(found,found); 01702 CBreakpoint::AddMemBreakpoint(seg,ofs); 01703 DEBUG_ShowMsg("DEBUG: Set memory breakpoint at %04X:%04X\n",seg,ofs); 01704 return true; 01705 } 01706 01707 if (command == "BPPM") { // Add new breakpoint 01708 Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":" 01709 Bit32u ofs = GetHexValue(found,found); 01710 CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(seg,ofs); 01711 if (bp) { 01712 bp->SetType(BKPNT_MEMORY_PROT); 01713 DEBUG_ShowMsg("DEBUG: Set prot-mode memory breakpoint at %04X:%08X\n",seg,ofs); 01714 } 01715 return true; 01716 } 01717 01718 if (command == "BPLM") { // Add new breakpoint 01719 Bit32u ofs = GetHexValue(found,found); 01720 CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(0,ofs); 01721 if (bp) bp->SetType(BKPNT_MEMORY_LINEAR); 01722 DEBUG_ShowMsg("DEBUG: Set linear memory breakpoint at %08X\n",ofs); 01723 return true; 01724 } 01725 01726 #endif 01727 01728 if (command == "BPINT") { // Add Interrupt Breakpoint 01729 Bit8u intNr = (Bit8u)GetHexValue(found,found); 01730 bool all = !(*found); 01731 Bit8u valAH = (Bit8u)GetHexValue(found,found); 01732 if ((valAH==0x00) && (*found=='*' || all)) { 01733 CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,BPINT_ALL,false); 01734 DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X\n",intNr); 01735 } else { 01736 all = !(*found); 01737 Bit8u valAL = (Bit8u)GetHexValue(found,found); 01738 if ((valAL==0x00) && (*found=='*' || all)) { 01739 CBreakpoint::AddIntBreakpoint(intNr,valAH,BPINT_ALL,false); 01740 DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X\n",intNr,valAH); 01741 } else { 01742 CBreakpoint::AddIntBreakpoint(intNr,valAH,valAL,false); 01743 DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X AL=%02X\n",intNr,valAH,valAL); 01744 } 01745 } 01746 return true; 01747 } 01748 01749 if (command == "BPLIST") { 01750 DEBUG_BeginPagedContent(); 01751 DEBUG_ShowMsg("Breakpoint list:\n"); 01752 DEBUG_ShowMsg("-------------------------------------------------------------------------\n"); 01753 CBreakpoint::ShowList(); 01754 DEBUG_EndPagedContent(); 01755 return true; 01756 } 01757 01758 if (command == "BPDEL") { // Delete Breakpoints 01759 Bit8u bpNr = (Bit8u)GetHexValue(found,found); 01760 if ((bpNr==0x00) && (*found=='*')) { // Delete all 01761 CBreakpoint::DeleteAll(); 01762 DEBUG_ShowMsg("DEBUG: Breakpoints deleted.\n"); 01763 } else { 01764 // delete single breakpoint 01765 DEBUG_ShowMsg("DEBUG: Breakpoint deletion %s.\n",(CBreakpoint::DeleteByIndex(bpNr)?"success":"failure")); 01766 } 01767 return true; 01768 } 01769 01770 if (command == "RUN") { 01771 DrawRegistersUpdateOld(); 01772 debugging=false; 01773 01774 logBuffSuppressConsole = false; 01775 if (logBuffSuppressConsoleNeedUpdate) { 01776 logBuffSuppressConsoleNeedUpdate = false; 01777 DEBUG_RefreshPage(0); 01778 } 01779 01780 Bits DEBUG_NullCPUCore(void); 01781 01782 CPU_Cycles = 1; 01783 inhibit_int_breakpoint = true; 01784 if (cpudecoder != DEBUG_NullCPUCore) 01785 (*cpudecoder)(); 01786 01787 inhibit_int_breakpoint = false; 01788 01789 void DEBUG_DrawScreen(void); 01790 DEBUG_DrawScreen(); 01791 01792 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip); 01793 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu); 01794 DOSBOX_SetNormalLoop(); 01795 GFX_SetTitle(-1,-1,-1,is_paused); 01796 return true; 01797 } 01798 01799 if (command == "RUNWATCH") { 01800 debug_running = true; 01801 DEBUG_DrawScreen(); 01802 return true; 01803 } 01804 01805 if (command == "A20") { 01806 void MEM_A20_Enable(bool enabled); 01807 bool MEM_A20_Enabled(void); 01808 01809 command.clear(); 01810 stream >> command; 01811 01812 if (command == "ON" || command == "1") 01813 MEM_A20_Enable(true); 01814 else if (command == "OFF" || command == "0") 01815 MEM_A20_Enable(false); 01816 else if (command == "") 01817 DEBUG_ShowMsg("A20 gate is %s",MEM_A20_Enabled() ? "ON" : "OFF"); 01818 else 01819 return false; 01820 01821 return true; 01822 } 01823 01824 if (command == "PIC") { // interrupt controller state/controls 01825 void DEBUG_PICSignal(int irq,bool raise); 01826 void DEBUG_PICMask(int irq,bool mask); 01827 void DEBUG_PICAck(int irq); 01828 void DEBUG_LogPIC(void); 01829 01830 DEBUG_BeginPagedContent(); 01831 01832 command.clear(); 01833 stream >> command; 01834 01835 if (command == "MASKIRQ") { 01836 std::string what; 01837 stream >> what; 01838 int irq = atoi(what.c_str()); 01839 DEBUG_PICMask(irq,true); 01840 } 01841 else if (command == "UNMASKIRQ") { 01842 std::string what; 01843 stream >> what; 01844 int irq = atoi(what.c_str()); 01845 DEBUG_PICMask(irq,false); 01846 } 01847 else if (command == "ACKIRQ") { /* debugging: manually acknowledge an IRQ where the DOS program failed to do so */ 01848 std::string what; 01849 stream >> what; 01850 int irq = atoi(what.c_str()); 01851 DEBUG_PICAck(irq); 01852 } 01853 else if (command == "LOWERIRQ") { /* manually lower an IRQ signal */ 01854 std::string what; 01855 stream >> what; 01856 int irq = atoi(what.c_str()); 01857 DEBUG_PICSignal(irq,false); 01858 } 01859 else if (command == "RAISEIRQ") { /* manually raise an IRQ signal */ 01860 std::string what; 01861 stream >> what; 01862 int irq = atoi(what.c_str()); 01863 DEBUG_PICSignal(irq,true); 01864 } 01865 else if (command == "") { 01866 DEBUG_LogPIC(); 01867 } 01868 else { 01869 DEBUG_EndPagedContent(); 01870 return false; 01871 } 01872 01873 DEBUG_EndPagedContent(); 01874 01875 return true; 01876 } 01877 01878 if (command == "C") { // Set code overview 01879 Bit16u codeSeg = (Bit16u)GetHexValue(found,found); found++; 01880 Bit32u codeOfs = GetHexValue(found,found); 01881 DEBUG_ShowMsg("DEBUG: Set code overview to %04X:%04X\n",codeSeg,codeOfs); 01882 codeViewData.useCS = codeSeg; 01883 codeViewData.useEIP = codeOfs; 01884 codeViewData.cursorPos = 0; 01885 return true; 01886 } 01887 01888 if (command == "D") { // Set data overview 01889 dataSeg = (Bit16u)GetHexValue(found,found); SkipSpace(found); 01890 if (*found == ':') { // allow seg:off syntax 01891 found++; 01892 SkipSpace(found); 01893 } 01894 dataOfs = GetHexValue(found,found); SkipSpace(found); 01895 dbg.set_data_view(DBGBlock::DATV_SEGMENTED); 01896 DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs); 01897 return true; 01898 } 01899 01900 if (command == "DV") { // Set data overview 01901 dataSeg = 0; 01902 dataOfs = GetHexValue(found,found); SkipSpace(found); 01903 dbg.set_data_view(DBGBlock::DATV_VIRTUAL); 01904 DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs); 01905 return true; 01906 } 01907 01908 if (command == "DP") { // Set data overview 01909 dataSeg = 0; 01910 dataOfs = GetHexValue(found,found); SkipSpace(found); 01911 dbg.set_data_view(DBGBlock::DATV_PHYSICAL); 01912 DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs); 01913 return true; 01914 } 01915 01916 #if C_HEAVY_DEBUG 01917 01918 if (command == "LOG") { // Create Cpu normal log file 01919 cpuLogType = 1; 01920 command = "logcode"; 01921 } 01922 01923 if (command == "LOGS") { // Create Cpu short log file 01924 cpuLogType = 0; 01925 command = "logcode"; 01926 } 01927 01928 if (command == "LOGL") { // Create Cpu long log file 01929 cpuLogType = 2; 01930 command = "logcode"; 01931 } 01932 01933 if (command == "logcode") { //Shared code between all logs 01934 DEBUG_ShowMsg("DEBUG: Starting log\n"); 01935 cpuLogFile.open("LOGCPU.TXT"); 01936 if (!cpuLogFile.is_open()) { 01937 DEBUG_ShowMsg("DEBUG: Logfile couldn't be created.\n"); 01938 return false; 01939 } 01940 //Initialize log object 01941 cpuLogFile << hex << noshowbase << setfill('0') << uppercase; 01942 cpuLog = true; 01943 cpuLogCounter = (int)GetHexValue(found,found); 01944 01945 debugging = false; 01946 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip); 01947 DOSBOX_SetNormalLoop(); 01948 return true; 01949 } 01950 01951 #endif 01952 01953 if (command == "INTT") { //trace int. 01954 Bit8u intNr = (Bit8u)GetHexValue(found,found); 01955 DEBUG_ShowMsg("DEBUG: Tracing INT %02X\n",intNr); 01956 CPU_HW_Interrupt(intNr); 01957 SetCodeWinStart(); 01958 return true; 01959 } 01960 01961 if (command == "INT") { // start int. 01962 Bit8u intNr = (Bit8u)GetHexValue(found,found); 01963 DEBUG_ShowMsg("DEBUG: Starting INT %02X\n",intNr); 01964 CBreakpoint::AddBreakpoint(SegValue(cs),reg_eip, true); 01965 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip-1); 01966 debugging = false; 01967 DrawCode(); 01968 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu); 01969 DOSBOX_SetNormalLoop(); 01970 CPU_HW_Interrupt(intNr); 01971 return true; 01972 } 01973 01974 if (command == "SELINFO") { 01975 while (found[0] == ' ') found++; 01976 char out1[200],out2[200]; 01977 GetDescriptorInfo(found,out1,out2); 01978 DEBUG_ShowMsg("SelectorInfo %s:\n%s\n%s\n",found,out1,out2); 01979 return true; 01980 } 01981 01982 if (command == "DOS") { 01983 stream >> command; 01984 if (command == "MCBS") LogMCBS(); 01985 else if (command == "KERN") LogDOSKernMem(); 01986 else if (command == "XMS") LogXMS(); 01987 else if (command == "EMS") LogEMS(); 01988 else if (command == "FNKEY") LogFNKEY(); 01989 else return false; 01990 01991 return true; 01992 } 01993 01994 if (command == "BIOS") { 01995 stream >> command; 01996 01997 if (command == "MEM") LogBIOSMem(); 01998 else return false; 01999 02000 return true; 02001 } 02002 02003 if (command == "VGA") { 02004 stream >> command; 02005 02006 if (IS_PC98_ARCH) { 02007 DEBUG_ShowMsg("VGA debugger commands not available in PC-98 mode"); 02008 return false; 02009 } 02010 02011 if (command == "CRTC") { 02012 DEBUG_ShowMsg("VGA CRTC info: index=%02xh readonly=%u",vga.crtc.index,vga.crtc.read_only?1:0); 02013 DEBUG_ShowMsg("htotal=%02xh hdend=%02xh strhb=%02xh endhb=%02xh strrt=%02xh endrt=%02xh", 02014 vga.crtc.horizontal_total, vga.crtc.horizontal_display_end, 02015 vga.crtc.start_horizontal_blanking, vga.crtc.end_horizontal_blanking, 02016 vga.crtc.start_horizontal_retrace, vga.crtc.end_horizontal_retrace); 02017 DEBUG_ShowMsg("vtotal=%02xh overflow=%02xh prerwscn=%02xh maxscnl=%02xh offset=%02xh", 02018 vga.crtc.vertical_total, vga.crtc.overflow, 02019 vga.crtc.preset_row_scan, vga.crtc.maximum_scan_line, 02020 vga.crtc.offset); 02021 DEBUG_ShowMsg("curs-st=%02xh curs-en=%02xh start-addr=%02x%02xh curs-loc=%02x%02xh", 02022 vga.crtc.cursor_start, vga.crtc.cursor_end, 02023 vga.crtc.start_address_high, vga.crtc.start_address_low, 02024 vga.crtc.cursor_location_high, vga.crtc.cursor_location_low); 02025 DEBUG_ShowMsg("strvrt=%02xh endvrt=%02xh vdend=%02xh underline=%02xh modectrl=%02xh", 02026 vga.crtc.vertical_retrace_start, vga.crtc.vertical_retrace_end, 02027 vga.crtc.vertical_display_end, vga.crtc.underline_location, 02028 vga.crtc.mode_control); 02029 DEBUG_ShowMsg("strvhb=%02xh endvhb=%02xh linecomp=%02xh", 02030 vga.crtc.start_vertical_blanking, vga.crtc.end_vertical_blanking, 02031 vga.crtc.line_compare); 02032 } 02033 else if (command == "GC") { 02034 DEBUG_ShowMsg("VGA Graphics controller info: index=%02xh setreset=%02xh",vga.gfx.index,vga.gfx.set_reset); 02035 DEBUG_ShowMsg("enablesetreset=%02xh color-comp=%02xh data-rotate=%02xh rdmapsel=%02xh", 02036 vga.gfx.enable_set_reset, vga.gfx.color_compare, vga.gfx.data_rotate, 02037 vga.gfx.read_map_select); 02038 DEBUG_ShowMsg("mode=%02xh misc=%02xh color-dont-care=%02xh bitmask=%02xh", 02039 vga.gfx.mode, vga.gfx.miscellaneous, vga.gfx.color_dont_care, 02040 vga.gfx.bit_mask); 02041 } 02042 else if (command == "DAC") { 02043 // FIXME: Remove this var, use vga.dac.bits == 8 instead! 02044 extern bool vga_8bit_dac; 02045 02046 DEBUG_ShowMsg("VGA DAC info: bits=%u pel_mask=%02xh pel_index[RGB]=%02xh", 02047 vga_8bit_dac ? 8 : 6,//FIXME 02048 vga.dac.pel_mask, vga.dac.pel_index); 02049 DEBUG_ShowMsg("state=%02xh write_index=%02xh read_index=%02xh first_changed=%u", 02050 vga.dac.state, vga.dac.write_index, 02051 vga.dac.read_index, (unsigned int)vga.dac.first_changed); 02052 DEBUG_ShowMsg("hidac_counter=%u reg02=%02xh", 02053 vga.dac.hidac_counter, vga.dac.reg02); 02054 } 02055 else if (command == "DACPAL") { 02056 std::string cpptmp; 02057 char tmp[64]; 02058 02059 DEBUG_BeginPagedContent(); 02060 02061 DEBUG_ShowMsg("VGA DAC palette (RGB):"); 02062 for (unsigned int i=0;i < 256;i += 8) { 02063 sprintf(tmp,"%02x: ",i); 02064 cpptmp = tmp; 02065 02066 for (unsigned int c=0;c < 8;c++) { 02067 sprintf(tmp,"%02x%02x%02x%c", 02068 vga.dac.rgb[i+c].red, 02069 vga.dac.rgb[i+c].green, 02070 vga.dac.rgb[i+c].blue, 02071 c == 3 ? '-' : ' ' 02072 ); 02073 cpptmp += tmp; 02074 } 02075 02076 DEBUG_ShowMsg("%s",cpptmp.c_str()); 02077 } 02078 02079 DEBUG_EndPagedContent(); 02080 } 02081 else if (command == "SEQ") { 02082 DEBUG_ShowMsg("VGA Sequencer info: index=%02xh",vga.seq.index); 02083 DEBUG_ShowMsg("reset=%02xh clockmode=%02xh map_mask=%02xh charmapsel=%02xh memmode=%02xh", 02084 vga.seq.reset, vga.seq.clocking_mode, vga.seq.map_mask, 02085 vga.seq.character_map_select, vga.seq.memory_mode); 02086 } 02087 else if (command == "AC") { 02088 std::string cpptmp; 02089 char tmp[64]; 02090 02091 DEBUG_ShowMsg("VGA Attribute Controller info: attrindexmode=%u",vga.internal.attrindex?1:0); 02092 DEBUG_ShowMsg("mode_control=%02xh horz-pel-pan=%02xh overscan-color=%02xh", 02093 vga.attr.mode_control, vga.attr.horizontal_pel_panning, 02094 vga.attr.overscan_color); 02095 DEBUG_ShowMsg("color-plane-en=%02xh color-select=%02xh index=%02xh", 02096 vga.attr.color_plane_enable, vga.attr.color_select, vga.attr.index); 02097 DEBUG_ShowMsg("disabled-by-index=%u disabled-by-idx1-bit5=%u index-written=%u", 02098 (vga.attr.disabled & 1) ? 1 : 0, 02099 (vga.attr.disabled & 2) ? 1 : 0, 02100 vga.internal.attrindex); 02101 02102 cpptmp = " "; 02103 for (unsigned int i=0;i < 16;i++) { 02104 sprintf(tmp,"%02x%c",vga.attr.palette[i],((i&3) == 3 && i != 15) ? '-' : ' '); 02105 cpptmp += tmp; 02106 } 02107 02108 DEBUG_ShowMsg("palette={%s}",cpptmp.c_str()); 02109 } 02110 else if (command == "DRAW") { 02111 DEBUG_ShowMsg("VGA draw info: resizing=%u width=%lu height=%lu blocks=%lu", 02112 vga.draw.resizing?1:0,(unsigned long)vga.draw.width,(unsigned long)vga.draw.height,(unsigned long)vga.draw.blocks); 02113 DEBUG_ShowMsg("address=%lxh panning=%lu bytes-skip=%lu lin-mask=%lx pln-mask=%lx", 02114 (unsigned long)vga.draw.address,(unsigned long)vga.draw.panning,(unsigned long)vga.draw.bytes_skip, 02115 (unsigned long)vga.draw.linear_mask,(unsigned long)vga.draw.planar_mask); 02116 DEBUG_ShowMsg("addr-add=%lxh line-length=%lu addrline-total=%lu addrline=%lu", 02117 (unsigned long)vga.draw.address_add,(unsigned long)vga.draw.line_length, 02118 (unsigned long)vga.draw.address_line_total,(unsigned long)vga.draw.address_line); 02119 DEBUG_ShowMsg("line-total=%lu vblank-skip=%lu lines-done=%lu split-line=%lu", 02120 (unsigned long)vga.draw.lines_total,(unsigned long)vga.draw.vblank_skip, 02121 (unsigned long)vga.draw.lines_done,(unsigned long)vga.draw.split_line); 02122 DEBUG_ShowMsg("byte-pan-shft=%lu render-stop=%lu render-max=%lu scrn-ratio=%.3f", 02123 (unsigned long)vga.draw.byte_panning_shift,(unsigned long)vga.draw.render_step, 02124 (unsigned long)vga.draw.render_max,(double)vga.draw.screen_ratio); 02125 DEBUG_ShowMsg("blinking=%lu blink=%u char9dot=%u has-split=%u vret-trig=%u", 02126 (unsigned long)vga.draw.blinking,vga.draw.blink?1:0, 02127 vga.draw.char9dot?1:0,vga.draw.has_split?1:0, 02128 vga.draw.vret_triggered?1:0); 02129 DEBUG_ShowMsg("bpp=%lu curs-addr=%lxh curs-s=%u curs-e=%u curs-c=%u curs-d=%u curs-en=%u", 02130 (unsigned long)vga.draw.bpp, 02131 (unsigned long)vga.draw.cursor.address, 02132 vga.draw.cursor.sline, 02133 vga.draw.cursor.eline, 02134 vga.draw.cursor.count, 02135 vga.draw.cursor.delay, 02136 vga.draw.cursor.enabled); 02137 // TODO: Remove vga.draw.refresh, appears to be unused 02138 } 02139 else if (command == "MODE") { 02140 DEBUG_ShowMsg("VGA mode info:"); 02141 DEBUG_ShowMsg("mode=%s vref=%.3fHz href=%.3fHz chrclk=%.3fHz dotclk=%.3fHz", 02142 mode_texts[vga.mode],1000.0/vga.draw.delay.vtotal,1000.0/vga.draw.delay.htotal, 02143 vga.draw.clock,vga.draw.oscclock); 02144 DEBUG_ShowMsg("disp-start=%lxh real-start=%lxh retrace=%u scanlen=%lu cursor-start=%lxh", 02145 (unsigned long)vga.config.display_start, 02146 (unsigned long)vga.config.real_start, 02147 vga.config.retrace?1:0, 02148 (unsigned long)vga.config.scan_len, 02149 (unsigned long)vga.config.cursor_start); 02150 DEBUG_ShowMsg("line-compare=%lu chained=%u compat-chain4=%u pel-pan=%u hline-skip=%u", 02151 (unsigned long)vga.config.line_compare, 02152 vga.config.chained, 02153 (unsigned int)vga.config.compatible_chain4, 02154 (unsigned int)vga.config.pel_panning, 02155 (unsigned int)vga.config.hlines_skip); 02156 DEBUG_ShowMsg("byte-skip=%u addr-shift=%u rd-mode=%u wr-mode=%u rdmap-sel=%u", 02157 (unsigned int)vga.config.bytes_skip, 02158 (unsigned int)vga.config.addr_shift, 02159 (unsigned int)vga.config.read_mode, 02160 (unsigned int)vga.config.write_mode, 02161 (unsigned int)vga.config.read_map_select); 02162 DEBUG_ShowMsg("col-dont-care=%u color-compare=%u data-rotate=%u raster-op=%02xh", 02163 (unsigned int)vga.config.color_dont_care, 02164 (unsigned int)vga.config.color_compare, 02165 (unsigned int)vga.config.data_rotate, 02166 (unsigned int)vga.config.raster_op); 02167 DEBUG_ShowMsg("fbmsk=%x fmmsk=%x fnmmsk=%x fsr=%x fnesr=%x fesr=%x feasr=%x", 02168 (unsigned int)vga.config.full_bit_mask, 02169 (unsigned int)vga.config.full_map_mask, 02170 (unsigned int)vga.config.full_not_map_mask, 02171 (unsigned int)vga.config.full_set_reset, 02172 (unsigned int)vga.config.full_not_enable_set_reset, 02173 (unsigned int)vga.config.full_enable_set_reset, 02174 (unsigned int)vga.config.full_enable_and_set_reset); 02175 } 02176 else { 02177 return false; 02178 } 02179 02180 return true; 02181 } 02182 02183 if (command == "PC98") { 02184 stream >> command; 02185 02186 if (!IS_PC98_ARCH) { 02187 DEBUG_ShowMsg("PC-98 debugger commands not available except in PC-98 mode"); 02188 return false; 02189 } 02190 02191 if (command == "MODE") { 02192 DEBUG_ShowMsg("Mode info:"); 02193 DEBUG_ShowMsg("mode=%s vref=%.3fHz href=%.3fHz chrclk=%.3fHz dotclk=%.3fHz", 02194 mode_texts[vga.mode],1000.0/vga.draw.delay.vtotal,1000.0/vga.draw.delay.htotal, 02195 vga.draw.clock,vga.draw.oscclock); 02196 } 02197 else if (command == "GRAPHICS") { 02198 const auto &gdc = pc98_gdc[GDC_SLAVE]; 02199 std::string cpptmp; 02200 02201 cpptmp.clear(); 02202 if (gdc_analog) { 02203 if (pc98_gdc_vramop & (1 << VOPBIT_VGA)) 02204 cpptmp += "'256-color packed' "; 02205 else 02206 cpptmp += "'16-color planar' "; 02207 } 02208 else { 02209 cpptmp += "'8-color planar' "; 02210 } 02211 02212 if (egc_enable_enable) /* Port 6Ah, 0x06/0x07 to enable EGC enable commands 0x04/0x05 */ 02213 cpptmp += "EGC-ENABL "; 02214 if (pc98_gdc_vramop & (1 << VOPBIT_EGC)) /* Port 6Ah, 0x04/0x05 */ 02215 cpptmp += "EGC "; 02216 if (pc98_gdc_vramop & (2 << VOPBIT_GRCG)) /* Port 7Ch, bits [7:6]. bit 7 (2 << VOPBIT_GRCG) is the enable. */ 02217 cpptmp += "GRCG "; 02218 02219 if (gdc.display_enable) 02220 cpptmp += "ENABLED "; 02221 else 02222 cpptmp += "DISABLED "; 02223 02224 if (gdc.doublescan) { 02225 if (pc98_graphics_hide_odd_raster_200line) 02226 cpptmp += "200-LINE-EVEN-SCAN "; 02227 else 02228 cpptmp += "DOUBLESCAN "; 02229 } 02230 02231 if (pc98_pegc_linear_framebuffer_enabled()) 02232 cpptmp += "PEGC-LFB "; 02233 02234 if (pc98_gdc_vramop & (1 << VOPBIT_PEGC_PLANAR)) 02235 cpptmp += "256-PLANAR "; 02236 02237 DEBUG_ShowMsg("PC-98 graphics mode: %s",cpptmp.c_str()); 02238 02239 /*--------------------*/ 02240 02241 cpptmp.clear(); 02242 DEBUG_ShowMsg("PC-98 page display: cpu=%u display-pending=%u display-active=%u pitch=%u", 02243 (pc98_gdc_vramop & (1 << VOPBIT_ACCESS))?1:0, 02244 GDC_display_plane_pending, 02245 GDC_display_plane, 02246 gdc.display_pitch); 02247 02248 /*--------------------*/ 02249 02250 cpptmp.clear(); 02251 DEBUG_ShowMsg("PC-98 status: gdc5mhz=%u vsync-int-trig=%u rowheight=%u lines-drawn=%u", 02252 gdc_5mhz_mode,GDC_vsync_interrupt,gdc.row_height,(unsigned int)vga.draw.lines_done); 02253 DEBUG_ShowMsg(" cur-row-line=%u cur-scan=0x%x cur-partition=%u/%u part-remline=%u", 02254 gdc.row_line,gdc.scan_address,gdc.display_partition,gdc.display_partition_mask+1,gdc.display_partition_rem_lines); 02255 DEBUG_ShowMsg(" vram-bound=%uKB", 02256 pc98_256kb_boundary?256:128); 02257 02258 /*--------------------*/ 02259 02260 cpptmp.clear(); 02261 { 02262 char tmp[16]; 02263 for (unsigned int i=0;i < 16;i++) { 02264 sprintf(tmp,"%02x%c",gdc.param_ram[i],((i&3) == 3 && i != 15) ? '-' : ' '); 02265 cpptmp += tmp; 02266 } 02267 } 02268 DEBUG_ShowMsg("PC-98 GDC PRAM: wptr=%u %s",gdc.param_ram_wptr,cpptmp.c_str()); 02269 02270 /*---------------------*/ 02271 cpptmp.clear(); 02272 DEBUG_ShowMsg("PC-98 GRCG: active=%u mode=%s tilecount=%u modereg(7Ch)=%02xh", 02273 (pc98_gdc_vramop & (2 << VOPBIT_GRCG))?1:0, 02274 (pc98_gdc_vramop & (1 << VOPBIT_GRCG))?"Read/Modify/Write":"TCR/TDW", 02275 pc98_gdc_tile_counter, 02276 pc98_gdc_modereg); 02277 02278 /*---------------------*/ 02279 cpptmp.clear(); 02280 DEBUG_ShowMsg("PC-98 GRGC tiles: [%02x %02x] [%02x %02x] [%02x %02x] [%02x %02x]", 02281 pc98_gdc_tiles[0].b[0], 02282 pc98_gdc_tiles[0].b[1], 02283 pc98_gdc_tiles[1].b[0], 02284 pc98_gdc_tiles[1].b[1], 02285 pc98_gdc_tiles[2].b[0], 02286 pc98_gdc_tiles[2].b[1], 02287 pc98_gdc_tiles[3].b[0], 02288 pc98_gdc_tiles[3].b[1]); 02289 } 02290 else if (command == "TEXT") { 02291 const auto &gdc = pc98_gdc[GDC_MASTER]; 02292 std::string cpptmp; 02293 02294 cpptmp.clear(); 02295 if (gdc.display_enable) 02296 cpptmp += "ENABLED "; 02297 else 02298 cpptmp += "DISABLED "; 02299 02300 if (gdc.doublescan) 02301 cpptmp += "DOUBLESCAN "; 02302 02303 if (pc98_attr4_graphic) 02304 cpptmp += "SIMPLE-GRPH "; 02305 else 02306 cpptmp += "VERT-LINE "; 02307 02308 DEBUG_ShowMsg("PC-98 text mode: %s",cpptmp.c_str()); 02309 02310 /*--------------------*/ 02311 02312 cpptmp.clear(); 02313 DEBUG_ShowMsg("PC-98 display/cursor: pitch=%u curs-en=%u curs-blink=%u curs-blinkrate=%u", 02314 gdc.display_pitch, 02315 gdc.cursor_enable, 02316 gdc.cursor_blink, 02317 gdc.cursor_blink_rate); 02318 02319 DEBUG_ShowMsg(" curs-blink-count=%u curs-blink-state=%u/4 crt-mode=%u", 02320 gdc.cursor_blink_count, 02321 gdc.cursor_blink_state, 02322 pc98_crt_mode?1:0); 02323 02324 /*--------------------*/ 02325 02326 cpptmp.clear(); 02327 DEBUG_ShowMsg("PC-98 status: gdc5mhz=%u vsync-int-trig=%u rowheight=%u lines-drawn=%u", 02328 gdc_5mhz_mode,GDC_vsync_interrupt,gdc.row_height,(unsigned int)vga.draw.lines_done); 02329 DEBUG_ShowMsg(" cur-row-line=%u cur-scan=0x%x cur-partition=%u/%u part-remline=%u", 02330 gdc.row_line,gdc.scan_address,gdc.display_partition,gdc.display_partition_mask+1,gdc.display_partition_rem_lines); 02331 02332 /*--------------------*/ 02333 02334 cpptmp.clear(); 02335 { 02336 char tmp[16]; 02337 for (unsigned int i=0;i < 16;i++) { 02338 sprintf(tmp,"%02x%c",gdc.param_ram[i],((i&3) == 3 && i != 15) ? '-' : ' '); 02339 cpptmp += tmp; 02340 } 02341 } 02342 DEBUG_ShowMsg("PC-98 GDC PRAM: wptr=%u %s",gdc.param_ram_wptr,cpptmp.c_str()); 02343 02344 /*--------------------*/ 02345 02346 DEBUG_ShowMsg("PC-98 CG raster: row-scan=[start=%u/32 end-incl=%u/32] blank-at-in-charcell=%u/32", 02347 pc98_text_first_row_scanline_start, 02348 pc98_text_first_row_scanline_end, 02349 pc98_text_row_scanline_blank_at); 02350 02351 DEBUG_ShowMsg("PC-98 CG scrollregion: countstart=%u char-rows=%u lines=%u", 02352 pc98_text_row_scroll_count_start, 02353 pc98_text_row_scroll_num_lines, 02354 pc98_text_row_scroll_lines); 02355 } 02356 else if (command == "CGIO") { 02357 DEBUG_ShowMsg("PC-98 CG I/O port state (A1h-A9h odd): char-row=%u char-code=0x%04x", 02358 a1_font_char_offset, 02359 a1_font_load_addr); 02360 } 02361 else if (command == "EGC") { 02362 DEBUG_ShowMsg("PC-98 EGC Raw registers:"); 02363 DEBUG_ShowMsg(" 4A0h even: %04xh %04xh %04xh %04xh", 02364 pc98_egc_raw_values[0], 02365 pc98_egc_raw_values[1], 02366 pc98_egc_raw_values[2], 02367 pc98_egc_raw_values[3]); 02368 DEBUG_ShowMsg(" 4A8h even: %04xh %04xh %04xh %04xh bitplane-access=%02xh", 02369 pc98_egc_raw_values[4], 02370 pc98_egc_raw_values[5], 02371 pc98_egc_raw_values[6], 02372 pc98_egc_raw_values[7], 02373 pc98_egc_access); 02374 DEBUG_ShowMsg(" bg-color=%02xh bgcm=[%02xh %02xh] [%02xh %02xh] [%02xh %02xh] [%02xh %02xh]", 02375 pc98_egc_background_color, 02376 pc98_egc_bgcm[0].b[0], 02377 pc98_egc_bgcm[0].b[1], 02378 pc98_egc_bgcm[1].b[0], 02379 pc98_egc_bgcm[1].b[1], 02380 pc98_egc_bgcm[2].b[0], 02381 pc98_egc_bgcm[2].b[1], 02382 pc98_egc_bgcm[3].b[0], 02383 pc98_egc_bgcm[3].b[1]); 02384 DEBUG_ShowMsg(" fg-color=%02xh fgcm=[%02xh %02xh] [%02xh %02xh] [%02xh %02xh] [%02xh %02xh]", 02385 pc98_egc_foreground_color, 02386 pc98_egc_fgcm[0].b[0], 02387 pc98_egc_fgcm[0].b[1], 02388 pc98_egc_fgcm[1].b[0], 02389 pc98_egc_fgcm[1].b[1], 02390 pc98_egc_fgcm[2].b[0], 02391 pc98_egc_fgcm[2].b[1], 02392 pc98_egc_fgcm[3].b[0], 02393 pc98_egc_fgcm[3].b[1]); 02394 DEBUG_ShowMsg(" fgc-select=%d=%s lead-plane=%u srcmask=[%02xh %02xh]", 02395 pc98_egc_fgc, 02396 egc_fgc_modes[pc98_egc_fgc], 02397 pc98_egc_lead_plane, 02398 pc98_egc_srcmask[0],pc98_egc_srcmask[1]); 02399 DEBUG_ShowMsg(" mask=[%02xh %02xh] mask-effective=[%02xh %02xh] ROP=%02xh", 02400 pc98_egc_mask[0],pc98_egc_mask[1], 02401 pc98_egc_maskef[0],pc98_egc_maskef[1], 02402 pc98_egc_rop); 02403 DEBUG_ShowMsg(" compare-lead-plane=%u lightsource=%u shiftinput=%u regload=%u", 02404 pc98_egc_compare_lead, 02405 pc98_egc_lightsource, 02406 pc98_egc_shiftinput, 02407 pc98_egc_regload); 02408 DEBUG_ShowMsg(" shift-desc=%u shf-destbit=%u shf-srcbit=%u shf-length=%u", 02409 pc98_egc_shift_descend, 02410 pc98_egc_shift_destbit, 02411 pc98_egc_shift_srcbit, 02412 pc98_egc_shift_length); 02413 DEBUG_ShowMsg(" %s", 02414 pc98_egc_shift_debug_status().c_str()); 02415 } 02416 else { 02417 return false; 02418 } 02419 02420 return true; 02421 } 02422 02423 if (command == "EMU") { 02424 stream >> command; 02425 02426 if (command == "MEM") LogEMUMem(); 02427 else if (command == "MACHINE") LogEMUMachine(); 02428 else return false; 02429 02430 return true; 02431 } 02432 02433 if (command == "CALLBACKS") { 02434 DEBUG_BeginPagedContent(); 02435 02436 void DBG_CALLBACK_Dump(void); 02437 DBG_CALLBACK_Dump(); 02438 02439 DEBUG_EndPagedContent(); 02440 return true; 02441 } 02442 02443 if (command == "INP" || command == "INB") { 02444 Bit16u port = (Bit16u)GetHexValue(found,found); 02445 Bit8u r = IO_ReadB(port); 02446 DEBUG_ShowMsg("Result: %x",(unsigned int)r); 02447 return true; 02448 } 02449 02450 if (command == "INW") { 02451 Bit16u port = (Bit16u)GetHexValue(found,found); 02452 Bit16u r = IO_ReadW(port); 02453 DEBUG_ShowMsg("Result: %x",(unsigned int)r); 02454 return true; 02455 } 02456 02457 if (command == "IND") { 02458 Bit16u port = (Bit16u)GetHexValue(found,found); 02459 Bit32u r = IO_ReadD(port); 02460 DEBUG_ShowMsg("Result: %x",(unsigned int)r); 02461 return true; 02462 } 02463 02464 if (command == "OUTP" || command == "OUTB") { 02465 Bit16u port = (Bit16u)GetHexValue(found,found); 02466 Bit8u r = (Bit8u)GetHexValue(found,found); 02467 IO_WriteB(port,r); 02468 return true; 02469 } 02470 02471 if (command == "OUTW") { 02472 Bit16u port = (Bit16u)GetHexValue(found,found); 02473 Bit16u r = (Bit16u)GetHexValue(found,found); 02474 IO_WriteW(port,r); 02475 return true; 02476 } 02477 02478 if (command == "OUTD") { 02479 Bit16u port = (Bit16u)GetHexValue(found,found); 02480 Bit32u r = (Bit32u)GetHexValue(found,found); 02481 IO_WriteD(port,r); 02482 return true; 02483 } 02484 02485 if (command == "GDT") {LogGDT(); return true;} 02486 02487 if (command == "LDT") {LogLDT(); return true;} 02488 02489 if (command == "IDT") {LogIDT(); return true;} 02490 02491 if (command == "PAGING") {LogPages(found); return true;} 02492 02493 if (command == "CPU") {LogCPUInfo(); return true;} 02494 02495 if (command == "FPU") {LogFPUInfo(); return true;} 02496 02497 if (command == "INTVEC") { 02498 if (found[0] != 0) { 02499 OutputVecTable(found); 02500 return true; 02501 } 02502 } 02503 02504 if (command == "INTHAND") { 02505 if (found[0] != 0) { 02506 Bit8u intNr = (Bit8u)GetHexValue(found,found); 02507 DEBUG_ShowMsg("DEBUG: Set code overview to interrupt handler %X\n",intNr); 02508 if (cpu.pmode) { 02509 Descriptor gate; 02510 if (cpu.idt.GetDescriptor((Bitu)intNr<<3u,gate)) { 02511 codeViewData.useCS = (Bit16u)gate.GetSelector(); 02512 codeViewData.useEIP = (Bit32u)gate.GetOffset(); 02513 } 02514 else { 02515 DEBUG_ShowMsg("INTHAND unable to retrieve vector"); 02516 } 02517 } 02518 else { 02519 codeViewData.useCS = mem_readw(intNr*4u+2u); 02520 codeViewData.useEIP = mem_readw(intNr*4u); 02521 } 02522 codeViewData.cursorPos = 0; 02523 return true; 02524 } 02525 } 02526 02527 if(command == "EXTEND") { //Toggle additional data. 02528 showExtend = !showExtend; 02529 return true; 02530 } 02531 02532 if(command == "TIMERIRQ") { //Start a timer irq 02533 DEBUG_RaiseTimerIrq(); 02534 DEBUG_ShowMsg("Debug: Timer Int started.\n"); 02535 return true; 02536 } 02537 02538 02539 #if C_HEAVY_DEBUG 02540 if (command == "HEAVYLOG") { // Create Cpu log file 02541 logHeavy = !logHeavy; 02542 DEBUG_ShowMsg("DEBUG: Heavy cpu logging %s.\n",logHeavy?"on":"off"); 02543 return true; 02544 } 02545 02546 if (command == "ZEROPROTECT") { //toggle zero protection 02547 zeroProtect = !zeroProtect; 02548 DEBUG_ShowMsg("DEBUG: Zero code execution protection %s.\n",zeroProtect?"on":"off"); 02549 return true; 02550 } 02551 02552 #endif 02553 if (command == "HELP" || command == "?") { 02554 DEBUG_BeginPagedContent(); 02555 DEBUG_ShowMsg("Debugger commands (enter all values in hex or as register):\n"); 02556 DEBUG_ShowMsg("Commands------------------------------------------------\n"); 02557 DEBUG_ShowMsg("BP [segment]:[offset] - Set breakpoint.\n"); 02558 DEBUG_ShowMsg("BPINT [intNr] * - Set interrupt breakpoint.\n"); 02559 DEBUG_ShowMsg("BPINT [intNr] [ah] * - Set interrupt breakpoint with ah.\n"); 02560 DEBUG_ShowMsg("BPINT [intNr] [ah] [al] - Set interrupt breakpoint with ah and al.\n"); 02561 #if C_HEAVY_DEBUG 02562 DEBUG_ShowMsg("BPM [segment]:[offset] - Set memory breakpoint (memory change).\n"); 02563 DEBUG_ShowMsg("BPPM [selector]:[offset]- Set pmode-memory breakpoint (memory change).\n"); 02564 DEBUG_ShowMsg("BPLM [linear address] - Set linear memory breakpoint (memory change).\n"); 02565 #endif 02566 DEBUG_ShowMsg("BPLIST - List breakpoints.\n"); 02567 DEBUG_ShowMsg("BPDEL [bpNr] / * - Delete breakpoint nr / all.\n"); 02568 DEBUG_ShowMsg("C / D [segment]:[offset] - Set code / data view address.\n"); 02569 DEBUG_ShowMsg("DOS MCBS - Show Memory Control Block chain.\n"); 02570 DEBUG_ShowMsg("DOS KERN - Show DOS kernel memory blocks.\n"); 02571 DEBUG_ShowMsg("DOS XMS - Show XMS memory handles.\n"); 02572 DEBUG_ShowMsg("DOS EMS - Show EMS memory handles.\n"); 02573 DEBUG_ShowMsg("DOS FNKEY - Show PC-98 FnKey mapping.\n"); 02574 DEBUG_ShowMsg("BIOS MEM - Show BIOS memory blocks.\n"); 02575 DEBUG_ShowMsg("INT [nr] / INTT [nr] - Execute / Trace into interrupt.\n"); 02576 #if C_HEAVY_DEBUG 02577 DEBUG_ShowMsg("LOG [num] - Write cpu log file.\n"); 02578 DEBUG_ShowMsg("LOGS/LOGL [num] - Write short/long cpu log file.\n"); 02579 DEBUG_ShowMsg("HEAVYLOG - Enable/Disable automatic cpu log when dosbox exits.\n"); 02580 DEBUG_ShowMsg("ZEROPROTECT - Enable/Disable zero code execution detection.\n"); 02581 #endif 02582 DEBUG_ShowMsg("SR [reg] [value] - Set register value. Multiple pairs allowed.\n"); 02583 DEBUG_ShowMsg("SM [seg]:[off] [val] [.]..- Set memory with following values.\n"); 02584 DEBUG_ShowMsg("EV [value [value] ...] - Show register value(s).\n"); 02585 02586 DEBUG_ShowMsg("IV [seg]:[off] [name] - Create var name for memory address.\n"); 02587 DEBUG_ShowMsg("SV [filename] - Save var list in file.\n"); 02588 DEBUG_ShowMsg("LV [filename] - Load var list from file.\n"); 02589 02590 DEBUG_ShowMsg("ADDLOG [message] - Add message to the log file.\n"); 02591 02592 DEBUG_ShowMsg("MEMDUMP [seg]:[off] [len] - Write memory to file memdump.txt.\n"); 02593 DEBUG_ShowMsg("MEMDUMPBIN [s]:[o] [len] - Write memory to file memdump.bin.\n"); 02594 DEBUG_ShowMsg("SELINFO [segName] - Show selector info.\n"); 02595 02596 DEBUG_ShowMsg("INTVEC [filename] - Writes interrupt vector table to file.\n"); 02597 DEBUG_ShowMsg("INTHAND [intNum] - Set code view to interrupt handler.\n"); 02598 02599 DEBUG_ShowMsg("CPU - Display CPU status information.\n"); 02600 DEBUG_ShowMsg("FPU - Display FPU status information.\n"); 02601 DEBUG_ShowMsg("GDT - Lists descriptors of the GDT.\n"); 02602 DEBUG_ShowMsg("LDT - Lists descriptors of the LDT.\n"); 02603 DEBUG_ShowMsg("IDT - Lists descriptors of the IDT.\n"); 02604 DEBUG_ShowMsg("PAGING [page] - Display content of page table.\n"); 02605 DEBUG_ShowMsg("EXTEND - Toggle additional info.\n"); 02606 DEBUG_ShowMsg("TIMERIRQ - Run the system timer.\n"); 02607 02608 DEBUG_ShowMsg("IN[P|W|D] [port] - I/O port read byte/word/dword.\n"); 02609 DEBUG_ShowMsg("OUT[P|W|D] [port] [data] - I/O port write byte/word/dword.\n"); 02610 02611 DEBUG_ShowMsg("HELP - Help\n"); 02612 DEBUG_ShowMsg("Keys------------------------------------------------\n"); 02613 DEBUG_ShowMsg("F3/F6 - Previous command in history.\n"); 02614 DEBUG_ShowMsg("F4/F7 - Next command in history.\n"); 02615 DEBUG_ShowMsg("F5 - Run.\n"); 02616 DEBUG_ShowMsg("F9 - Set/Remove breakpoint.\n"); 02617 DEBUG_ShowMsg("F10/F11 - Step over / trace into instruction.\n"); 02618 DEBUG_ShowMsg("ALT + D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX.\n"); 02619 DEBUG_ShowMsg("Escape - Clear input line."); 02620 DEBUG_ShowMsg("Up/Down - Scroll up/down in the current window.\n"); 02621 DEBUG_ShowMsg("Page Up/Down - Page up/down in the current window.\n"); 02622 DEBUG_ShowMsg("Home/End - Move to begin/end of the current window.\n"); 02623 DEBUG_ShowMsg("TAB - Select next window\n"); 02624 DEBUG_EndPagedContent(); 02625 02626 return true; 02627 } 02628 02629 return false; 02630 } 02631 02632 char* AnalyzeInstruction(char* inst, bool saveSelector) { 02633 static char result[256]; 02634 02635 char instu[256]; 02636 02637 strcpy(instu,inst); 02638 upcase(instu); 02639 02640 result[0] = 0; 02641 char* pos = strchr(instu,'['); 02642 if (pos) { 02643 char prefix[3]; 02644 Bit16u seg; 02645 // Segment prefix ? 02646 if (*(pos-1)==':') { 02647 char* segpos = pos-3; 02648 prefix[0] = tolower(*segpos); 02649 prefix[1] = tolower(*(segpos+1)); 02650 prefix[2] = 0; 02651 seg = (Bit16u)GetHexValue(segpos,segpos); 02652 } else { 02653 if (strstr(pos,"SP") || strstr(pos,"BP")) { 02654 seg = SegValue(ss); 02655 strcpy(prefix,"ss"); 02656 } else { 02657 seg = SegValue(ds); 02658 strcpy(prefix,"ds"); 02659 } 02660 } 02661 02662 pos++; 02663 Bit32u adr = GetHexValue(pos,pos); 02664 while (*pos!=']') { 02665 if (*pos=='+') { 02666 pos++; 02667 adr += GetHexValue(pos,pos); 02668 } else if (*pos=='-') { 02669 pos++; 02670 adr -= GetHexValue(pos,pos); 02671 } else 02672 pos++; 02673 } 02674 Bit32u address = (Bit32u)GetAddress(seg,adr); 02675 if (!(get_tlb_readhandler(address)->flags & PFLAG_INIT)) { 02676 static char outmask[] = "%s:[%04X]=%02X"; 02677 02678 if (cpu.pmode) outmask[6] = '8'; 02679 switch (DasmLastOperandSize()) { 02680 case 8 : { Bit8u val = mem_readb(address); 02681 outmask[12] = '2'; 02682 sprintf(result,outmask,prefix,adr,val); 02683 } break; 02684 case 16: { Bit16u val = mem_readw(address); 02685 outmask[12] = '4'; 02686 sprintf(result,outmask,prefix,adr,val); 02687 } break; 02688 case 32: { Bit32u val = mem_readd(address); 02689 outmask[12] = '8'; 02690 sprintf(result,outmask,prefix,adr,val); 02691 } break; 02692 } 02693 } else { 02694 sprintf(result,"[illegal]"); 02695 } 02696 // Variable found ? 02697 CDebugVar* var = CDebugVar::FindVar(address); 02698 if (var) { 02699 // Replace occurrence 02700 char* pos1 = strchr(inst,'['); 02701 char* pos2 = strchr(inst,']'); 02702 if (pos1 && pos2) { 02703 char temp[256]; 02704 strcpy(temp,pos2); // save end 02705 pos1++; *pos1 = 0; // cut after '[' 02706 strcat(inst,var->GetName()); // add var name 02707 strcat(inst,temp); // add end 02708 } 02709 } 02710 // show descriptor info, if available 02711 if ((cpu.pmode) && saveSelector) { 02712 strcpy(curSelectorName,prefix); 02713 } 02714 } 02715 // If it is a callback add additional info 02716 pos = strstr(inst,"callback"); 02717 if (pos) { 02718 pos += 9; 02719 Bitu nr = GetHexValue(pos,pos); 02720 const char* descr = CALLBACK_GetDescription(nr); 02721 if (descr) { 02722 strcat(inst," ("); strcat(inst,descr); strcat(inst,")"); 02723 } 02724 } 02725 // Must be a jump 02726 if (instu[0] == 'J') 02727 { 02728 bool jmp = false; 02729 switch (instu[1]) { 02730 case 'A' : { jmp = (get_CF()?false:true) && (get_ZF()?false:true); // JA 02731 } break; 02732 case 'B' : { if (instu[2] == 'E') { 02733 jmp = (get_CF()?true:false) || (get_ZF()?true:false); // JBE 02734 } else { 02735 jmp = get_CF()?true:false; // JB 02736 } 02737 } break; 02738 case 'C' : { if (instu[2] == 'X') { 02739 jmp = reg_cx == 0; // JCXZ 02740 } else { 02741 jmp = get_CF()?true:false; // JC 02742 } 02743 } break; 02744 case 'E' : { jmp = get_ZF()?true:false; // JE 02745 } break; 02746 case 'G' : { if (instu[2] == 'E') { 02747 jmp = (get_SF()?true:false)==(get_OF()?true:false); // JGE 02748 } else { 02749 jmp = (get_ZF()?false:true) && ((get_SF()?true:false)==(get_OF()?true:false)); // JG 02750 } 02751 } break; 02752 case 'L' : { if (instu[2] == 'E') { 02753 jmp = (get_ZF()?true:false) || ((get_SF()?true:false)!=(get_OF()?true:false)); // JLE 02754 } else { 02755 jmp = (get_SF()?true:false)!=(get_OF()?true:false); // JL 02756 } 02757 } break; 02758 case 'M' : { jmp = true; // JMP 02759 } break; 02760 case 'N' : { switch (instu[2]) { 02761 case 'B' : 02762 case 'C' : { jmp = get_CF()?false:true; // JNB / JNC 02763 } break; 02764 case 'E' : { jmp = get_ZF()?false:true; // JNE 02765 } break; 02766 case 'O' : { jmp = get_OF()?false:true; // JNO 02767 } break; 02768 case 'P' : { jmp = get_PF()?false:true; // JNP 02769 } break; 02770 case 'S' : { jmp = get_SF()?false:true; // JNS 02771 } break; 02772 case 'Z' : { jmp = get_ZF()?false:true; // JNZ 02773 } break; 02774 } 02775 } break; 02776 case 'O' : { jmp = get_OF()?true:false; // JO 02777 } break; 02778 case 'P' : { if (instu[2] == 'O') { 02779 jmp = get_PF()?false:true; // JPO 02780 } else { 02781 jmp = get_SF()?true:false; // JP / JPE 02782 } 02783 } break; 02784 case 'S' : { jmp = get_SF()?true:false; // JS 02785 } break; 02786 case 'Z' : { jmp = get_ZF()?true:false; // JZ 02787 } break; 02788 } 02789 if (jmp) { 02790 pos = strchr(instu,'$'); 02791 if (pos) { 02792 pos = strchr(instu,'+'); 02793 if (pos) { 02794 strcpy(result,"(down)"); 02795 } else { 02796 strcpy(result,"(up)"); 02797 } 02798 } 02799 } else { 02800 sprintf(result,"(no jmp)"); 02801 } 02802 } 02803 return result; 02804 } 02805 02806 // data window 02807 void win_data_ui_down(int count) { 02808 if (count > 0) 02809 dataOfs += (unsigned)count * 16; 02810 } 02811 02812 void win_data_ui_up(int count) { 02813 if (count > 0) 02814 dataOfs -= (unsigned)count * 16; 02815 } 02816 02817 // code window 02818 void win_code_ui_down(int count) { 02819 if (dbg.win_code != NULL) { 02820 int y,x; 02821 02822 getmaxyx(dbg.win_code,y,x); 02823 02824 while (count-- > 0) { 02825 if (codeViewData.cursorPos < (y-1)) codeViewData.cursorPos++; 02826 else codeViewData.useEIP += codeViewData.firstInstSize; 02827 } 02828 } 02829 } 02830 02831 void win_code_ui_up(int count) { 02832 if (dbg.win_code != NULL) { 02833 int y,x; 02834 02835 getmaxyx(dbg.win_code,y,x); 02836 02837 (void)y; // SET, BUT UNUSED 02838 02839 while (count-- > 0) { 02840 if (codeViewData.cursorPos>0) 02841 codeViewData.cursorPos--; 02842 else { 02843 Bit32u newEIP = codeViewData.useEIP - 1; 02844 if(codeViewData.useEIP) { 02845 Bitu bytes = 0; 02846 char dline[200]; 02847 for (; bytes < 10; bytes++) { 02848 PhysPt start = (PhysPt)GetAddress(codeViewData.useCS,newEIP); 02849 Bitu size = DasmI386(dline, start, newEIP, cpu.code.big); 02850 if(codeViewData.useEIP == newEIP+size) break; 02851 newEIP--; 02852 } 02853 if (bytes>=10) newEIP = codeViewData.useEIP - 1; 02854 } 02855 codeViewData.useEIP = newEIP; 02856 } 02857 } 02858 } 02859 } 02860 02861 #ifdef WIN32 02862 extern "C" INPUT_RECORD * _pdcurses_hax_inputrecord(void); 02863 #endif 02864 02865 Bit32u DEBUG_CheckKeys(void) { 02866 Bits ret=0; 02867 bool numberrun = false; 02868 bool skipDraw = false; 02869 int key=getch(); 02870 02871 if (key == KEY_RESIZE) { 02872 #ifdef WIN32 /* BUG: pdcurses notifies us immediately upon getting a resize event but does not update it's 02873 internal structures to reflect the new console size. For example a Win32 console event 02874 reporting a change to 80x41 would still return 80x40 if we asked pdcurses right now. 02875 To make resizing the console window less painful, look at pdcurses internal structure 02876 directly instead. 02877 02878 Note that we need to call resize_term() or pdcurses will never notify us about console 02879 resize again. */ 02880 /* FIXME: Windows will notify us if the user enlarges the window vertically, but will NOT notify 02881 us if the user vertically shrinks the window (adds scrollbar instead). How do we disable 02882 that behavior? */ 02883 { 02884 INPUT_RECORD *r = _pdcurses_hax_inputrecord(); 02885 if (r->EventType == WINDOW_BUFFER_SIZE_EVENT) { 02886 resize_term(r->Event.WindowBufferSizeEvent.dwSize.Y, r->Event.WindowBufferSizeEvent.dwSize.X); 02887 } 02888 } 02889 #endif 02890 void DEBUG_GUI_OnResize(void); 02891 DEBUG_GUI_OnResize(); 02892 DEBUG_DrawScreen(); 02893 return 0; 02894 } 02895 02896 if (key >='1' && key <='5' && strlen(codeViewData.inputStr) == 0) { 02897 const Bit32s v[] ={5,500,1000,5000,10000}; 02898 CPU_Cycles= v[key - '1']; 02899 02900 skipFirstInstruction = true; 02901 02902 ret = (*cpudecoder)(); 02903 SetCodeWinStart(); 02904 02905 /* Setup variables so we end up at the proper ret processing */ 02906 numberrun = true; 02907 02908 // Don't redraw the screen if it's going to get redrawn immediately 02909 // afterwards, to avoid resetting oldregs. 02910 if (ret == (Bits)debugCallback) 02911 skipDraw = true; 02912 key = -1; 02913 } 02914 02915 if (key>0 || numberrun) { 02916 #if defined(WIN32) && defined(__PDCURSES__) 02917 switch (key) { 02918 case PADENTER: key=0x0A; break; 02919 case PADSLASH: key='/'; break; 02920 case PADSTAR: key='*'; break; 02921 case PADMINUS: key='-'; break; 02922 case PADPLUS: key='+'; break; 02923 case ALT_D: 02924 if (ungetch('D') != ERR) key=27; 02925 break; 02926 case ALT_E: 02927 if (ungetch('E') != ERR) key=27; 02928 break; 02929 case ALT_X: 02930 if (ungetch('X') != ERR) key=27; 02931 break; 02932 case ALT_B: 02933 if (ungetch('B') != ERR) key=27; 02934 break; 02935 case ALT_S: 02936 if (ungetch('S') != ERR) key=27; 02937 break; 02938 } 02939 #endif 02940 switch (toupper(key)) { 02941 case 27: // escape (a bit slow): Clears line. and processes alt commands. 02942 key=getch(); 02943 if(key < 0) { //Purely escape Clear line 02944 ClearInputLine(); 02945 break; 02946 } 02947 02948 switch(toupper(key)) { 02949 case 'D' : // ALT - D: DS:SI 02950 dataSeg = SegValue(ds); 02951 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_esi; 02952 else dataOfs = reg_si; 02953 break; 02954 case 'E' : //ALT - E: es:di 02955 dataSeg = SegValue(es); 02956 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_edi; 02957 else dataOfs = reg_di; 02958 break; 02959 case 'X': //ALT - X: ds:dx 02960 dataSeg = SegValue(ds); 02961 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_edx; 02962 else dataOfs = reg_dx; 02963 break; 02964 case 'B' : //ALT -B: es:bx 02965 dataSeg = SegValue(es); 02966 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_ebx; 02967 else dataOfs = reg_bx; 02968 break; 02969 case 'S': //ALT - S: ss:sp 02970 dataSeg = SegValue(ss); 02971 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_esp; 02972 else dataOfs = reg_sp; 02973 break; 02974 default: 02975 break; 02976 } 02977 break; 02978 case KEY_PPAGE: // page up 02979 switch (dbg.active_win) { 02980 case DBGBlock::WINI_CODE: 02981 if (dbg.win_code != NULL) { 02982 int w,h; 02983 02984 getmaxyx(dbg.win_code,h,w); 02985 win_code_ui_up(h-1); 02986 } 02987 break; 02988 case DBGBlock::WINI_DATA: 02989 if (dbg.win_data != NULL) { 02990 int w,h; 02991 02992 getmaxyx(dbg.win_data,h,w); 02993 win_data_ui_up(h); 02994 } 02995 break; 02996 case DBGBlock::WINI_OUT: 02997 if (dbg.win_out != NULL) { 02998 int w,h; 02999 03000 getmaxyx(dbg.win_out,h,w); 03001 DEBUG_RefreshPage(-h); 03002 } 03003 break; 03004 } 03005 break; 03006 03007 case KEY_NPAGE: // page down 03008 switch (dbg.active_win) { 03009 case DBGBlock::WINI_CODE: 03010 if (dbg.win_code != NULL) { 03011 int w,h; 03012 03013 getmaxyx(dbg.win_code,h,w); 03014 win_code_ui_down(h-1); 03015 } 03016 break; 03017 case DBGBlock::WINI_DATA: 03018 if (dbg.win_data != NULL) { 03019 int w,h; 03020 03021 getmaxyx(dbg.win_data,h,w); 03022 win_data_ui_down(h); 03023 } 03024 break; 03025 case DBGBlock::WINI_OUT: 03026 if (dbg.win_out != NULL) { 03027 int w,h; 03028 03029 getmaxyx(dbg.win_out,h,w); 03030 DEBUG_RefreshPage(h); 03031 } 03032 break; 03033 } 03034 break; 03035 03036 case KEY_DOWN: // down 03037 switch (dbg.active_win) { 03038 case DBGBlock::WINI_CODE: 03039 win_code_ui_down(1); 03040 break; 03041 case DBGBlock::WINI_DATA: 03042 win_data_ui_down(1); 03043 break; 03044 case DBGBlock::WINI_OUT: 03045 DEBUG_RefreshPage(1); 03046 break; 03047 } 03048 break; 03049 case KEY_UP: // up 03050 switch (dbg.active_win) { 03051 case DBGBlock::WINI_CODE: 03052 win_code_ui_up(1); 03053 break; 03054 case DBGBlock::WINI_DATA: 03055 win_data_ui_up(1); 03056 break; 03057 case DBGBlock::WINI_OUT: 03058 DEBUG_RefreshPage(-1); 03059 break; 03060 } 03061 break; 03062 03063 case KEY_HOME: // Home 03064 switch (dbg.active_win) { 03065 case DBGBlock::WINI_CODE: 03066 // and do what? 03067 break; 03068 case DBGBlock::WINI_DATA: 03069 // and do what? 03070 break; 03071 case DBGBlock::WINI_OUT: 03072 void DEBUG_ScrollHomeOutput(void); 03073 DEBUG_ScrollHomeOutput(); 03074 break; 03075 } 03076 break; 03077 03078 case KEY_END: // End 03079 switch (dbg.active_win) { 03080 case DBGBlock::WINI_CODE: 03081 // and do what? 03082 break; 03083 case DBGBlock::WINI_DATA: 03084 // and do what? 03085 break; 03086 case DBGBlock::WINI_OUT: 03087 void DEBUG_ScrollToEndOutput(void); 03088 DEBUG_ScrollToEndOutput(); 03089 break; 03090 } 03091 break; 03092 03093 case KEY_IC: // Insert: toggle insert/overwrite 03094 codeViewData.ovrMode = !codeViewData.ovrMode; 03095 break; 03096 case KEY_LEFT: // move to the left in command line 03097 if (codeViewData.inputPos > 0) codeViewData.inputPos--; 03098 break; 03099 case KEY_RIGHT: // move to the right in command line 03100 if (codeViewData.inputStr[codeViewData.inputPos]) codeViewData.inputPos++; 03101 break; 03102 case KEY_F(6): // previous command (f1-f4 generate rubbish at my place) 03103 case KEY_F(3): // previous command 03104 if (histBuffPos == histBuff.begin()) break; 03105 if (histBuffPos == histBuff.end()) { 03106 // copy inputStr to suspInputStr so we can restore it 03107 safe_strncpy(codeViewData.suspInputStr, codeViewData.inputStr, sizeof(codeViewData.suspInputStr)); 03108 } 03109 safe_strncpy(codeViewData.inputStr,(*--histBuffPos).c_str(),sizeof(codeViewData.inputStr)); 03110 codeViewData.inputPos = (int)strlen(codeViewData.inputStr); 03111 break; 03112 case KEY_F(7): // next command (f1-f4 generate rubbish at my place) 03113 case KEY_F(4): // next command 03114 if (histBuffPos == histBuff.end()) break; 03115 if (++histBuffPos != histBuff.end()) { 03116 safe_strncpy(codeViewData.inputStr,(*histBuffPos).c_str(),sizeof(codeViewData.inputStr)); 03117 } else { 03118 // copy suspInputStr back into inputStr 03119 safe_strncpy(codeViewData.inputStr, codeViewData.suspInputStr, sizeof(codeViewData.inputStr)); 03120 } 03121 codeViewData.inputPos = (int)strlen(codeViewData.inputStr); 03122 break; 03123 case KEY_F(5): // Run Program 03124 DrawRegistersUpdateOld(); 03125 debugging=false; 03126 DrawCode(); 03127 DrawInput(); 03128 logBuffSuppressConsole = false; 03129 if (logBuffSuppressConsoleNeedUpdate) { 03130 logBuffSuppressConsoleNeedUpdate = false; 03131 DEBUG_RefreshPage(0); 03132 } 03133 03134 Bits DEBUG_NullCPUCore(void); 03135 03136 CPU_Cycles = 1; 03137 inhibit_int_breakpoint = true; 03138 if (cpudecoder == DEBUG_NullCPUCore) 03139 ret = -1; /* DEBUG_Loop() must exit */ 03140 else 03141 ret = (*cpudecoder)(); 03142 03143 inhibit_int_breakpoint = false; 03144 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu); 03145 03146 skipFirstInstruction = true; // for heavy debugger 03147 CPU_Cycles = 1; 03148 03149 // ensure all breakpoints are activated 03150 CBreakpoint::ActivateBreakpoints(); 03151 03152 skipDraw = true; // don't update screen after this instruction 03153 03154 DOSBOX_SetNormalLoop(); 03155 break; 03156 case KEY_F(9): // Set/Remove Breakpoint 03157 if (CBreakpoint::IsBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs)) { 03158 if (CBreakpoint::DeleteBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs)) 03159 DEBUG_ShowMsg("DEBUG: Breakpoint deletion success.\n"); 03160 else 03161 DEBUG_ShowMsg("DEBUG: Failed to delete breakpoint.\n"); 03162 } 03163 else { 03164 CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false); 03165 DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X\n",codeViewData.cursorSeg,codeViewData.cursorOfs); 03166 } 03167 break; 03168 case KEY_F(10): // Step over inst 03169 DrawRegistersUpdateOld(); 03170 if (StepOver()) { 03171 mustCompleteInstruction = true; 03172 inhibit_int_breakpoint = true; 03173 skipFirstInstruction = true; // for heavy debugger 03174 CPU_Cycles = 1; 03175 ret=(*cpudecoder)(); 03176 inhibit_int_breakpoint = false; 03177 mustCompleteInstruction = false; 03178 03179 DOSBOX_SetNormalLoop(); 03180 03181 // ensure all breakpoints are activated 03182 CBreakpoint::ActivateBreakpoints(); 03183 skipDraw = true; 03184 break; 03185 } 03186 // If we aren't stepping over something, do a normal step. 03187 // NB: Fall-through 03188 case KEY_F(11): // trace into 03189 DrawRegistersUpdateOld(); 03190 exitLoop = false; 03191 skipFirstInstruction = true; // for heavy debugger 03192 mustCompleteInstruction = true; 03193 CPU_Cycles = 1; 03194 ret = (*cpudecoder)(); 03195 mustCompleteInstruction = false; 03196 SetCodeWinStart(); 03197 break; 03198 case 0x09: //TAB 03199 void DBGUI_NextWindow(void); 03200 DBGUI_NextWindow(); 03201 break; 03202 case 0x0A: //Parse typed Command 03203 if (codeViewData.inputPos > 0) { 03204 codeViewData.inputStr[MAXCMDLEN] = '\0'; 03205 if(ParseCommand(codeViewData.inputStr)) { 03206 char* cmd = ltrim(codeViewData.inputStr); 03207 if (histBuff.empty() || *--histBuff.end()!=cmd) 03208 histBuff.push_back(cmd); 03209 if (histBuff.size() > MAX_HIST_BUFFER) histBuff.pop_front(); 03210 histBuffPos = histBuff.end(); 03211 ClearInputLine(); 03212 } else { 03213 DEBUG_ShowMsg("*** Debugger command not recognized"); 03214 codeViewData.inputPos = (int)strlen(codeViewData.inputStr); 03215 } 03216 } 03217 break; 03218 case KEY_BACKSPACE: //backspace (linux) 03219 case 0x7f: // backspace in some terminal emulators (linux) 03220 case 0x08: // delete 03221 if (codeViewData.inputPos == 0) break; 03222 codeViewData.inputPos--; 03223 // fallthrough 03224 case KEY_DC: // delete character 03225 if ((codeViewData.inputPos<0) || (codeViewData.inputPos>=MAXCMDLEN)) break; 03226 if (codeViewData.inputStr[codeViewData.inputPos] != 0) { 03227 codeViewData.inputStr[MAXCMDLEN] = '\0'; 03228 for(char* p=&codeViewData.inputStr[codeViewData.inputPos];(*p=*(p+1));p++) {} 03229 } 03230 break; 03231 default: 03232 if ((key>=32) && (key<127)) { 03233 if ((codeViewData.inputPos<0) || (codeViewData.inputPos>=MAXCMDLEN)) break; 03234 codeViewData.inputStr[MAXCMDLEN] = '\0'; 03235 if (codeViewData.inputStr[codeViewData.inputPos] == 0) { 03236 codeViewData.inputStr[codeViewData.inputPos++] = char(key); 03237 codeViewData.inputStr[codeViewData.inputPos] = '\0'; 03238 } else if (!codeViewData.ovrMode) { 03239 int len = (int) strlen(codeViewData.inputStr); 03240 if (len < MAXCMDLEN) { 03241 for(len++;len>codeViewData.inputPos;len--) 03242 codeViewData.inputStr[len]=codeViewData.inputStr[len-1]; 03243 codeViewData.inputStr[codeViewData.inputPos++] = char(key); 03244 } 03245 } else { 03246 codeViewData.inputStr[codeViewData.inputPos++] = char(key); 03247 } 03248 } else if (key==killchar()) { 03249 ClearInputLine(); 03250 } 03251 break; 03252 } 03253 if (ret<0) return (Bit32u)ret; 03254 if (ret>0) { 03255 if (GCC_UNLIKELY(ret >= (Bits)CB_MAX)) 03256 ret = 0; 03257 else 03258 ret = (Bits)(*CallBack_Handlers[ret])(); 03259 if (ret) { 03260 exitLoop=true; 03261 CPU_Cycles=CPU_CycleLeft=0; 03262 return (Bit32u)ret; 03263 } 03264 } 03265 ret=0; 03266 if (!skipDraw) 03267 DEBUG_DrawScreen(); 03268 } 03269 return (Bit32u)ret; 03270 } 03271 03272 Bitu DEBUG_LastRunningUpdate = 0; 03273 03274 LoopHandler *DOSBOX_GetLoop(void); 03275 Bitu DEBUG_Loop(void); 03276 03277 void DEBUG_Wait(void) { 03278 while (DOSBOX_GetLoop() == DEBUG_Loop) 03279 DOSBOX_RunMachine(); 03280 } 03281 03282 Bits DEBUG_NullCPUCore(void) { 03283 return CBRET_NONE; 03284 } 03285 03286 void DEBUG_WaitNoExecute(void) { 03287 /* the caller uses this version to indicate a fatal error 03288 * in a condition where single-stepping or executing any 03289 * more x86 instructions is very unwise */ 03290 auto oldcore = cpudecoder; 03291 cpudecoder = DEBUG_NullCPUCore; 03292 DEBUG_Wait(); 03293 cpudecoder = oldcore; 03294 } 03295 03296 Bitu DEBUG_Loop(void) { 03297 if (debug_running) { 03298 Bitu now = SDL_GetTicks(); 03299 03300 if ((DEBUG_LastRunningUpdate + 33) < now) { 03301 DEBUG_LastRunningUpdate = now; 03302 SetCodeWinStart(); 03303 DEBUG_DrawScreen(); 03304 } 03305 03306 return old_loop(); 03307 } 03308 else { 03309 //TODO Disable sound 03310 GFX_Events(); 03311 // Interrupt started ? - then skip it 03312 Bit16u oldCS = SegValue(cs); 03313 Bit32u oldEIP = reg_eip; 03314 PIC_runIRQs(); 03315 SDL_Delay(1); 03316 if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) { 03317 CBreakpoint::AddBreakpoint(oldCS,oldEIP,true); 03318 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip); 03319 debugging=false; 03320 03321 logBuffSuppressConsole = false; 03322 if (logBuffSuppressConsoleNeedUpdate) { 03323 logBuffSuppressConsoleNeedUpdate = false; 03324 DEBUG_RefreshPage(0); 03325 } 03326 03327 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu); 03328 DOSBOX_SetNormalLoop(); 03329 DrawRegistersUpdateOld(); 03330 return 0; 03331 } 03332 03333 /* between DEBUG_Enable and DEBUG_Loop CS:EIP can change */ 03334 if (check_rescroll) { 03335 Bit16u ocs; 03336 Bit32u oip; 03337 int ocr; 03338 03339 check_rescroll = false; 03340 ocs = codeViewData.useCS; 03341 oip = codeViewData.useEIP; 03342 ocr = codeViewData.cursorPos; 03343 SetCodeWinStart(); 03344 if (ocs != codeViewData.useCS || 03345 oip != codeViewData.useEIP) { 03346 DEBUG_DrawScreen(); 03347 } 03348 else { 03349 /* SetCodeWinStart() resets cursor position */ 03350 codeViewData.cursorPos = ocr; 03351 } 03352 } 03353 03354 if (logBuffSuppressConsoleNeedUpdate) { 03355 logBuffSuppressConsoleNeedUpdate = false; 03356 DEBUG_RefreshPage(0); 03357 } 03358 03359 return DEBUG_CheckKeys(); 03360 } 03361 } 03362 03363 void DEBUG_FlushInput(void); 03364 03365 void DEBUG_Enable_Handler(bool pressed) { 03366 if (!pressed) 03367 return; 03368 03369 /* this command is now a toggle! */ 03370 /* However this should break back into the debugger if RUNWATCH is active */ 03371 if (debug_running) { 03372 debug_running = false; 03373 DrawRegistersUpdateOld(); 03374 SetCodeWinStart(); 03375 DEBUG_DrawScreen(); 03376 return; 03377 } 03378 else if (debugging) { 03379 DrawRegistersUpdateOld(); 03380 debugging=false; 03381 03382 logBuffSuppressConsole = false; 03383 if (logBuffSuppressConsoleNeedUpdate) { 03384 logBuffSuppressConsoleNeedUpdate = false; 03385 DEBUG_RefreshPage(0); 03386 } 03387 03388 void DEBUG_DrawScreen(void); 03389 DEBUG_DrawScreen(); 03390 03391 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip); 03392 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu); 03393 DOSBOX_SetNormalLoop(); 03394 GFX_SetTitle(-1,-1,-1,is_paused); 03395 return; 03396 } 03397 03398 static bool showhelp=false; 03399 03400 #if defined(MACOSX) || defined(LINUX) 03401 /* Mac OS X does not have a console for us to just allocate on a whim like Windows does. 03402 So the debugger interface is useless UNLESS the user has started us from a terminal 03403 (whether over SSH or from the Terminal app). */ 03404 bool allow = true; 03405 03406 if (!isatty(0) || !isatty(1) || !isatty(2)) 03407 allow = false; 03408 03409 if (!allow) { 03410 # if defined(MACOSX) 03411 LOG_MSG("Debugger in Mac OS X is not available unless you start DOSBox-X from a terminal or from the Terminal application"); 03412 # else 03413 LOG_MSG("Debugger is not available unless you start DOSBox-X from a terminal"); 03414 # endif 03415 return; 03416 } 03417 #endif 03418 03419 CPU_CycleLeft+=CPU_Cycles; 03420 CPU_Cycles=0; 03421 03422 logBuffSuppressConsole = true; 03423 03424 LoopHandler *ol = DOSBOX_GetLoop(); 03425 if (ol != DEBUG_Loop) old_loop = ol; 03426 03427 debugging=true; 03428 debug_running=false; 03429 check_rescroll=true; 03430 DrawRegistersUpdateOld(); 03431 DEBUG_SetupConsole(); 03432 DEBUG_FlushInput(); 03433 SetCodeWinStart(); 03434 DEBUG_DrawScreen(); 03435 DOSBOX_SetLoop(&DEBUG_Loop); 03436 mainMenu.get_item("mapper_debugger").check(true).refresh_item(mainMenu); 03437 if(!showhelp) { 03438 showhelp=true; 03439 DEBUG_ShowMsg("***| TYPE HELP (+ENTER) TO GET AN OVERVIEW OF ALL COMMANDS |***\n"); 03440 } 03441 KEYBOARD_ClrBuffer(); 03442 GFX_SetTitle(-1,-1,-1,false); 03443 } 03444 03445 void DEBUG_DrawScreen(void) { 03446 DrawData(); 03447 DrawCode(); 03448 DrawInput(); 03449 DrawRegisters(); 03450 DrawVariables(); 03451 } 03452 03453 static void DEBUG_RaiseTimerIrq(void) { 03454 PIC_ActivateIRQ(0); 03455 } 03456 03457 // Display the content of the MCB chain starting with the MCB at the specified segment. 03458 static void LogMCBChain(Bit16u mcb_segment) { 03459 DOS_MCB mcb(mcb_segment); 03460 char filename[9]; // 8 characters plus a terminating NUL 03461 const char *psp_seg_note; 03462 Bit16u DOS_dataOfs = static_cast<Bit16u>(dataOfs); //Realmode addressing only 03463 PhysPt dataAddr = PhysMake(dataSeg,DOS_dataOfs);// location being viewed in the "Data Overview" 03464 03465 // loop forever, breaking out of the loop once we've processed the last MCB 03466 while (true) { 03467 // verify that the type field is valid 03468 if (mcb.GetType()!=0x4d && mcb.GetType()!=0x5a) { 03469 DEBUG_ShowMsg("MCB chain broken at %04X:0000!",mcb_segment); 03470 return; 03471 } 03472 03473 mcb.GetFileName(filename); 03474 03475 // some PSP segment values have special meanings 03476 switch (mcb.GetPSPSeg()) { 03477 case MCB_FREE: 03478 psp_seg_note = "(free)"; 03479 break; 03480 case MCB_DOS: 03481 psp_seg_note = "(DOS)"; 03482 break; 03483 default: 03484 psp_seg_note = ""; 03485 } 03486 03487 DEBUG_ShowMsg(" %04X %12u %04X %-7s %s",mcb_segment,mcb.GetSize() << 4,mcb.GetPSPSeg(), psp_seg_note, filename); 03488 03489 // print a message if dataAddr is within this MCB's memory range 03490 PhysPt mcbStartAddr = PhysMake(mcb_segment+1,0); 03491 PhysPt mcbEndAddr = PhysMake(mcb_segment+1+mcb.GetSize(),0); 03492 if (dataAddr >= mcbStartAddr && dataAddr < mcbEndAddr) { 03493 DEBUG_ShowMsg(" (data addr %04hX:%04X is %u bytes past this MCB)",dataSeg,DOS_dataOfs,dataAddr - mcbStartAddr); 03494 } 03495 03496 // if we've just processed the last MCB in the chain, break out of the loop 03497 if (mcb.GetType()==0x5a) { 03498 break; 03499 } 03500 // else, move to the next MCB in the chain 03501 mcb_segment+=mcb.GetSize()+1; 03502 mcb.SetPt(mcb_segment); 03503 } 03504 } 03505 03506 #include "regionalloctracking.h" 03507 03508 extern bool dos_kernel_disabled; 03509 extern RegionAllocTracking rombios_alloc; 03510 03511 static void LogBIOSMem(void) { 03512 char tmp[192]; 03513 03514 DEBUG_BeginPagedContent(); 03515 03516 DEBUG_ShowMsg("BIOS memory blocks:"); 03517 DEBUG_ShowMsg("Region Status What"); 03518 for (auto i=rombios_alloc.alist.begin();i!=rombios_alloc.alist.end();i++) { 03519 sprintf(tmp,"%08lx-%08lx %s", 03520 (unsigned long)(i->start), 03521 (unsigned long)(i->end), 03522 i->free ? "FREE " : "ALLOC "); 03523 DEBUG_ShowMsg("%s %s",tmp,i->who.c_str()); 03524 } 03525 03526 DEBUG_EndPagedContent(); 03527 } 03528 03529 Bitu XMS_GetTotalHandles(void); 03530 bool XMS_GetHandleInfo(Bitu &phys_location,Bitu &size,Bitu &lockcount,bool &free,Bitu handle); 03531 03532 bool EMS_GetHandle(Bitu &size,PhysPt &addr,std::string &name,Bitu handle); 03533 const char *EMS_Type_String(void); 03534 Bitu EMS_Max_Handles(void); 03535 bool EMS_Active(void); 03536 03537 static void LogFNKEY(void) { 03538 DEBUG_BeginPagedContent(); 03539 03540 void DEBUG_INTDC_FnKeyMapInfo(void); 03541 DEBUG_INTDC_FnKeyMapInfo(); 03542 03543 DEBUG_EndPagedContent(); 03544 } 03545 03546 static void LogEMS(void) { 03547 Bitu h_size; 03548 PhysPt xh_addr; 03549 std::string h_name; 03550 03551 if (dos_kernel_disabled) { 03552 DEBUG_ShowMsg("Cannot enumerate EMS memory while DOS kernel is inactive."); 03553 return; 03554 } 03555 03556 if (!EMS_Active()) { 03557 DEBUG_ShowMsg("Cannot enumerate EMS memory while EMS is inactive."); 03558 return; 03559 } 03560 03561 DEBUG_BeginPagedContent(); 03562 03563 DEBUG_ShowMsg("EMS memory (type %s) handles:",EMS_Type_String()); 03564 DEBUG_ShowMsg("Handle Address Size (bytes) Name"); 03565 for (Bitu h=0;h < EMS_Max_Handles();h++) { 03566 if (EMS_GetHandle(/*&*/h_size,/*&*/xh_addr,/*&*/h_name,h)) { 03567 DEBUG_ShowMsg("%6lu %08lx %08lx %s", 03568 (unsigned long)h, 03569 (unsigned long)xh_addr, 03570 (unsigned long)h_size, 03571 h_name.c_str()); 03572 } 03573 } 03574 03575 bool EMS_GetMapping(Bitu &handle,Bit16u &log_page,Bitu ems_page); 03576 Bitu GetEMSPageFrameSegment(void); 03577 Bitu GetEMSPageFrameSize(void); 03578 03579 DEBUG_ShowMsg("EMS page frame 0x%08lx-0x%08lx", 03580 GetEMSPageFrameSegment()*16UL, 03581 (GetEMSPageFrameSegment()*16UL)+GetEMSPageFrameSize()-1UL); 03582 DEBUG_ShowMsg("Handle Page(p/l) Address"); 03583 03584 for (Bitu p=0;p < (GetEMSPageFrameSize() >> 14UL);p++) { 03585 Bit16u log_page; 03586 Bitu handle; 03587 03588 if (EMS_GetMapping(handle,log_page,p)) { 03589 char tmp[192] = {0}; 03590 03591 xh_addr = 0; 03592 h_size = 0; 03593 h_name.clear(); 03594 EMS_GetHandle(/*&*/h_size,/*&*/xh_addr,/*&*/h_name,handle); 03595 03596 if (xh_addr != 0) 03597 sprintf(tmp," virt -> %08lx-%08lx phys", 03598 (unsigned long)(xh_addr + ((PhysPt)log_page << 14u)), 03599 (unsigned long)(xh_addr + ((PhysPt)log_page << 14u) + (1u << 14u) - 1u)); 03600 03601 DEBUG_ShowMsg("%6lu %4lu/%4lu %08lx-%08lx%s",(unsigned long)handle, 03602 (unsigned long)p,(unsigned long)log_page, 03603 (GetEMSPageFrameSegment()*16UL)+(p << 14UL), 03604 (GetEMSPageFrameSegment()*16UL)+((p+1UL) << 14UL)-1, 03605 tmp); 03606 } 03607 else { 03608 DEBUG_ShowMsg("-- %4lu/ %08lx-%08lx",(unsigned long)p, 03609 (GetEMSPageFrameSegment()*16UL)+(p << 14UL), 03610 (GetEMSPageFrameSegment()*16UL)+((p+1UL) << 14UL)-1); 03611 } 03612 } 03613 03614 DEBUG_EndPagedContent(); 03615 } 03616 03617 static void LogXMS(void) { 03618 Bitu phys_location; 03619 Bitu lockcount; 03620 bool free; 03621 Bitu size; 03622 03623 if (dos_kernel_disabled) { 03624 DEBUG_ShowMsg("Cannot enumerate XMS memory while DOS kernel is inactive."); 03625 return; 03626 } 03627 03628 if (!XMS_Active()) { 03629 DEBUG_ShowMsg("Cannot enumerate XMS memory while XMS is inactive."); 03630 return; 03631 } 03632 03633 DEBUG_BeginPagedContent(); 03634 03635 DEBUG_ShowMsg("XMS memory handles:"); 03636 DEBUG_ShowMsg("Handle Status Location Size (bytes)"); 03637 for (Bitu h = 1; h < XMS_GetTotalHandles(); h++) { 03638 if (XMS_GetHandleInfo(/*&*/phys_location,/*&*/size,/*&*/lockcount,/*&*/free, h)) { 03639 DEBUG_ShowMsg("%6lu %s 0x%08lx %lu", 03640 (unsigned long)h, 03641 free ? "FREE " : "ALLOC ", 03642 (unsigned long)phys_location, 03643 (unsigned long)size << 10UL); /* KB -> bytes */ 03644 } 03645 } 03646 03647 DEBUG_EndPagedContent(); 03648 } 03649 03650 static void LogDOSKernMem(void) { 03651 char tmp[192]; 03652 03653 if (dos_kernel_disabled) { 03654 DEBUG_ShowMsg("Cannot enumerate DOS kernel memory while DOS kernel is inactive."); 03655 return; 03656 } 03657 03658 DEBUG_BeginPagedContent(); 03659 03660 DEBUG_ShowMsg("DOS kernel memory blocks:"); 03661 DEBUG_ShowMsg("Seg Size (bytes) What"); 03662 for (auto i=DOS_GetMemLog.begin();i!=DOS_GetMemLog.end();i++) { 03663 sprintf(tmp,"%04x %8lu ", 03664 (unsigned int)(i->segbase), 03665 (unsigned long)(i->pages << 4UL)); 03666 03667 DEBUG_ShowMsg("%s %s",tmp,i->who.c_str()); 03668 } 03669 03670 DEBUG_EndPagedContent(); 03671 } 03672 03673 // Display the content of all Memory Control Blocks. 03674 static void LogMCBS(void) 03675 { 03676 if (dos_kernel_disabled) { 03677 if (boothax == BOOTHAX_MSDOS) { 03678 if (guest_msdos_LoL == 0 || guest_msdos_mcb_chain == 0) { 03679 DEBUG_ShowMsg("Cannot enumerate MCB list while DOS kernel is inactive, and DOSBox-X has not yet determined the MCB list of the guest MS-DOS operating system"); 03680 return; 03681 } 03682 03683 DEBUG_BeginPagedContent(); 03684 03685 try { 03686 DEBUG_ShowMsg("MCB Seg Size (bytes) PSP Seg (notes) Filename"); 03687 DEBUG_ShowMsg("Conventional memory:"); 03688 LogMCBChain(guest_msdos_mcb_chain); 03689 } 03690 catch (GuestPageFaultException &pf) { 03691 (void)pf;//unused 03692 DEBUG_ShowMsg("(Enumeration caused page fault within the guest)"); 03693 } 03694 03695 DEBUG_EndPagedContent(); 03696 return; 03697 } 03698 else { 03699 DEBUG_ShowMsg("Cannot enumerate MCB list while DOS kernel is inactive."); 03700 return; 03701 } 03702 } 03703 03704 DEBUG_BeginPagedContent(); 03705 03706 DEBUG_ShowMsg("MCB Seg Size (bytes) PSP Seg (notes) Filename"); 03707 DEBUG_ShowMsg("Conventional memory:"); 03708 LogMCBChain(dos.firstMCB); 03709 03710 if (dos_infoblock.GetStartOfUMBChain() != 0xFFFF) { 03711 DEBUG_ShowMsg("Upper memory:"); 03712 LogMCBChain(dos_infoblock.GetStartOfUMBChain()); 03713 } 03714 03715 DEBUG_EndPagedContent(); 03716 } 03717 03718 static void LogGDT(void) 03719 { 03720 char out1[512]; 03721 Descriptor desc; 03722 Bitu length = cpu.gdt.GetLimit(); 03723 PhysPt address = cpu.gdt.GetBase(); 03724 PhysPt max = (PhysPt)(address + length); 03725 Bitu i = 0; 03726 03727 DEBUG_BeginPagedContent(); 03728 03729 DEBUG_ShowMsg("GDT Base:%08lX Limit:%08lX",(unsigned long)address,(unsigned long)length); 03730 while (address<max) { 03731 desc.Load(address); 03732 sprintf(out1,"%04X: b:%08lX type: %02X parbg",(int)(i<<3),(unsigned long)desc.GetBase(),desc.saved.seg.type); 03733 DEBUG_ShowMsg("%s",out1); 03734 sprintf(out1," l:%08lX dpl : %01X %1X%1X%1X%1X%1X",(unsigned long)desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.r,desc.saved.seg.big,desc.saved.seg.g); 03735 DEBUG_ShowMsg("%s",out1); 03736 address+=8; i++; 03737 } 03738 03739 DEBUG_EndPagedContent(); 03740 } 03741 03742 static void LogLDT(void) { 03743 char out1[512]; 03744 Descriptor desc; 03745 Bitu ldtSelector = cpu.gdt.SLDT(); 03746 if (!cpu.gdt.GetDescriptor(ldtSelector,desc)) return; 03747 Bitu length = desc.GetLimit(); 03748 PhysPt address = desc.GetBase(); 03749 PhysPt max = (PhysPt)(address + length); 03750 Bitu i = 0; 03751 03752 DEBUG_BeginPagedContent(); 03753 03754 DEBUG_ShowMsg("LDT Base:%08lX Limit:%08lX",(unsigned long)address,(unsigned long)length); 03755 while (address<max) { 03756 desc.Load(address); 03757 sprintf(out1,"%04X: b:%08lX type: %02X parbg",(int)((i<<3)|4),(unsigned long)desc.GetBase(),desc.saved.seg.type); 03758 DEBUG_ShowMsg("%s",out1); 03759 sprintf(out1," l:%08lX dpl : %01X %1X%1X%1X%1X%1X",(unsigned long)desc.GetLimit(),desc.saved.seg.dpl,desc.saved.seg.p,desc.saved.seg.avl,desc.saved.seg.r,desc.saved.seg.big,desc.saved.seg.g); 03760 DEBUG_ShowMsg("%s",out1); 03761 address+=8; i++; 03762 } 03763 03764 DEBUG_EndPagedContent(); 03765 } 03766 03767 static void LogIDT(void) { 03768 char out1[512]; 03769 Descriptor desc; 03770 Bitu address = 0; 03771 03772 DEBUG_BeginPagedContent(); 03773 03774 while (address<256*8) { 03775 if (cpu.idt.GetDescriptor(address,desc)) { 03776 sprintf(out1,"%04X: sel:%04X off:%02X",(unsigned int)(address/8),(int)desc.GetSelector(),(int)desc.GetOffset()); 03777 DEBUG_ShowMsg("%s",out1); 03778 } 03779 address+=8; 03780 } 03781 03782 DEBUG_EndPagedContent(); 03783 } 03784 03785 void LogPages(char* selname) { 03786 DEBUG_BeginPagedContent(); 03787 03788 if (paging.enabled) { 03789 char out1[512]; 03790 Bitu sel = GetHexValue(selname,selname); 03791 if ((sel==0x00) && ((*selname==0) || (*selname=='*'))) { 03792 for (unsigned int i=0; i<0xfffff; i++) { 03793 Bitu table_addr=((Bitu)paging.base.page<<12u)+(i >> 10u)*(Bitu)4u; 03794 X86PageEntry table; 03795 table.load=phys_readd((PhysPt)table_addr); 03796 if (table.block.p) { 03797 X86PageEntry entry; 03798 PhysPt entry_addr=((PhysPt)table.block.base<<12u)+(i & 0x3ffu)* 4u; 03799 entry.load=phys_readd(entry_addr); 03800 if (entry.block.p) { 03801 sprintf(out1,"page %05Xxxx -> %04Xxxx flags [uw] %x:%x::%x:%x [d=%x|a=%x]", 03802 i,entry.block.base,entry.block.us,table.block.us, 03803 entry.block.wr,table.block.wr,entry.block.d,entry.block.a); 03804 DEBUG_ShowMsg("%s",out1); 03805 } 03806 } 03807 } 03808 } else { 03809 Bitu table_addr=(paging.base.page<<12u)+(sel >> 10u)*4u; 03810 X86PageEntry table; 03811 table.load=phys_readd((PhysPt)table_addr); 03812 if (table.block.p) { 03813 X86PageEntry entry; 03814 Bitu entry_addr=((Bitu)table.block.base<<12u)+(sel & 0x3ffu)*4u; 03815 entry.load=phys_readd((PhysPt)entry_addr); 03816 sprintf(out1,"page %05lXxxx -> %04lXxxx flags [puw] %x:%x::%x:%x::%x:%x", 03817 (unsigned long)sel, 03818 (unsigned long)entry.block.base, 03819 entry.block.p,table.block.p,entry.block.us,table.block.us,entry.block.wr,table.block.wr); 03820 DEBUG_ShowMsg("%s",out1); 03821 } else { 03822 sprintf(out1,"pagetable %03X not present, flags [puw] %x::%x::%x", 03823 (int)(sel >> 10), 03824 (int)table.block.p, 03825 (int)table.block.us, 03826 (int)table.block.wr); 03827 DEBUG_ShowMsg("%s",out1); 03828 } 03829 } 03830 } 03831 03832 DEBUG_EndPagedContent(); 03833 } 03834 03835 const char *FPU_tag(unsigned int i) { 03836 switch (i) { 03837 case TAG_Valid: return "Valid"; 03838 case TAG_Zero: return "Zero"; 03839 case TAG_Weird: return "Weird"; 03840 case TAG_Empty: return "Empty"; 03841 } 03842 03843 return "?"; 03844 } 03845 03846 static void LogFPUInfo(void) { 03847 DEBUG_BeginPagedContent(); 03848 03849 DEBUG_ShowMsg("FPU TOP=%u",(unsigned int)fpu.top); 03850 03851 for (unsigned int i=0;i < 8;i++) { 03852 unsigned int adj = STV(i); 03853 03854 #if defined(HAS_LONG_DOUBLE)//probably shouldn't allow struct to change size based on this 03855 DEBUG_ShowMsg(" st(%u): %s val=%.9f",i,FPU_tag(fpu.tags[adj]),(double)fpu.regs_80[adj].v); 03856 #else 03857 DEBUG_ShowMsg(" st(%u): %s use80=%u val=%.9f",i,FPU_tag(fpu.tags[adj]),fpu.use80[adj],fpu.regs[adj].d); 03858 #endif 03859 } 03860 03861 DEBUG_EndPagedContent(); 03862 } 03863 03864 static void LogCPUInfo(void) { 03865 char out1[512]; 03866 03867 DEBUG_BeginPagedContent(); 03868 03869 sprintf(out1,"cr0:%08lX cr2:%08lX cr3:%08lX cpl=%lx", 03870 (unsigned long)cpu.cr0, 03871 (unsigned long)paging.cr2, 03872 (unsigned long)paging.cr3, 03873 (unsigned long)cpu.cpl); 03874 DEBUG_ShowMsg("%s",out1); 03875 sprintf(out1,"eflags:%08lX [vm=%x iopl=%x nt=%x]", 03876 (unsigned long)reg_flags, 03877 (int)(GETFLAG(VM)>>17), 03878 (int)(GETFLAG(IOPL)>>12), 03879 (int)(GETFLAG(NT)>>14)); 03880 DEBUG_ShowMsg("%s",out1); 03881 sprintf(out1,"GDT base=%08lX limit=%08lX", 03882 (unsigned long)cpu.gdt.GetBase(), 03883 (unsigned long)cpu.gdt.GetLimit()); 03884 DEBUG_ShowMsg("%s",out1); 03885 sprintf(out1,"IDT base=%08lX limit=%08lX", 03886 (unsigned long)cpu.idt.GetBase(), 03887 (unsigned long)cpu.idt.GetLimit()); 03888 DEBUG_ShowMsg("%s",out1); 03889 03890 Bitu sel=CPU_STR(); 03891 Descriptor desc; 03892 if (cpu.gdt.GetDescriptor(sel,desc)) { 03893 sprintf(out1,"TR selector=%04X, base=%08lX limit=%08lX*%X",(int)sel,(unsigned long)desc.GetBase(),(unsigned long)desc.GetLimit(),desc.saved.seg.g?0x4000:1); 03894 DEBUG_ShowMsg("%s",out1); 03895 } 03896 sel=CPU_SLDT(); 03897 if (cpu.gdt.GetDescriptor(sel,desc)) { 03898 sprintf(out1,"LDT selector=%04X, base=%08lX limit=%08lX*%X",(int)sel,(unsigned long)desc.GetBase(),(unsigned long)desc.GetLimit(),desc.saved.seg.g?0x4000:1); 03899 DEBUG_ShowMsg("%s",out1); 03900 } 03901 03902 DEBUG_EndPagedContent(); 03903 } 03904 03905 #if C_HEAVY_DEBUG 03906 static void LogInstruction(Bit16u segValue, Bit32u eipValue, ofstream& out) { 03907 static char empty[23] = { 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0 }; 03908 03909 PhysPt start = (PhysPt)GetAddress(segValue,eipValue); 03910 char dline[200];Bitu size; 03911 size = DasmI386(dline, start, reg_eip, cpu.code.big); 03912 char* res = empty; 03913 if (showExtend && (cpuLogType > 0) ) { 03914 res = AnalyzeInstruction(dline,false); 03915 if (!res || !(*res)) res = empty; 03916 Bitu reslen = strlen(res); 03917 if (reslen < 22) { 03918 for (Bitu i = 0; i < 22 - reslen; i++) res[reslen + i] = ' '; 03919 res[22] = 0; 03920 } 03921 } 03922 Bitu len = strlen(dline); 03923 if (len < 30) { 03924 for (Bitu i = 0; i < 30 - len; i++) dline[len + i] = ' '; 03925 dline[30] = 0; 03926 } 03927 03928 // Get register values 03929 03930 if(cpuLogType == 0) { 03931 out << setw(4) << SegValue(cs) << ":" << setw(4) << reg_eip << " " << dline; 03932 } else if (cpuLogType == 1) { 03933 out << setw(4) << SegValue(cs) << ":" << setw(8) << reg_eip << " " << dline << " " << res; 03934 } else if (cpuLogType == 2) { 03935 char ibytes[200]=""; char tmpc[200]; 03936 for (Bitu i=0; i<size; i++) { 03937 Bit8u value; 03938 if (mem_readb_checked((PhysPt)(start+i),&value)) sprintf(tmpc,"%s","?? "); 03939 else sprintf(tmpc,"%02X ",value); 03940 strcat(ibytes,tmpc); 03941 } 03942 len = strlen(ibytes); 03943 if (len < 21) { 03944 for (Bitu i = 0; i < 21 - len; i++) ibytes[len + i] = ' '; 03945 ibytes[21] = 0; 03946 } 03947 out << setw(4) << SegValue(cs) << ":" << setw(8) << reg_eip << " " << dline << " " << res << " " << ibytes; 03948 } 03949 03950 out << " EAX:" << setw(8) << reg_eax << " EBX:" << setw(8) << reg_ebx 03951 << " ECX:" << setw(8) << reg_ecx << " EDX:" << setw(8) << reg_edx 03952 << " ESI:" << setw(8) << reg_esi << " EDI:" << setw(8) << reg_edi 03953 << " EBP:" << setw(8) << reg_ebp << " ESP:" << setw(8) << reg_esp 03954 << " DS:" << setw(4) << SegValue(ds)<< " ES:" << setw(4) << SegValue(es); 03955 03956 if(cpuLogType == 0) { 03957 out << " SS:" << setw(4) << SegValue(ss) << " C" << (get_CF()>0) << " Z" << (get_ZF()>0) 03958 << " S" << (get_SF()>0) << " O" << (get_OF()>0) << " I" << GETFLAGBOOL(IF); 03959 } else { 03960 out << " FS:" << setw(4) << SegValue(fs) << " GS:" << setw(4) << SegValue(gs) 03961 << " SS:" << setw(4) << SegValue(ss) 03962 << " CF:" << (get_CF()>0) << " ZF:" << (get_ZF()>0) << " SF:" << (get_SF()>0) 03963 << " OF:" << (get_OF()>0) << " AF:" << (get_AF()>0) << " PF:" << (get_PF()>0) 03964 << " IF:" << GETFLAGBOOL(IF); 03965 } 03966 if(cpuLogType == 2) { 03967 out << " TF:" << GETFLAGBOOL(TF) << " VM:" << GETFLAGBOOL(VM) <<" FLG:" << setw(8) << reg_flags 03968 << " CR0:" << setw(8) << cpu.cr0; 03969 } 03970 out << endl; 03971 } 03972 #endif 03973 03974 #if 0 03975 // DEBUG.COM stuff 03976 03977 class DEBUG : public Program { 03978 public: 03979 DEBUG() { pDebugcom = this; active = false; }; 03980 ~DEBUG() { pDebugcom = 0; }; 03981 03982 bool IsActive() { return active; }; 03983 03984 void Run(void) 03985 { 03986 if(cmd->FindExist("/NOMOUSE",false)) { 03987 real_writed(0,0x33<<2,0); 03988 return; 03989 } 03990 03991 char filename[128]; 03992 char args[256+1]; 03993 03994 cmd->FindCommand(1,temp_line); 03995 safe_strncpy(filename,temp_line.c_str(),128); 03996 // Read commandline 03997 Bit16u i =2; 03998 args[0] = 0; 03999 for (;cmd->FindCommand(i++,temp_line)==true;) { 04000 strncat(args,temp_line.c_str(),256); 04001 strncat(args," ",256); 04002 } 04003 // Start new shell and execute prog 04004 active = true; 04005 // Save cpu state.... 04006 Bit16u oldcs = SegValue(cs); 04007 Bit32u oldeip = reg_eip; 04008 Bit16u oldss = SegValue(ss); 04009 Bit32u oldesp = reg_esp; 04010 04011 // Start shell 04012 DOS_Shell shell; 04013 shell.Execute(filename,args); 04014 04015 // set old reg values 04016 SegSet16(ss,oldss); 04017 reg_esp = oldesp; 04018 SegSet16(cs,oldcs); 04019 reg_eip = oldeip; 04020 }; 04021 04022 private: 04023 bool active; 04024 }; 04025 #endif 04026 04027 #if C_DEBUG 04028 extern bool debugger_break_on_exec; 04029 #endif 04030 04031 void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off) 04032 { 04033 #if C_DEBUG 04034 if (debugger_break_on_exec) { 04035 CBreakpoint::AddBreakpoint(seg,off,true); 04036 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip); 04037 debugger_break_on_exec = false; 04038 } 04039 #endif 04040 #if 0 04041 if (pDebugcom && pDebugcom->IsActive()) { 04042 CBreakpoint::AddBreakpoint(seg,off,true); 04043 CBreakpoint::ActivateBreakpointsExceptAt(SegPhys(cs)+reg_eip); 04044 pDebugcom = 0; 04045 }; 04046 #endif 04047 } 04048 04049 Bitu DEBUG_EnableDebugger(void) 04050 { 04051 exitLoop = true; 04052 04053 if (!debugging) 04054 DEBUG_Enable_Handler(true); 04055 04056 CPU_Cycles=CPU_CycleLeft=0; 04057 return 0; 04058 } 04059 04060 // INIT 04061 04062 void DBGBlock::set_data_view(unsigned int view) { 04063 void DrawBars(void); 04064 04065 if (data_view != view) { 04066 data_view = view; 04067 04068 if (win_data) wclear(win_data); 04069 04070 switch (view) { 04071 case DATV_SEGMENTED: 04072 win_title[DBGBlock::WINI_DATA] = "Data view (segmented)"; 04073 break; 04074 case DATV_VIRTUAL: 04075 win_title[DBGBlock::WINI_DATA] = "Data view (virtual)"; 04076 break; 04077 case DATV_PHYSICAL: 04078 win_title[DBGBlock::WINI_DATA] = "Data view (physical)"; 04079 break; 04080 } 04081 04082 DrawBars(); 04083 } 04084 } 04085 04086 void DEBUG_SetupConsole(void) { 04087 if (dbg.win_main == NULL) { 04088 LOG(LOG_MISC, LOG_DEBUG)("DEBUG_SetupConsole initializing GUI"); 04089 04090 dbg.set_data_view(DBGBlock::DATV_SEGMENTED); 04091 04092 #ifdef WIN32 04093 WIN32_Console(); 04094 #else 04095 tcgetattr(0,&consolesettings); 04096 #endif 04097 // dbg.active_win=3; 04098 /* Start the Debug Gui */ 04099 DBGUI_StartUp(); 04100 } 04101 } 04102 04103 void DEBUG_ShutDown(Section * /*sec*/) { 04104 CBreakpoint::DeleteAll(); 04105 CDebugVar::DeleteAll(); 04106 if (dbg.win_main != NULL) { 04107 LOG(LOG_MISC, LOG_DEBUG)("DEBUG_Shutdown freeing ncurses state"); 04108 curs_set(old_cursor_state); 04109 04110 void DEBUG_GUI_DestroySubWindows(void); 04111 DEBUG_GUI_DestroySubWindows(); 04112 04113 // if (dbg.win_main) delwin(dbg.win_main); 04114 dbg.win_main = NULL; 04115 04116 endwin(); 04117 04118 #ifndef WIN32 04119 tcsetattr(0,TCSANOW,&consolesettings); 04120 #endif 04121 } 04122 } 04123 04124 Bitu debugCallback; 04125 04126 void DEBUG_ReinitCallback(void) { 04127 /* this is REQUIRED after loading a custom BIOS */ 04128 debugCallback=CALLBACK_Allocate(); 04129 CALLBACK_Setup(debugCallback,DEBUG_EnableDebugger,CB_RETF,"debugger"); 04130 } 04131 04132 void DEBUG_Init() { 04133 DOSBoxMenu::item *item; 04134 04135 LOG(LOG_MISC, LOG_DEBUG)("Initializing debug system"); 04136 04137 /* Add some keyhandlers */ 04138 #if defined(MACOSX) 04139 // OSX NOTE: ALT-F12 to launch debugger. pause maps to F16 on macOS, 04140 // which is not easy to input on a modern mac laptop 04141 MAPPER_AddHandler(DEBUG_Enable_Handler,MK_f12,MMOD2,"debugger","Debugger", &item); 04142 #else 04143 MAPPER_AddHandler(DEBUG_Enable_Handler,MK_pause,MMOD2,"debugger","Debugger",&item); 04144 #endif 04145 item->set_text("Debugger"); 04146 /* Reset code overview and input line */ 04147 memset((void*)&codeViewData,0,sizeof(codeViewData)); 04148 /* Setup callback */ 04149 debugCallback=CALLBACK_Allocate(); 04150 CALLBACK_Setup(debugCallback,DEBUG_EnableDebugger,CB_RETF,"debugger"); 04151 04152 #if defined(MACOSX) || defined(LINUX) 04153 /* Mac OS X does not have a console for us to just allocate on a whim like Windows does. 04154 So the debugger interface is useless UNLESS the user has started us from a terminal 04155 (whether over SSH or from the Terminal app). 04156 04157 Linux/X11 also does not have a console we can allocate on a whim. You either run 04158 this program from XTerm for the debugger, or not. */ 04159 bool allow = true; 04160 04161 if (!isatty(0) || !isatty(1) || !isatty(2)) 04162 allow = false; 04163 04164 mainMenu.get_item("mapper_debugger").enable(allow).refresh_item(mainMenu); 04165 #endif 04166 04167 /* shutdown function */ 04168 AddExitFunction(AddExitFunctionFuncPair(DEBUG_ShutDown)); 04169 } 04170 04171 // DEBUGGING VAR STUFF 04172 04173 void CDebugVar::InsertVariable(char* name, PhysPt adr) 04174 { 04175 varList.push_back(new CDebugVar(name,adr)); 04176 } 04177 04178 void CDebugVar::DeleteAll(void) 04179 { 04180 std::vector<CDebugVar*>::iterator i; 04181 for(i=varList.begin(); i != varList.end(); ++i) { 04182 CDebugVar* bp = static_cast<CDebugVar*>(*i); 04183 delete bp; 04184 } 04185 (varList.clear)(); 04186 } 04187 04188 CDebugVar* CDebugVar::FindVar(PhysPt pt) 04189 { 04190 if (varList.empty()) return 0; 04191 04192 std::vector<CDebugVar*>::size_type s = varList.size(); 04193 for(std::vector<CDebugVar*>::size_type i = 0; i != s; i++) { 04194 CDebugVar* bp = static_cast<CDebugVar*>(varList[i]); 04195 if (bp->GetAdr() == pt) return bp; 04196 } 04197 return 0; 04198 } 04199 04200 bool CDebugVar::SaveVars(char* name) { 04201 if (varList.size() > 65535) return false; 04202 04203 FILE* f = fopen(name,"wb+"); 04204 if (!f) return false; 04205 04206 // write number of vars 04207 Bit16u num = (Bit16u)varList.size(); 04208 fwrite(&num,1,sizeof(num),f); 04209 04210 std::vector<CDebugVar*>::iterator i; 04211 CDebugVar* bp; 04212 for(i=varList.begin(); i != varList.end(); ++i) { 04213 bp = static_cast<CDebugVar*>(*i); 04214 // name 04215 fwrite(bp->GetName(),1,16,f); 04216 // adr 04217 PhysPt adr = bp->GetAdr(); 04218 fwrite(&adr,1,sizeof(adr),f); 04219 } 04220 fclose(f); 04221 return true; 04222 } 04223 04224 bool CDebugVar::LoadVars(char* name) 04225 { 04226 FILE* f = fopen(name,"rb"); 04227 if (!f) return false; 04228 04229 // read number of vars 04230 Bit16u num; 04231 if (fread(&num,sizeof(num),1,f) != 1) { 04232 fclose(f); 04233 return false; 04234 } 04235 04236 for (Bit16u i=0; i<num; i++) { 04237 char name2[16]; 04238 // name 04239 if (fread(name2,16,1,f) != 1) break; 04240 // adr 04241 PhysPt adr; 04242 if (fread(&adr,sizeof(adr),1,f) != 1) break; 04243 // insert 04244 InsertVariable(name2,adr); 04245 } 04246 fclose(f); 04247 return true; 04248 } 04249 04250 static void SaveMemory(Bit16u seg, Bit32u ofs1, Bit32u num) { 04251 FILE* f = fopen("MEMDUMP.TXT","wt"); 04252 if (!f) { 04253 DEBUG_ShowMsg("DEBUG: Memory dump failed.\n"); 04254 return; 04255 } 04256 04257 char buffer[128]; 04258 char temp[16]; 04259 04260 while (num>16) { 04261 sprintf(buffer,"%04X:%04X ",seg,ofs1); 04262 for (Bit16u x=0; x<16; x++) { 04263 Bit8u value; 04264 if (mem_readb_checked((PhysPt)GetAddress(seg,ofs1+x),&value)) sprintf(temp,"%s","?? "); 04265 else sprintf(temp,"%02X ",value); 04266 strcat(buffer,temp); 04267 } 04268 ofs1+=16; 04269 num-=16; 04270 04271 fprintf(f,"%s\n",buffer); 04272 } 04273 if (num>0) { 04274 sprintf(buffer,"%04X:%04X ",seg,ofs1); 04275 for (Bit16u x=0; x<num; x++) { 04276 Bit8u value; 04277 if (mem_readb_checked((PhysPt)GetAddress(seg,ofs1+x),&value)) sprintf(temp,"%s","?? "); 04278 else sprintf(temp,"%02X ",value); 04279 strcat(buffer,temp); 04280 } 04281 fprintf(f,"%s\n",buffer); 04282 } 04283 fclose(f); 04284 DEBUG_ShowMsg("DEBUG: Memory dump success.\n"); 04285 } 04286 04287 static void SaveMemoryBin(Bit16u seg, Bit32u ofs1, Bit32u num) { 04288 FILE* f = fopen("MEMDUMP.BIN","wb"); 04289 if (!f) { 04290 DEBUG_ShowMsg("DEBUG: Memory binary dump failed.\n"); 04291 return; 04292 } 04293 04294 for (Bit32u x = 0; x < num;x++) { 04295 Bit8u val; 04296 if (mem_readb_checked((PhysPt)GetAddress(seg,ofs1+x),&val)) val=0; 04297 fwrite(&val,1,1,f); 04298 } 04299 04300 fclose(f); 04301 DEBUG_ShowMsg("DEBUG: Memory dump binary success.\n"); 04302 } 04303 04304 static void OutputVecTable(char* filename) { 04305 FILE* f = fopen(filename, "wt"); 04306 if (!f) 04307 { 04308 DEBUG_ShowMsg("DEBUG: Output of interrupt vector table failed.\n"); 04309 return; 04310 } 04311 04312 for (unsigned int i=0; i<256; i++) 04313 fprintf(f,"INT %02X: %04X:%04X\n", i, mem_readw(i * 4u + 2u), mem_readw(i * 4u)); 04314 04315 fclose(f); 04316 DEBUG_ShowMsg("DEBUG: Interrupt vector table written to %s.\n", filename); 04317 } 04318 04319 #define DEBUG_VAR_BUF_LEN 16 04320 static void DrawVariables(void) { 04321 if (CDebugVar::varList.empty()) return; 04322 04323 char buffer[DEBUG_VAR_BUF_LEN]; 04324 std::vector<CDebugVar*>::size_type s = CDebugVar::varList.size(); 04325 bool windowchanges = false; 04326 04327 for(std::vector<CDebugVar*>::size_type i = 0; i != s; i++) { 04328 04329 if (i == 4*3) { 04330 /* too many variables */ 04331 break; 04332 } 04333 04334 CDebugVar *dv = static_cast<CDebugVar*>(CDebugVar::varList[i]); 04335 Bit16u value; 04336 bool varchanges = false; 04337 bool has_no_value = mem_readw_checked(dv->GetAdr(),&value); 04338 if (has_no_value) { 04339 snprintf(buffer,DEBUG_VAR_BUF_LEN, "%s", "??????"); 04340 dv->SetValue(false,0); 04341 varchanges = true; 04342 } else { 04343 if ( dv->HasValue() && dv->GetValue() == value) { 04344 //It already had a value and it didn't change (most likely case) 04345 } else { 04346 dv->SetValue(true,value); 04347 snprintf(buffer,DEBUG_VAR_BUF_LEN, "0x%04x", value); 04348 varchanges = true; 04349 } 04350 } 04351 04352 if (varchanges) { 04353 unsigned int y = (unsigned int)(i / 3u); 04354 unsigned int x = (i % 3u) * 26u; 04355 mvwprintw(dbg.win_var, (int)y, (int)x, dv->GetName()); 04356 mvwprintw(dbg.win_var, (int)y, ((int)x + DEBUG_VAR_BUF_LEN + 1) , buffer); 04357 windowchanges = true; //Something has changed in this window 04358 } 04359 } 04360 04361 if (windowchanges) wrefresh(dbg.win_var); 04362 } 04363 #undef DEBUG_VAR_BUF_LEN 04364 // HEAVY DEBUGGING STUFF 04365 04366 #if C_HEAVY_DEBUG 04367 04368 const Bit32u LOGCPUMAX = 20000; 04369 04370 static Bit32u logCount = 0; 04371 04372 struct TLogInst { 04373 Bit16u s_cs; 04374 Bit32u eip; 04375 Bit32u eax; 04376 Bit32u ebx; 04377 Bit32u ecx; 04378 Bit32u edx; 04379 Bit32u esi; 04380 Bit32u edi; 04381 Bit32u ebp; 04382 Bit32u esp; 04383 Bit16u s_ds; 04384 Bit16u s_es; 04385 Bit16u s_fs; 04386 Bit16u s_gs; 04387 Bit16u s_ss; 04388 bool c; 04389 bool z; 04390 bool s; 04391 bool o; 04392 bool a; 04393 bool p; 04394 bool i; 04395 char dline[31]; 04396 char res[23]; 04397 }; 04398 04399 TLogInst logInst[LOGCPUMAX]; 04400 04401 void DEBUG_HeavyLogInstruction(void) { 04402 04403 static char empty[23] = { 32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,0 }; 04404 04405 PhysPt start = (PhysPt)GetAddress(SegValue(cs),reg_eip); 04406 char dline[200]; 04407 DasmI386(dline, start, reg_eip, cpu.code.big); 04408 char* res = empty; 04409 if (showExtend) { 04410 res = AnalyzeInstruction(dline,false); 04411 if (!res || !(*res)) res = empty; 04412 Bitu reslen = strlen(res); 04413 if (reslen < 22) { 04414 for (Bitu i = 0; i < 22 - reslen; i++) res[reslen + i] = ' '; 04415 res[22] = 0; 04416 } 04417 } 04418 04419 Bitu len = strlen(dline); 04420 if (len < 30) for (Bitu i=0; i < 30-len; i++) dline[len+i] = ' '; 04421 dline[30] = 0; 04422 04423 TLogInst & inst = logInst[logCount]; 04424 strcpy(inst.dline,dline); 04425 inst.s_cs = SegValue(cs); 04426 inst.eip = reg_eip; 04427 strcpy(inst.res,res); 04428 inst.eax = reg_eax; 04429 inst.ebx = reg_ebx; 04430 inst.ecx = reg_ecx; 04431 inst.edx = reg_edx; 04432 inst.esi = reg_esi; 04433 inst.edi = reg_edi; 04434 inst.ebp = reg_ebp; 04435 inst.esp = reg_esp; 04436 inst.s_ds = SegValue(ds); 04437 inst.s_es = SegValue(es); 04438 inst.s_fs = SegValue(fs); 04439 inst.s_gs = SegValue(gs); 04440 inst.s_ss = SegValue(ss); 04441 inst.c = get_CF()>0; 04442 inst.z = get_ZF()>0; 04443 inst.s = get_SF()>0; 04444 inst.o = get_OF()>0; 04445 inst.a = get_AF()>0; 04446 inst.p = get_PF()>0; 04447 inst.i = GETFLAGBOOL(IF); 04448 04449 if (++logCount >= LOGCPUMAX) logCount = 0; 04450 } 04451 04452 void DEBUG_HeavyWriteLogInstruction(void) { 04453 if (!logHeavy) return; 04454 logHeavy = false; 04455 04456 DEBUG_ShowMsg("DEBUG: Creating cpu log LOGCPU_INT_CD.TXT\n"); 04457 04458 ofstream out("LOGCPU_INT_CD.TXT"); 04459 if (!out.is_open()) { 04460 DEBUG_ShowMsg("DEBUG: Failed.\n"); 04461 return; 04462 } 04463 out << hex << noshowbase << setfill('0') << uppercase; 04464 Bit32u startLog = logCount; 04465 do { 04466 // Write Instructions 04467 TLogInst & inst = logInst[startLog]; 04468 out << setw(4) << inst.s_cs << ":" << setw(8) << inst.eip << " " 04469 << inst.dline << " " << inst.res << " EAX:" << setw(8)<< inst.eax 04470 << " EBX:" << setw(8) << inst.ebx << " ECX:" << setw(8) << inst.ecx 04471 << " EDX:" << setw(8) << inst.edx << " ESI:" << setw(8) << inst.esi 04472 << " EDI:" << setw(8) << inst.edi << " EBP:" << setw(8) << inst.ebp 04473 << " ESP:" << setw(8) << inst.esp << " DS:" << setw(4) << inst.s_ds 04474 << " ES:" << setw(4) << inst.s_es<< " FS:" << setw(4) << inst.s_fs 04475 << " GS:" << setw(4) << inst.s_gs<< " SS:" << setw(4) << inst.s_ss 04476 << " CF:" << inst.c << " ZF:" << inst.z << " SF:" << inst.s 04477 << " OF:" << inst.o << " AF:" << inst.a << " PF:" << inst.p 04478 << " IF:" << inst.i << endl; 04479 04480 /* fprintf(f,"%04X:%08X %s %s EAX:%08X EBX:%08X ECX:%08X EDX:%08X ESI:%08X EDI:%08X EBP:%08X ESP:%08X DS:%04X ES:%04X FS:%04X GS:%04X SS:%04X CF:%01X ZF:%01X SF:%01X OF:%01X AF:%01X PF:%01X IF:%01X\n", 04481 logInst[startLog].s_cs,logInst[startLog].eip,logInst[startLog].dline,logInst[startLog].res,logInst[startLog].eax,logInst[startLog].ebx,logInst[startLog].ecx,logInst[startLog].edx,logInst[startLog].esi,logInst[startLog].edi,logInst[startLog].ebp,logInst[startLog].esp, 04482 logInst[startLog].s_ds,logInst[startLog].s_es,logInst[startLog].s_fs,logInst[startLog].s_gs,logInst[startLog].s_ss, 04483 logInst[startLog].c,logInst[startLog].z,logInst[startLog].s,logInst[startLog].o,logInst[startLog].a,logInst[startLog].p,logInst[startLog].i);*/ 04484 if (++startLog >= LOGCPUMAX) startLog = 0; 04485 } while (startLog != logCount); 04486 04487 out.close(); 04488 DEBUG_ShowMsg("DEBUG: Done.\n"); 04489 } 04490 04491 bool DEBUG_HeavyIsBreakpoint(void) { 04492 if (cpuLog) { 04493 if (cpuLogCounter>0) { 04494 LogInstruction(SegValue(cs),reg_eip,cpuLogFile); 04495 cpuLogCounter--; 04496 } 04497 if (cpuLogCounter<=0) { 04498 cpuLogFile.flush(); 04499 cpuLogFile.close(); 04500 DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT created\n"); 04501 cpuLog = false; 04502 DEBUG_EnableDebugger(); 04503 return true; 04504 } 04505 } 04506 // LogInstruction 04507 if (logHeavy) DEBUG_HeavyLogInstruction(); 04508 if (zeroProtect) { 04509 static Bitu zero_count = 0; 04510 Bit32u value=0; 04511 if (!mem_readd_checked(SegPhys(cs)+reg_eip,&value)) { 04512 if (value == 0) zero_count++; 04513 else zero_count = 0; 04514 } 04515 if (GCC_UNLIKELY(zero_count == 10)) E_Exit("running zeroed code"); 04516 } 04517 04518 if (skipFirstInstruction) { 04519 skipFirstInstruction = false; 04520 return false; 04521 } 04522 if (CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) { 04523 return true; 04524 } 04525 return false; 04526 } 04527 04528 /* this is for the BIOS, to stop the log upon BIOS POST. */ 04529 void DEBUG_StopLog(void) { 04530 if (cpuLog) { 04531 cpuLogCounter = 0; 04532 cpuLogFile.close(); 04533 DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT stopped\n"); 04534 cpuLog = false; 04535 } 04536 } 04537 04538 #endif // HEAVY DEBUG 04539 04540 04541 #endif // DEBUG 04542 04543