DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/debug/debug.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  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
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #include "dosbox.h"
00021 #if C_DEBUG
00022 
00023 #include <string.h>
00024 #include <list>
00025 #include <ctype.h>
00026 #include <fstream>
00027 #include <iomanip>
00028 #include <string>
00029 #include <sstream>
00030 using namespace std;
00031 
00032 #include "debug.h"
00033 #include "cross.h" //snprintf
00034 #include "cpu.h"
00035 #include "video.h"
00036 #include "pic.h"
00037 #include "mapper.h"
00038 #include "cpu.h"
00039 #include "callback.h"
00040 #include "inout.h"
00041 #include "mixer.h"
00042 #include "timer.h"
00043 #include "paging.h"
00044 #include "support.h"
00045 #include "shell.h"
00046 #include "programs.h"
00047 #include "debug_inc.h"
00048 #include "../cpu/lazyflags.h"
00049 #include "keyboard.h"
00050 #include "setup.h"
00051 
00052 #ifdef WIN32
00053 void WIN32_Console();
00054 #else
00055 #include <termios.h>
00056 #include <unistd.h>
00057 static struct termios consolesettings;
00058 #endif
00059 int old_cursor_state;
00060 
00061 extern bool logBuffSuppressConsole;
00062 extern bool logBuffSuppressConsoleNeedUpdate;
00063 
00064 // Forwards
00065 static void DrawCode(void);
00066 static void DrawInput(void);
00067 static void DEBUG_RaiseTimerIrq(void);
00068 static void SaveMemory(Bit16u seg, Bit32u ofs1, Bit32u num);
00069 static void SaveMemoryBin(Bit16u seg, Bit32u ofs1, Bit32u num);
00070 static void LogMCBS(void);
00071 static void LogGDT(void);
00072 static void LogLDT(void);
00073 static void LogIDT(void);
00074 static void LogXMS(void);
00075 static void LogEMS(void);
00076 static void LogPages(char* selname);
00077 static void LogCPUInfo(void);
00078 static void OutputVecTable(char* filename);
00079 static void DrawVariables(void);
00080 static void LogDOSKernMem(void);
00081 static void LogBIOSMem(void);
00082 
00083 void DEBUG_DrawInput(void) {
00084     DrawInput();
00085 }
00086 
00087 bool XMS_Active(void);
00088 
00089 Bitu XMS_GetTotalHandles(void);
00090 bool XMS_GetHandleInfo(Bitu &phys_location,Bitu &size,Bitu &lockcount,bool &free,Bitu handle);
00091 
00092 LoopHandler *old_loop = NULL;
00093 
00094 char* AnalyzeInstruction(char* inst, bool saveSelector);
00095 Bit32u GetHexValue(char* str, char*& hex);
00096 
00097 #if 0
00098 class DebugPageHandler : public PageHandler {
00099 public:
00100         Bitu readb(PhysPt /*addr*/) {
00101         }
00102         Bitu readw(PhysPt /*addr*/) {
00103         }
00104         Bitu readd(PhysPt /*addr*/) {
00105         }
00106         void writeb(PhysPt /*addr*/,Bitu /*val*/) {
00107         }
00108         void writew(PhysPt /*addr*/,Bitu /*val*/) {
00109         }
00110         void writed(PhysPt /*addr*/,Bitu /*val*/) {
00111         }
00112 };
00113 #endif
00114 
00115 
00116 class DEBUG;
00117 
00118 //DEBUG*        pDebugcom       = 0;
00119 bool    exitLoop        = false;
00120 
00121 
00122 // Heavy Debugging Vars for logging
00123 #if C_HEAVY_DEBUG
00124 static ofstream         cpuLogFile;
00125 static bool             cpuLog                  = false;
00126 static int              cpuLogCounter   = 0;
00127 static int              cpuLogType              = 1;    // log detail
00128 static bool zeroProtect = false;
00129 bool    logHeavy        = false;
00130 #endif
00131 
00132 
00133 
00134 static struct  {
00135         Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
00136 } oldregs;
00137 
00138 static char curSelectorName[3] = { 0,0,0 };
00139 
00140 static Segment oldsegs[6];
00141 static Bitu oldflags,oldcpucpl;
00142 DBGBlock dbg;
00143 extern Bitu cycle_count;
00144 static bool debugging = false;
00145 static bool debug_running = false;
00146 static bool check_rescroll = false;
00147 
00148 bool IsDebuggerActive(void) {
00149     return debugging;
00150 }
00151 
00152 static void SetColor(Bitu test) {
00153         if (test) {
00154                 if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
00155         } else {
00156                 if (has_colors()) { wattrset(dbg.win_reg,0);}
00157         }
00158 }
00159 
00160 #define MAXCMDLEN 254 
00161 struct SCodeViewData {  
00162         int     cursorPos;
00163         Bit16u  firstInstSize;
00164         Bit16u  useCS;
00165         Bit32u  useEIPlast, useEIPmid;
00166         Bit32u  useEIP;
00167         Bit16u  cursorSeg;
00168         Bit32u  cursorOfs;
00169         bool    ovrMode;
00170         char    inputStr[MAXCMDLEN+1];
00171         char    suspInputStr[MAXCMDLEN+1];
00172         int     inputPos;
00173 } codeViewData;
00174 
00175 static Bit16u  dataSeg;
00176 static Bit32u  dataOfs;
00177 static bool    showExtend = true;
00178 
00179 static void ClearInputLine(void) {
00180         codeViewData.inputStr[0] = 0;
00181         codeViewData.inputPos = 0;
00182 }
00183 
00184 // History stuff
00185 #define MAX_HIST_BUFFER 50
00186 static list<string> histBuff;
00187 static list<string>::iterator histBuffPos = histBuff.end();
00188 
00189 /***********/
00190 /* Helpers */
00191 /***********/
00192 
00193 static const Bit64u mem_no_address = (Bit64u)(~0ULL);
00194 
00195 Bit64u LinMakeProt(Bit16u selector, Bit32u offset)
00196 {
00197         Descriptor desc;
00198 
00199     if (cpu.gdt.GetDescriptor(selector,desc)) {
00200         if (selector >= 8 && desc.Type() != 0) {
00201             if (offset <= desc.GetLimit())
00202                 return desc.GetBase()+offset;
00203         }
00204     }
00205 
00206         return mem_no_address;
00207 }
00208 
00209 Bit64u GetAddress(Bit16u seg, Bit32u offset)
00210 {
00211         if (cpu.pmode && !(reg_flags & FLAG_VM))
00212         return LinMakeProt(seg,offset);
00213 
00214         if (seg==SegValue(cs)) return SegPhys(cs)+offset;
00215         return ((Bit64u)seg<<4u)+offset;
00216 }
00217 
00218 static char empty_sel[] = { ' ',' ',0 };
00219 
00220 bool GetDescriptorInfo(char* selname, char* out1, char* out2)
00221 {
00222         Bitu sel;
00223         Descriptor desc;
00224 
00225         if (strstr(selname,"cs") || strstr(selname,"CS")) sel = SegValue(cs);
00226         else if (strstr(selname,"ds") || strstr(selname,"DS")) sel = SegValue(ds);
00227         else if (strstr(selname,"es") || strstr(selname,"ES")) sel = SegValue(es);
00228         else if (strstr(selname,"fs") || strstr(selname,"FS")) sel = SegValue(fs);
00229         else if (strstr(selname,"gs") || strstr(selname,"GS")) sel = SegValue(gs);
00230         else if (strstr(selname,"ss") || strstr(selname,"SS")) sel = SegValue(ss);
00231         else {
00232                 sel = GetHexValue(selname,selname);
00233                 if (*selname==0) selname=empty_sel;
00234         }
00235         if (cpu.gdt.GetDescriptor(sel,desc)) {
00236                 switch (desc.Type()) {
00237                         case DESC_TASK_GATE:
00238                                 sprintf(out1,"%s: s:%08lX type:%02X p",selname,(unsigned long)desc.GetSelector(),(int)desc.saved.gate.type);
00239                                 sprintf(out2,"    TaskGate   dpl : %01X %1X",desc.saved.gate.dpl,desc.saved.gate.p);
00240                                 return true;
00241                         case DESC_LDT:
00242                         case DESC_286_TSS_A:
00243                         case DESC_286_TSS_B:
00244                         case DESC_386_TSS_A:
00245                         case DESC_386_TSS_B:
00246                                 sprintf(out1,"%s: b:%08lX type:%02X pag",selname,(unsigned long)desc.GetBase(),(int)desc.saved.seg.type);
00247                                 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);
00248                                 return true;
00249                         case DESC_286_CALL_GATE:
00250                         case DESC_386_CALL_GATE:
00251                                 sprintf(out1,"%s: s:%08lX type:%02X p params: %02X",selname,(unsigned long)desc.GetSelector(),desc.saved.gate.type,desc.saved.gate.paramcount);
00252                                 sprintf(out2,"    o:%08lX dpl : %01X %1X",(unsigned long)desc.GetOffset(),desc.saved.gate.dpl,desc.saved.gate.p);
00253                                 return true;
00254                         case DESC_286_INT_GATE:
00255                         case DESC_286_TRAP_GATE:
00256                         case DESC_386_INT_GATE:
00257                         case DESC_386_TRAP_GATE:
00258                                 sprintf(out1,"%s: s:%08lX type:%02X p",selname,(unsigned long)desc.GetSelector(),desc.saved.gate.type);
00259                                 sprintf(out2,"    o:%08lX dpl : %01X %1X",(unsigned long)desc.GetOffset(),desc.saved.gate.dpl,desc.saved.gate.p);
00260                                 return true;
00261                 }
00262                 sprintf(out1,"%s: b:%08lX type:%02X parbg",selname,(unsigned long)desc.GetBase(),desc.saved.seg.type);
00263                 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);
00264                 return true;
00265         } else {
00266                 strcpy(out1,"                                  ");
00267                 strcpy(out2,"                                  ");
00268         }
00269         return false;
00270 }
00271 
00272 /********************/
00273 /* DebugVar   stuff */
00274 /********************/
00275 
00276 class CDebugVar
00277 {
00278 public:
00279         CDebugVar(char* _name, PhysPt _adr) { adr=_adr; safe_strncpy(name,_name,16); };
00280         
00281         char*   GetName(void) { return name; };
00282         PhysPt  GetAdr (void) { return adr;  };
00283 
00284 private:
00285         PhysPt  adr;
00286         char    name[16];
00287 
00288 public: 
00289         static void                     InsertVariable  (char* name, PhysPt adr);
00290         static CDebugVar*       FindVar                 (PhysPt adr);
00291         static void                     DeleteAll               ();
00292         static bool                     SaveVars                (char* name);
00293         static bool                     LoadVars                (char* name);
00294 
00295         static std::list<CDebugVar*>    varList;
00296 };
00297 
00298 std::list<CDebugVar*> CDebugVar::varList;
00299 
00300 
00301 /********************/
00302 /* Breakpoint stuff */
00303 /********************/
00304 
00305 bool skipFirstInstruction = false;
00306 
00307 enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT, BKPNT_MEMORY, BKPNT_MEMORY_PROT, BKPNT_MEMORY_LINEAR };
00308 
00309 #define BPINT_ALL 0x100
00310 
00311 class CBreakpoint
00312 {
00313 public:
00314 
00315         CBreakpoint(void);
00316         void                                    SetAddress              (Bit16u seg, Bit32u off)        { location = (PhysPt)GetAddress(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; };
00317         void                                    SetAddress              (PhysPt adr)                            { location = adr;                               type = BKPNT_PHYSICAL; };
00318         void                                    SetInt                  (Bit8u _intNr, Bit16u ah)       { intNr = _intNr, ahValue = ah; type = BKPNT_INTERRUPT; };
00319         void                                    SetOnce                 (bool _once)                            { once = _once; };
00320         void                                    SetType                 (EBreakpoint _type)                     { type = _type; };
00321         void                                    SetValue                (Bit8u value)                           { ahValue = value; };
00322 
00323         bool                                    IsActive                (void)                                          { return active; };
00324         void                                    Activate                (bool _active);
00325 
00326         EBreakpoint                             GetType                 (void)                                          { return type; };
00327         bool                                    GetOnce                 (void)                                          { return once; };
00328         PhysPt                                  GetLocation             (void)                                          { if (GetType()!=BKPNT_INTERRUPT)       return location;        else return 0; };
00329         Bit16u                                  GetSegment              (void)                                          { return segment; };
00330         Bit32u                                  GetOffset               (void)                                          { return offset; };
00331         Bit8u                                   GetIntNr                (void)                                          { if (GetType()==BKPNT_INTERRUPT)       return intNr;           else return 0; };
00332         Bit16u                                  GetValue                (void)                                          { if (GetType()!=BKPNT_PHYSICAL)        return ahValue;         else return 0; };
00333 
00334         // statics
00335         static CBreakpoint*             AddBreakpoint           (Bit16u seg, Bit32u off, bool once);
00336         static CBreakpoint*             AddIntBreakpoint        (Bit8u intNum, Bit16u ah, bool once);
00337         static CBreakpoint*             AddMemBreakpoint        (Bit16u seg, Bit32u off);
00338         static void                             ActivateBreakpoints     (PhysPt adr, bool activate);
00339         static bool                             CheckBreakpoint         (PhysPt adr);
00340         static bool                             CheckBreakpoint         (Bitu seg, Bitu off);
00341         static bool                             CheckIntBreakpoint      (PhysPt adr, Bit8u intNr, Bit16u ahValue);
00342         static bool                             IsBreakpoint            (PhysPt where);
00343         static bool                             IsBreakpointDrawn       (PhysPt where);
00344         static bool                             DeleteBreakpoint        (PhysPt where);
00345         static bool                             DeleteByIndex           (Bit16u index);
00346         static void                             DeleteAll                       (void);
00347         static void                             ShowList                        (void);
00348 
00349 
00350 private:
00351         EBreakpoint     type;
00352         // Physical
00353         PhysPt          location;
00354         Bit8u           oldData;
00355         Bit16u          segment;
00356         Bit32u          offset;
00357         // Int
00358         Bit8u           intNr;
00359         Bit16u          ahValue;
00360         // Shared
00361         bool            active;
00362         bool            once;
00363 
00364         static std::list<CBreakpoint*>  BPoints;
00365 public:
00366         static CBreakpoint*                             ignoreOnce;
00367 };
00368 
00369 CBreakpoint::CBreakpoint(void):type(BKPNT_UNKNOWN),location(0),segment(0),offset(0),intNr(0),ahValue(0),active(false),once(false) { }
00370 
00371 void CBreakpoint::Activate(bool _active)
00372 {
00373 #if !C_HEAVY_DEBUG
00374         if (GetType()==BKPNT_PHYSICAL) {
00375                 if (_active) {
00376                         // Set 0xCC and save old value
00377                         Bit8u data = mem_readb(location);
00378                         if (data!=0xCC) {
00379                                 oldData = data;
00380                                 mem_writeb(location,0xCC);
00381                         };
00382                 } else {
00383                         // Remove 0xCC and set old value
00384                         if (mem_readb (location)==0xCC) {
00385                                 mem_writeb(location,oldData);
00386                         };
00387                 }
00388         }
00389 #endif
00390         active = _active;
00391 }
00392 
00393 // Statics
00394 std::list<CBreakpoint*> CBreakpoint::BPoints;
00395 CBreakpoint*                    CBreakpoint::ignoreOnce = 0;
00396 Bitu                                    ignoreAddressOnce = 0;
00397 
00398 CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once)
00399 {
00400         CBreakpoint* bp = new CBreakpoint();
00401         bp->SetAddress          (seg,off);
00402         bp->SetOnce                     (once);
00403         BPoints.push_front      (bp);
00404         return bp;
00405 }
00406 
00407 CBreakpoint* CBreakpoint::AddIntBreakpoint(Bit8u intNum, Bit16u ah, bool once)
00408 {
00409         CBreakpoint* bp = new CBreakpoint();
00410         bp->SetInt                      (intNum,ah);
00411         bp->SetOnce                     (once);
00412         BPoints.push_front      (bp);
00413         return bp;
00414 }
00415 
00416 CBreakpoint* CBreakpoint::AddMemBreakpoint(Bit16u seg, Bit32u off)
00417 {
00418         CBreakpoint* bp = new CBreakpoint();
00419         bp->SetAddress          (seg,off);
00420         bp->SetOnce                     (false);
00421         bp->SetType                     (BKPNT_MEMORY);
00422         BPoints.push_front      (bp);
00423         return bp;
00424 }
00425 
00426 void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate)
00427 {
00428         // activate all breakpoints
00429         std::list<CBreakpoint*>::iterator i;
00430         CBreakpoint* bp;
00431         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00432                 bp = (*i);
00433                 // Do not activate, when bp is an actual address
00434                 if (activate && (bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
00435                         // Do not activate :)
00436                         continue;
00437                 }
00438                 bp->Activate(activate); 
00439         }
00440 }
00441 
00442 bool CBreakpoint::CheckBreakpoint(Bitu seg, Bitu off)
00443 // Checks if breakpoint is valid and should stop execution
00444 {
00445         if ((ignoreAddressOnce!=0) && (GetAddress(seg,off)==ignoreAddressOnce)) {
00446                 ignoreAddressOnce = 0;
00447                 return false;
00448         } else
00449                 ignoreAddressOnce = 0;
00450 
00451         // Search matching breakpoint
00452         std::list<CBreakpoint*>::iterator i;
00453         CBreakpoint* bp;
00454         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00455                 bp = (*i);
00456                 if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetSegment()==seg) && (bp->GetOffset()==off)) {
00457                         // Ignore Once ?
00458                         if (ignoreOnce==bp) {
00459                                 ignoreOnce=0;
00460                                 bp->Activate(true);
00461                                 return false;
00462                         };
00463                         // Found, 
00464                         if (bp->GetOnce()) {
00465                                 // delete it, if it should only be used once
00466                                 (BPoints.erase)(i);
00467                                 bp->Activate(false);
00468                                 delete bp;
00469                         } else {
00470                                 ignoreOnce = bp;
00471                         };
00472                         return true;
00473                 } 
00474 #if C_HEAVY_DEBUG
00475                 // Memory breakpoint support
00476                 else if (bp->IsActive()) {
00477                         if ((bp->GetType()==BKPNT_MEMORY) || (bp->GetType()==BKPNT_MEMORY_PROT) || (bp->GetType()==BKPNT_MEMORY_LINEAR)) {
00478                                 // Watch Protected Mode Memoryonly in pmode
00479                                 if (bp->GetType()==BKPNT_MEMORY_PROT) {
00480                                         // Check if pmode is active
00481                                         if (!cpu.pmode) return false;
00482                                         // Check if descriptor is valid
00483                                         Descriptor desc;
00484                                         if (!cpu.gdt.GetDescriptor(bp->GetSegment(),desc)) return false;
00485                                         if (desc.GetLimit()==0) return false;
00486                                 }
00487 
00488                                 Bitu address; 
00489                                 if (bp->GetType()==BKPNT_MEMORY_LINEAR) address = bp->GetOffset();
00490                                 else address = (Bitu)GetAddress(bp->GetSegment(),bp->GetOffset());
00491                                 Bit8u value=0;
00492                                 if (mem_readb_checked(address,&value)) return false;
00493                                 if (bp->GetValue() != value) {
00494                                         // Yup, memory value changed
00495                                         DEBUG_ShowMsg("DEBUG: Memory breakpoint %s: %04X:%04X - %02X -> %02X\n",(bp->GetType()==BKPNT_MEMORY_PROT)?"(Prot)":"",bp->GetSegment(),bp->GetOffset(),bp->GetValue(),value);
00496                                         bp->SetValue(value);
00497                                         return true;
00498                                 }               
00499                         }
00500                 }
00501 #endif
00502         }
00503         return false;
00504 }
00505 
00506 bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue)
00507 // Checks if interrupt breakpoint is valid and should stop execution
00508 {
00509         if ((ignoreAddressOnce!=0) && (adr==ignoreAddressOnce)) {
00510                 ignoreAddressOnce = 0;
00511                 return false;
00512         } else
00513                 ignoreAddressOnce = 0;
00514 
00515         // Search matching breakpoint
00516         std::list<CBreakpoint*>::iterator i;
00517         CBreakpoint* bp;
00518         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00519                 bp = (*i);
00520                 if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) {
00521                         if ((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) {
00522                                 // Ignore it once ?
00523                                 if (ignoreOnce==bp) {
00524                                         ignoreOnce=0;
00525                                         bp->Activate(true);
00526                                         return false;
00527                                 };
00528                                 // Found
00529                                 if (bp->GetOnce()) {
00530                                         // delete it, if it should only be used once
00531                                         (BPoints.erase)(i);
00532                                         bp->Activate(false);
00533                                         delete bp;
00534                                 } else {
00535                                         ignoreOnce = bp;
00536                                 }
00537                                 return true;
00538                         }
00539                 }
00540         }
00541         return false;
00542 }
00543 
00544 void CBreakpoint::DeleteAll() 
00545 {
00546         std::list<CBreakpoint*>::iterator i;
00547         CBreakpoint* bp;
00548         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00549                 bp = (*i);
00550                 bp->Activate(false);
00551                 delete bp;
00552         }
00553         (BPoints.clear)();
00554 }
00555 
00556 
00557 bool CBreakpoint::DeleteByIndex(Bit16u index) 
00558 {
00559         // Search matching breakpoint
00560         int nr = 0;
00561         std::list<CBreakpoint*>::iterator i;
00562         CBreakpoint* bp;
00563         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00564                 if (nr==index) {
00565                         bp = (*i);
00566                         (BPoints.erase)(i);
00567                         bp->Activate(false);
00568                         delete bp;
00569                         return true;
00570                 }
00571                 nr++;
00572         }
00573         return false;
00574 }
00575 
00576 bool CBreakpoint::DeleteBreakpoint(PhysPt where) 
00577 {
00578         // Search matching breakpoint
00579         std::list<CBreakpoint*>::iterator i;
00580         CBreakpoint* bp;
00581         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00582                 bp = (*i);
00583                 if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==where)) {
00584                         (BPoints.erase)(i);
00585                         bp->Activate(false);
00586                         delete bp;
00587                         return true;
00588                 }
00589         }
00590         return false;
00591 }
00592 
00593 bool CBreakpoint::IsBreakpoint(PhysPt adr) 
00594 // is there a breakpoint at address ?
00595 {
00596         // Search matching breakpoint
00597         std::list<CBreakpoint*>::iterator i;
00598         CBreakpoint* bp;
00599         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00600                 bp = (*i);
00601                 if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetSegment()==adr)) {
00602                         return true;
00603                 }
00604                 if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
00605                         return true;
00606                 }
00607         }
00608         return false;
00609 }
00610 
00611 bool CBreakpoint::IsBreakpointDrawn(PhysPt adr) 
00612 // valid breakpoint, that should be drawn ?
00613 {
00614         // Search matching breakpoint
00615         std::list<CBreakpoint*>::iterator i;
00616         CBreakpoint* bp;
00617         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00618                 bp = (*i);
00619                 if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
00620                         // Only draw, if breakpoint is not only once, 
00621                         return !bp->GetOnce();
00622                 }
00623         }
00624         return false;
00625 }
00626 
00627 void CBreakpoint::ShowList(void)
00628 {
00629         // iterate list 
00630         int nr = 0;
00631         std::list<CBreakpoint*>::iterator i;
00632         for(i=BPoints.begin(); i != BPoints.end(); i++) {
00633                 CBreakpoint* bp = (*i);
00634                 if (bp->GetType()==BKPNT_PHYSICAL) {
00635                         DEBUG_ShowMsg("%02X. BP %04X:%04X\n",nr,bp->GetSegment(),bp->GetOffset());
00636                 } else if (bp->GetType()==BKPNT_INTERRUPT) {
00637                         if (bp->GetValue()==BPINT_ALL)  DEBUG_ShowMsg("%02X. BPINT %02X\n",nr,bp->GetIntNr());                                  
00638                         else                                                    DEBUG_ShowMsg("%02X. BPINT %02X AH=%02X\n",nr,bp->GetIntNr(),bp->GetValue());
00639                 } else if (bp->GetType()==BKPNT_MEMORY) {
00640                         DEBUG_ShowMsg("%02X. BPMEM %04X:%04X (%02X)\n",nr,bp->GetSegment(),bp->GetOffset(),bp->GetValue());
00641                 } else if (bp->GetType()==BKPNT_MEMORY_PROT) {
00642                         DEBUG_ShowMsg("%02X. BPPM %04X:%08X (%02X)\n",nr,bp->GetSegment(),bp->GetOffset(),bp->GetValue());
00643                 } else if (bp->GetType()==BKPNT_MEMORY_LINEAR ) {
00644                         DEBUG_ShowMsg("%02X. BPLM %08X (%02X)\n",nr,bp->GetOffset(),bp->GetValue());
00645                 };
00646                 nr++;
00647         }
00648 }
00649 
00650 bool DEBUG_Breakpoint(void)
00651 {
00652         /* First get the phyiscal address and check for a set Breakpoint */
00653         if (!CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) return false;
00654         // Found. Breakpoint is valid
00655         PhysPt where=(Bitu)GetAddress(SegValue(cs),reg_eip);
00656         CBreakpoint::ActivateBreakpoints(where,false);  // Deactivate all breakpoints
00657         return true;
00658 }
00659 
00660 bool DEBUG_IntBreakpoint(Bit8u intNum)
00661 {
00662         /* First get the phyiscal address and check for a set Breakpoint */
00663         PhysPt where=(Bitu)GetAddress(SegValue(cs),reg_eip);
00664         if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false;
00665         // Found. Breakpoint is valid
00666         CBreakpoint::ActivateBreakpoints(where,false);  // Deactivate all breakpoints
00667         return true;
00668 }
00669 
00670 static bool StepOver()
00671 {
00672         exitLoop = false;
00673         PhysPt start=(Bitu)GetAddress(SegValue(cs),reg_eip);
00674         char dline[200];Bitu size;
00675         size=DasmI386(dline, start, reg_eip, cpu.code.big);
00676 
00677         if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) {
00678                 CBreakpoint::AddBreakpoint              (SegValue(cs),reg_eip+size, true);
00679                 CBreakpoint::ActivateBreakpoints(start, true);
00680                 debugging=false;
00681 
00682         logBuffSuppressConsole = false;
00683         if (logBuffSuppressConsoleNeedUpdate) {
00684             logBuffSuppressConsoleNeedUpdate = false;
00685             DEBUG_RefreshPage(0);
00686         }
00687 
00688                 DrawCode();
00689                 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu);
00690                 DOSBOX_SetNormalLoop();
00691                 return true;
00692         } 
00693         return false;
00694 }
00695 
00696 bool DEBUG_ExitLoop(void)
00697 {
00698 #if C_HEAVY_DEBUG
00699         DrawVariables();
00700 #endif
00701 
00702         if (exitLoop) {
00703                 exitLoop = false;
00704                 return true;
00705         }
00706         return false;
00707 }
00708 
00709 /********************/
00710 /*   Draw windows   */
00711 /********************/
00712 
00713 static void DrawData(void) {
00714         if (dbg.win_main == NULL || dbg.win_data == NULL)
00715                 return;
00716 
00717         Bit8u ch;
00718         Bit32u add = dataOfs;
00719         Bit64u address;
00720     int w,h;
00721 
00722         /* Data win */  
00723     getmaxyx(dbg.win_data,h,w);
00724         for (int y=0;y<h;y++) {
00725                 // Address
00726         if (dbg.data_view == DBGBlock::DATV_SEGMENTED) {
00727             wattrset (dbg.win_data,0);
00728             mvwprintw (dbg.win_data,y,0,"%04X:%08X ",dataSeg,add);
00729         }
00730         else {
00731             wattrset (dbg.win_data,0);
00732             mvwprintw (dbg.win_data,y,0,"     %08X ",add);
00733         }
00734 
00735         if (dbg.data_view == DBGBlock::DATV_PHYSICAL) {
00736             for (int x=0; x<16; x++) {
00737                 address = add;
00738 
00739                 /* save the original page addr.
00740                  * we must hack the phys page tlb to make the hardware handler map 1:1 the page for this call. */
00741                 PhysPt opg = paging.tlb.phys_page[address>>12];
00742 
00743                 paging.tlb.phys_page[address>>12] = (Bit32u)(address>>12);
00744 
00745                 PageHandler *ph = MEM_GetPageHandler((Bitu)(address>>12));
00746 
00747                 if (ph->flags & PFLAG_READABLE)
00748                         ch = ph->GetHostReadPt((Bitu)(address>>12))[address&0xFFF];
00749                 else
00750                     ch = ph->readb((PhysPt)address);
00751 
00752                 paging.tlb.phys_page[address>>12] = opg;
00753 
00754                 wattrset (dbg.win_data,0);
00755                 mvwprintw (dbg.win_data,y,14+3*x,"%02X",ch);
00756                 if (ch<32 || !isprint(*reinterpret_cast<unsigned char*>(&ch))) ch='.';
00757                 mvwprintw (dbg.win_data,y,63+x,"%c",ch);
00758 
00759                 add++;
00760             }
00761         }
00762         else {
00763             for (int x=0; x<16; x++) {
00764                 if (dbg.data_view == DBGBlock::DATV_SEGMENTED)
00765                     address = GetAddress(dataSeg,add);
00766                 else
00767                     address = add;
00768 
00769                 if (address != mem_no_address) {
00770                     if (!mem_readb_checked((PhysPt)address,&ch)) {
00771                         wattrset (dbg.win_data,0);
00772                         mvwprintw (dbg.win_data,y,14+3*x,"%02X",ch);
00773                         if (ch<32 || !isprint(*reinterpret_cast<unsigned char*>(&ch))) ch='.';
00774                         mvwprintw (dbg.win_data,y,63+x,"%c",ch);
00775                     }
00776                     else {
00777                         wattrset (dbg.win_data, COLOR_PAIR(PAIR_BYELLOW_BLACK));
00778                         mvwprintw (dbg.win_data,y,14+3*x,"pf");
00779                         mvwprintw (dbg.win_data,y,63+x,".");
00780                     }
00781                 }
00782                 else {
00783                     wattrset (dbg.win_data, COLOR_PAIR(PAIR_BYELLOW_BLACK));
00784                     mvwprintw (dbg.win_data,y,14+3*x,"na");
00785                     mvwprintw (dbg.win_data,y,63+x,".");
00786                 }
00787 
00788                 add++;
00789             }
00790         }
00791         }       
00792         wrefresh(dbg.win_data);
00793 }
00794 
00795 void DrawRegistersUpdateOld(void) {
00796         /* Main Registers */
00797         oldregs.eax=reg_eax;
00798         oldregs.ebx=reg_ebx;
00799         oldregs.ecx=reg_ecx;
00800         oldregs.edx=reg_edx;
00801 
00802         oldregs.esi=reg_esi;
00803         oldregs.edi=reg_edi;
00804         oldregs.ebp=reg_ebp;
00805         oldregs.esp=reg_esp;
00806         oldregs.eip=reg_eip;
00807 
00808         oldsegs[ds].val=SegValue(ds);
00809         oldsegs[es].val=SegValue(es);
00810         oldsegs[fs].val=SegValue(fs);
00811         oldsegs[gs].val=SegValue(gs);
00812         oldsegs[ss].val=SegValue(ss);
00813         oldsegs[cs].val=SegValue(cs);
00814 
00815         /*Individual flags*/
00816         oldflags = reg_flags;
00817 
00818         oldcpucpl=cpu.cpl;
00819 }
00820 
00821 static void DrawRegisters(void) {
00822         if (dbg.win_main == NULL || dbg.win_reg == NULL)
00823                 return;
00824 
00825         /* Main Registers */
00826         SetColor(reg_eax!=oldregs.eax);mvwprintw (dbg.win_reg,0,4,"%08X",reg_eax);
00827         SetColor(reg_ebx!=oldregs.ebx);mvwprintw (dbg.win_reg,1,4,"%08X",reg_ebx);
00828         SetColor(reg_ecx!=oldregs.ecx);mvwprintw (dbg.win_reg,2,4,"%08X",reg_ecx);
00829         SetColor(reg_edx!=oldregs.edx);mvwprintw (dbg.win_reg,3,4,"%08X",reg_edx);
00830 
00831         SetColor(reg_esi!=oldregs.esi);mvwprintw (dbg.win_reg,0,18,"%08X",reg_esi);
00832         SetColor(reg_edi!=oldregs.edi);mvwprintw (dbg.win_reg,1,18,"%08X",reg_edi);
00833         SetColor(reg_ebp!=oldregs.ebp);mvwprintw (dbg.win_reg,2,18,"%08X",reg_ebp);
00834         SetColor(reg_esp!=oldregs.esp);mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp);
00835         SetColor(reg_eip!=oldregs.eip);mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip);
00836 
00837         SetColor(SegValue(ds)!=oldsegs[ds].val);mvwprintw (dbg.win_reg,0,31,"%04X",SegValue(ds));
00838         SetColor(SegValue(es)!=oldsegs[es].val);mvwprintw (dbg.win_reg,0,41,"%04X",SegValue(es));
00839         SetColor(SegValue(fs)!=oldsegs[fs].val);mvwprintw (dbg.win_reg,0,51,"%04X",SegValue(fs));
00840         SetColor(SegValue(gs)!=oldsegs[gs].val);mvwprintw (dbg.win_reg,0,61,"%04X",SegValue(gs));
00841         SetColor(SegValue(ss)!=oldsegs[ss].val);mvwprintw (dbg.win_reg,0,71,"%04X",SegValue(ss));
00842         SetColor(SegValue(cs)!=oldsegs[cs].val);mvwprintw (dbg.win_reg,1,31,"%04X",SegValue(cs));
00843 
00844         /*Individual flags*/
00845         Bitu changed_flags = reg_flags ^ oldflags;
00846 
00847         SetColor(changed_flags&FLAG_CF);
00848         mvwprintw (dbg.win_reg,1,53,"%01X",GETFLAG(CF) ? 1:0);
00849         SetColor(changed_flags&FLAG_ZF);
00850         mvwprintw (dbg.win_reg,1,56,"%01X",GETFLAG(ZF) ? 1:0);
00851         SetColor(changed_flags&FLAG_SF);
00852         mvwprintw (dbg.win_reg,1,59,"%01X",GETFLAG(SF) ? 1:0);
00853         SetColor(changed_flags&FLAG_OF);
00854         mvwprintw (dbg.win_reg,1,62,"%01X",GETFLAG(OF) ? 1:0);
00855         SetColor(changed_flags&FLAG_AF);
00856         mvwprintw (dbg.win_reg,1,65,"%01X",GETFLAG(AF) ? 1:0);
00857         SetColor(changed_flags&FLAG_PF);
00858         mvwprintw (dbg.win_reg,1,68,"%01X",GETFLAG(PF) ? 1:0);
00859 
00860 
00861         SetColor(changed_flags&FLAG_DF);
00862         mvwprintw (dbg.win_reg,1,71,"%01X",GETFLAG(DF) ? 1:0);
00863         SetColor(changed_flags&FLAG_IF);
00864         mvwprintw (dbg.win_reg,1,74,"%01X",GETFLAG(IF) ? 1:0);
00865         SetColor(changed_flags&FLAG_TF);
00866         mvwprintw (dbg.win_reg,1,77,"%01X",GETFLAG(TF) ? 1:0);
00867 
00868         SetColor(changed_flags&FLAG_IOPL);
00869         mvwprintw (dbg.win_reg,2,72,"%01X",GETFLAG(IOPL)>>12);
00870 
00871 
00872         SetColor(cpu.cpl ^ oldcpucpl);
00873         mvwprintw (dbg.win_reg,2,78,"%01X",cpu.cpl);
00874 
00875         if (cpu.pmode) {
00876                 if (reg_flags & FLAG_VM) mvwprintw(dbg.win_reg,0,76,"VM86");
00877                 else if (cpu.code.big) mvwprintw(dbg.win_reg,0,76,"Pr32");
00878                 else mvwprintw(dbg.win_reg,0,76,"Pr16");
00879                 mvwprintw(dbg.win_reg,2,62,paging.enabled ? "PAGE" : "NOPG");
00880         } else {
00881                 mvwprintw(dbg.win_reg,0,76,"Real");
00882                 mvwprintw(dbg.win_reg,2,62,"NOPG");
00883     }
00884 
00885         // Selector info, if available
00886         if ((cpu.pmode) && curSelectorName[0]) {
00887                 char out1[200], out2[200];
00888                 GetDescriptorInfo(curSelectorName,out1,out2);
00889                 mvwprintw(dbg.win_reg,2,28,out1);
00890                 mvwprintw(dbg.win_reg,3,28,out2);
00891         }
00892 
00893         wattrset(dbg.win_reg,0);
00894         mvwprintw(dbg.win_reg,3,60,"%u       ",cycle_count);
00895         wrefresh(dbg.win_reg);
00896 }
00897 
00898 bool DEBUG_IsPagingOutput(void);
00899 
00900 static void DrawInput(void) {
00901     if (!debugging) {
00902         wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK));
00903         wattrset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK));
00904 
00905         mvwprintw(dbg.win_inp,0,0,"%s","(Running)");
00906         wclrtoeol(dbg.win_inp);
00907     } else if (DEBUG_IsPagingOutput()) {
00908         wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK));
00909         wattrset(dbg.win_inp,COLOR_PAIR(PAIR_GREEN_BLACK));
00910 
00911         mvwprintw(dbg.win_inp,0,0,"%s","^ Paged content: Hit ENTER to continue, Q to exit paging");
00912         wclrtoeol(dbg.win_inp);
00913     } else {
00914         //TODO long lines
00915         char* dispPtr = codeViewData.inputStr; 
00916         char* curPtr = &codeViewData.inputStr[codeViewData.inputPos];
00917 
00918         wbkgdset(dbg.win_inp,COLOR_PAIR(PAIR_BLACK_GREY));
00919         wattrset(dbg.win_inp,COLOR_PAIR(PAIR_BLACK_GREY));
00920         mvwprintw(dbg.win_inp,0,0,"%c-> %s%c",
00921                 (codeViewData.ovrMode?'O':'I'),dispPtr,(*curPtr?' ':'_'));
00922         wclrtoeol(dbg.win_inp); // not correct in pdcurses if full line
00923         if (*curPtr) {
00924             mvwchgat(dbg.win_inp,0,(int)(curPtr-dispPtr+4),1,0,(PAIR_BLACK_GREY),NULL);
00925         } 
00926     }
00927 
00928     wrefresh(dbg.win_inp);
00929 }
00930 
00931 static void DrawCode(void) {
00932         if (dbg.win_main == NULL || dbg.win_code == NULL)
00933                 return;
00934 
00935         bool saveSel; 
00936         Bit32u disEIP = codeViewData.useEIP;
00937         char dline[200];Bitu size;Bitu c;
00938         static char line20[21] = "                    ";
00939     int w,h;
00940 
00941     getmaxyx(dbg.win_code,h,w);
00942         for (int i=0;i<h;i++) {
00943         Bit64u start = GetAddress(codeViewData.useCS,disEIP);
00944 
00945                 saveSel = false;
00946                 if (has_colors()) {
00947                         if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) {
00948                                 if (codeViewData.cursorPos==-1) {
00949                                         codeViewData.cursorPos = i; // Set Cursor 
00950                                 }
00951                                 if (i == codeViewData.cursorPos) {
00952                                         codeViewData.cursorSeg = SegValue(cs);
00953                                         codeViewData.cursorOfs = disEIP;
00954                                 }
00955                                 saveSel = (i == codeViewData.cursorPos);
00956 
00957                 if (i == codeViewData.cursorPos) {
00958                     wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREEN));
00959                     wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREEN));
00960                 }
00961                 else {
00962                     wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK));
00963                     wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK));
00964                 }
00965             } else if (i == codeViewData.cursorPos) {
00966                 wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY));
00967                                 wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY));                     
00968                                 codeViewData.cursorSeg = codeViewData.useCS;
00969                                 codeViewData.cursorOfs = disEIP;
00970                                 saveSel = true;
00971                         } else if (CBreakpoint::IsBreakpointDrawn((PhysPt)start)) {
00972                 wbkgdset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED));
00973                                 wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED));                       
00974                         } else {
00975                 wbkgdset(dbg.win_code,0);
00976                                 wattrset(dbg.win_code,0);                       
00977                         }
00978                 }
00979 
00980 
00981                 bool toolarge = false;
00982         bool no_bytes = false;
00983                 Bitu drawsize;
00984 
00985         if (start != mem_no_address) {
00986             drawsize=size=DasmI386(dline, (PhysPt)start, disEIP, cpu.code.big);
00987         }
00988         else {
00989             drawsize=size=1;
00990             dline[0]=0;
00991         }
00992                 mvwprintw(dbg.win_code,i,0,"%04X:%08X ",codeViewData.useCS,disEIP);
00993 
00994                 if (drawsize>10) { toolarge = true; drawsize = 9; };
00995  
00996         if (start != mem_no_address) {
00997             for (c=0;c<drawsize;c++) {
00998                 Bit8u value;
00999                 if (!mem_readb_checked((PhysPt)(start+c),&value)) {
01000                     wattrset (dbg.win_code,0);
01001                     wprintw(dbg.win_code,"%02X",value);
01002                 }
01003                 else {
01004                     no_bytes = true;
01005                     wattrset (dbg.win_code, COLOR_PAIR(PAIR_BYELLOW_BLACK));
01006                     wprintw(dbg.win_code,"pf");
01007                 }
01008             }
01009         }
01010         else {
01011             wattrset (dbg.win_code, COLOR_PAIR(PAIR_BYELLOW_BLACK));
01012             wprintw(dbg.win_code,"na");
01013         }
01014 
01015         wattrset (dbg.win_code,0);
01016         if (toolarge) { waddstr(dbg.win_code,".."); drawsize++; };
01017                 // Spacepad up to 20 characters
01018                 if(drawsize && (drawsize < 11)) {
01019                         line20[20 - drawsize*2] = 0;
01020                         waddstr(dbg.win_code,line20);
01021                         line20[20 - drawsize*2] = ' ';
01022                 } else waddstr(dbg.win_code,line20);
01023 
01024                 char empty_res[] = { 0 };
01025                 char* res = empty_res;
01026         wattrset (dbg.win_code,0);
01027         if (showExtend) res = AnalyzeInstruction(dline, saveSel);
01028                 // Spacepad it up to 28 characters
01029         if (no_bytes) dline[0] = 0;
01030                 size_t dline_len = strlen(dline);
01031                 if(dline_len < 28) for (c = (Bitu)dline_len; c < 28;c++) dline[c] = ' '; dline[28] = 0;
01032                 waddstr(dbg.win_code,dline);
01033                 // Spacepad it up to 20 characters
01034                 size_t res_len = strlen(res);
01035                 if(res_len && (res_len < 21)) {
01036                         waddstr(dbg.win_code,res);
01037                         line20[20-res_len] = 0;
01038                         waddstr(dbg.win_code,line20);
01039                         line20[20-res_len] = ' ';
01040                 } else  waddstr(dbg.win_code,line20);
01041 
01042         wclrtoeol(dbg.win_code);
01043 
01044         disEIP+=size;
01045 
01046                 if (i==0) codeViewData.firstInstSize = size;
01047                 if (i==4) codeViewData.useEIPmid         = disEIP;
01048         }
01049 
01050         codeViewData.useEIPlast = disEIP;
01051 
01052         wrefresh(dbg.win_code);
01053 }
01054 
01055 static void SetCodeWinStart()
01056 {
01057         if ((SegValue(cs)==codeViewData.useCS) && (reg_eip>=codeViewData.useEIP) && (reg_eip<=codeViewData.useEIPlast)) {
01058                 // in valid window - scroll ?
01059                 if (reg_eip>=codeViewData.useEIPmid) codeViewData.useEIP += codeViewData.firstInstSize;
01060                 
01061         } else {
01062                 // totally out of range.
01063                 codeViewData.useCS      = SegValue(cs);
01064                 codeViewData.useEIP     = reg_eip;
01065         }
01066         codeViewData.cursorPos = -1;    // Recalc Cursor position
01067 }
01068 
01069 void DEBUG_CheckCSIP() {
01070     SetCodeWinStart();
01071 }
01072 
01073 /********************/
01074 /*    User input    */
01075 /********************/
01076 
01077 Bit32u GetHexValue(char* str, char*& hex)
01078 {
01079         Bit32u  value = 0;
01080         Bit32u regval = 0;
01081         hex = str;
01082         while (*hex==' ') hex++;
01083         if (strstr(hex,"EAX")==hex) { hex+=3; regval = reg_eax; };
01084         if (strstr(hex,"EBX")==hex) { hex+=3; regval = reg_ebx; };
01085         if (strstr(hex,"ECX")==hex) { hex+=3; regval = reg_ecx; };
01086         if (strstr(hex,"EDX")==hex) { hex+=3; regval = reg_edx; };
01087         if (strstr(hex,"ESI")==hex) { hex+=3; regval = reg_esi; };
01088         if (strstr(hex,"EDI")==hex) { hex+=3; regval = reg_edi; };
01089         if (strstr(hex,"EBP")==hex) { hex+=3; regval = reg_ebp; };
01090         if (strstr(hex,"ESP")==hex) { hex+=3; regval = reg_esp; };
01091         if (strstr(hex,"EIP")==hex) { hex+=3; regval = reg_eip; };
01092         if (strstr(hex,"AX")==hex) { hex+=2; regval = reg_ax; };
01093         if (strstr(hex,"BX")==hex) { hex+=2; regval = reg_bx; };
01094         if (strstr(hex,"CX")==hex) { hex+=2; regval = reg_cx; };
01095         if (strstr(hex,"DX")==hex) { hex+=2; regval = reg_dx; };
01096         if (strstr(hex,"SI")==hex) { hex+=2; regval = reg_si; };
01097         if (strstr(hex,"DI")==hex) { hex+=2; regval = reg_di; };
01098         if (strstr(hex,"BP")==hex) { hex+=2; regval = reg_bp; };
01099         if (strstr(hex,"SP")==hex) { hex+=2; regval = reg_sp; };
01100         if (strstr(hex,"IP")==hex) { hex+=2; regval = reg_ip; };
01101         if (strstr(hex,"CS")==hex) { hex+=2; regval = SegValue(cs); };
01102         if (strstr(hex,"DS")==hex) { hex+=2; regval = SegValue(ds); };
01103         if (strstr(hex,"ES")==hex) { hex+=2; regval = SegValue(es); };
01104         if (strstr(hex,"FS")==hex) { hex+=2; regval = SegValue(fs); };
01105         if (strstr(hex,"GS")==hex) { hex+=2; regval = SegValue(gs); };
01106         if (strstr(hex,"SS")==hex) { hex+=2; regval = SegValue(ss); };
01107 
01108         while (*hex) {
01109                 if ((*hex>='0') && (*hex<='9')) value = (value<<4u) + ((Bit32u)(*hex)) - '0';
01110                 else if ((*hex>='A') && (*hex<='F')) value = (value<<4u) + ((Bit32u)(*hex)) - 'A' + 10u;
01111                 else { 
01112                         if(*hex == '+') {hex++;return regval + value + GetHexValue(hex,hex); };
01113                         if(*hex == '-') {hex++;return regval + value - GetHexValue(hex,hex); };
01114                         break; // No valid char
01115                 }
01116                 hex++;
01117         }
01118 
01119         return regval + value;
01120 }
01121 
01122 bool ChangeRegister(char* str)
01123 {
01124         char* hex = str;
01125         while (*hex==' ') hex++;
01126         if (strstr(hex,"EAX")==hex) { hex+=3; reg_eax = GetHexValue(hex,hex); } else
01127         if (strstr(hex,"EBX")==hex) { hex+=3; reg_ebx = GetHexValue(hex,hex); } else
01128         if (strstr(hex,"ECX")==hex) { hex+=3; reg_ecx = GetHexValue(hex,hex); } else
01129         if (strstr(hex,"EDX")==hex) { hex+=3; reg_edx = GetHexValue(hex,hex); } else
01130         if (strstr(hex,"ESI")==hex) { hex+=3; reg_esi = GetHexValue(hex,hex); } else
01131         if (strstr(hex,"EDI")==hex) { hex+=3; reg_edi = GetHexValue(hex,hex); } else
01132         if (strstr(hex,"EBP")==hex) { hex+=3; reg_ebp = GetHexValue(hex,hex); } else
01133         if (strstr(hex,"ESP")==hex) { hex+=3; reg_esp = GetHexValue(hex,hex); } else
01134         if (strstr(hex,"EIP")==hex) { hex+=3; reg_eip = GetHexValue(hex,hex); } else
01135         if (strstr(hex,"AX")==hex) { hex+=2; reg_ax = (Bit16u)GetHexValue(hex,hex); } else
01136         if (strstr(hex,"BX")==hex) { hex+=2; reg_bx = (Bit16u)GetHexValue(hex,hex); } else
01137         if (strstr(hex,"CX")==hex) { hex+=2; reg_cx = (Bit16u)GetHexValue(hex,hex); } else
01138         if (strstr(hex,"DX")==hex) { hex+=2; reg_dx = (Bit16u)GetHexValue(hex,hex); } else
01139         if (strstr(hex,"SI")==hex) { hex+=2; reg_si = (Bit16u)GetHexValue(hex,hex); } else
01140         if (strstr(hex,"DI")==hex) { hex+=2; reg_di = (Bit16u)GetHexValue(hex,hex); } else
01141         if (strstr(hex,"BP")==hex) { hex+=2; reg_bp = (Bit16u)GetHexValue(hex,hex); } else
01142         if (strstr(hex,"SP")==hex) { hex+=2; reg_sp = (Bit16u)GetHexValue(hex,hex); } else
01143         if (strstr(hex,"IP")==hex) { hex+=2; reg_ip = (Bit16u)GetHexValue(hex,hex); } else
01144         if (strstr(hex,"CS")==hex) { hex+=2; SegSet16(cs,(Bit16u)GetHexValue(hex,hex)); } else
01145         if (strstr(hex,"DS")==hex) { hex+=2; SegSet16(ds,(Bit16u)GetHexValue(hex,hex)); } else
01146         if (strstr(hex,"ES")==hex) { hex+=2; SegSet16(es,(Bit16u)GetHexValue(hex,hex)); } else
01147         if (strstr(hex,"FS")==hex) { hex+=2; SegSet16(fs,(Bit16u)GetHexValue(hex,hex)); } else
01148         if (strstr(hex,"GS")==hex) { hex+=2; SegSet16(gs,(Bit16u)GetHexValue(hex,hex)); } else
01149         if (strstr(hex,"SS")==hex) { hex+=2; SegSet16(ss,(Bit16u)GetHexValue(hex,hex)); } else
01150         if (strstr(hex,"AF")==hex) { hex+=2; SETFLAGBIT(AF,GetHexValue(hex,hex)); } else
01151         if (strstr(hex,"CF")==hex) { hex+=2; SETFLAGBIT(CF,GetHexValue(hex,hex)); } else
01152         if (strstr(hex,"DF")==hex) { hex+=2; SETFLAGBIT(DF,GetHexValue(hex,hex)); } else
01153         if (strstr(hex,"IF")==hex) { hex+=2; SETFLAGBIT(IF,GetHexValue(hex,hex)); } else
01154         if (strstr(hex,"OF")==hex) { hex+=2; SETFLAGBIT(OF,GetHexValue(hex,hex)); } else
01155         if (strstr(hex,"ZF")==hex) { hex+=2; SETFLAGBIT(ZF,GetHexValue(hex,hex)); } else
01156         if (strstr(hex,"PF")==hex) { hex+=2; SETFLAGBIT(PF,GetHexValue(hex,hex)); } else
01157         if (strstr(hex,"SF")==hex) { hex+=2; SETFLAGBIT(SF,GetHexValue(hex,hex)); } else
01158         { return false; };
01159         return true;
01160 }
01161 
01162 void DEBUG_GUI_Rebuild(void);
01163 void DBGUI_NextWindowIfActiveHidden(void);
01164 
01165 void DEBUG_BeginPagedContent(void);
01166 void DEBUG_EndPagedContent(void);
01167 
01168 bool ParseCommand(char* str) {
01169         char* found = str;
01170         for(char* idx = found;*idx != 0; idx++)
01171                 *idx = toupper(*idx);
01172 
01173         found = trim(found);
01174         string s_found(found);
01175         istringstream stream(s_found);
01176         string command;
01177         stream >> command;
01178         string::size_type next = s_found.find_first_not_of(' ',command.size());
01179         if(next == string::npos) next = command.size();
01180         (s_found.erase)(0,next);
01181         found = const_cast<char*>(s_found.c_str());
01182 
01183     if (command == "MOVEWINDN") { // MOVE WINDOW DOWN (by swapping)
01184         int order1 = dbg.win_find_order((int)dbg.active_win);
01185         int order2 = dbg.win_next_by_order(order1);
01186 
01187         if (order1 >= 0 && order2 >= 0 && order1 < order2) {
01188             dbg.swap_order(order1,order2);
01189             DEBUG_GUI_Rebuild();
01190             DBGUI_NextWindowIfActiveHidden();
01191         }
01192 
01193         return true;
01194     }
01195 
01196     if (command == "MOVEWINUP") { // MOVE WINDOW UP (by swapping)
01197         int order1 = dbg.win_find_order((int)dbg.active_win);
01198         int order2 = dbg.win_prev_by_order(order1);
01199 
01200         if (order1 >= 0 && order2 >= 0 && order1 > order2) {
01201             dbg.swap_order(order1,order2);
01202             DEBUG_GUI_Rebuild();
01203             DBGUI_NextWindowIfActiveHidden();
01204         }
01205 
01206         return true;
01207     }
01208 
01209     if (command == "SHOWWIN") { // SHOW WINDOW <name>
01210         int win = dbg.name_to_win(found);
01211         if (win >= 0) {
01212             dbg.win_vis[win] = true;
01213 
01214             DEBUG_GUI_Rebuild();
01215             DBGUI_NextWindowIfActiveHidden();
01216             return true;
01217         }
01218         else {
01219             LOG_MSG("No such window '%s'. Windows are: %s",found,dbg.windowlist_by_name().c_str());
01220             return false;
01221         }
01222     }
01223 
01224     if (command == "HIDEWIN") { // HIDE WINDOW <name>
01225         int win = dbg.name_to_win(found);
01226         if (win >= 0) {
01227             dbg.win_vis[win] = false;
01228 
01229             DEBUG_GUI_Rebuild();
01230             DBGUI_NextWindowIfActiveHidden();
01231             return true;
01232         }
01233         else {
01234             LOG_MSG("No such window '%s'. Windows are: %s",found,dbg.windowlist_by_name().c_str());
01235             return false;
01236         }
01237     }
01238 
01239         if (command == "MEMDUMP") { // Dump memory to file
01240                 Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
01241                 Bit32u ofs = GetHexValue(found,found); found++;
01242                 Bit32u num = GetHexValue(found,found); found++;
01243                 SaveMemory(seg,ofs,num);
01244                 return true;
01245         };
01246 
01247         if (command == "MEMDUMPBIN") { // Dump memory to file bineary
01248                 Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
01249                 Bit32u ofs = GetHexValue(found,found); found++;
01250                 Bit32u num = GetHexValue(found,found); found++;
01251                 SaveMemoryBin(seg,ofs,num);
01252                 return true;
01253         };
01254 
01255         if (command == "IV") { // Insert variable
01256                 Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
01257                 Bit32u ofs = (Bit16u)GetHexValue(found,found); found++;
01258                 char name[16];
01259                 for (int i=0; i<16; i++) {
01260                         if (found[i] && (found[i]!=' ')) name[i] = found[i]; 
01261                         else { name[i] = 0; break; };
01262                 };
01263                 name[15] = 0;
01264 
01265                 if(!name[0]) return false;
01266                 DEBUG_ShowMsg("DEBUG: Created debug var %s at %04X:%04X\n",name,seg,ofs);
01267                 CDebugVar::InsertVariable(name,(PhysPt)GetAddress(seg,ofs));
01268                 return true;
01269         };
01270 
01271         if (command == "SV") { // Save variables
01272                 char name[13];
01273                 for (int i=0; i<12; i++) {
01274                         if (found[i] && (found[i]!=' ')) name[i] = found[i]; 
01275                         else { name[i] = 0; break; };
01276                 };
01277                 name[12] = 0;
01278                 if(!name[0]) return false;
01279                 DEBUG_ShowMsg("DEBUG: Variable list save (%s) : %s.\n",name,(CDebugVar::SaveVars(name)?"ok":"failure"));
01280                 return true;
01281         };
01282 
01283         if (command == "LV") { // load variables
01284                 char name[13];
01285                 for (int i=0; i<12; i++) {
01286                         if (found[i] && (found[i]!=' ')) name[i] = found[i]; 
01287                         else { name[i] = 0; break; };
01288                 };
01289                 name[12] = 0;
01290                 if(!name[0]) return false;
01291                 DEBUG_ShowMsg("DEBUG: Variable list load (%s) : %s.\n",name,(CDebugVar::LoadVars(name)?"ok":"failure"));
01292                 return true;
01293         };
01294 
01295         if (command == "SR") { // Set register value
01296                 DEBUG_ShowMsg("DEBUG: Set Register %s.\n",(ChangeRegister(found)?"success":"failure"));
01297                 return true;
01298         };
01299 
01300         if (command == "SM") { // Set memory with following values
01301                 Bit16u seg = (Bit16u)GetHexValue(found,found); found++;
01302                 Bit32u ofs = GetHexValue(found,found); found++;
01303                 Bit16u count = 0;
01304                 while (*found) {
01305                         while (*found==' ') found++;
01306                         if (*found) {
01307                                 Bit8u value = (Bit8u)GetHexValue(found,found);
01308                                 if(*found) found++;
01309                                 mem_writeb_checked((PhysPt)GetAddress(seg,ofs+count),value);
01310                                 count++;
01311                         }
01312                 };
01313                 DEBUG_ShowMsg("DEBUG: Memory changed.\n");
01314                 return true;
01315         };
01316 
01317         if (command == "BP") { // Add new breakpoint
01318                 Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":"
01319                 Bit32u ofs = GetHexValue(found,found);
01320                 CBreakpoint::AddBreakpoint(seg,ofs,false);
01321                 DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X\n",seg,ofs);
01322                 return true;
01323         };
01324 
01325 #if C_HEAVY_DEBUG
01326 
01327         if (command == "BPM") { // Add new breakpoint
01328                 Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":"
01329                 Bit32u ofs = GetHexValue(found,found);
01330                 CBreakpoint::AddMemBreakpoint(seg,ofs);
01331                 DEBUG_ShowMsg("DEBUG: Set memory breakpoint at %04X:%04X\n",seg,ofs);
01332                 return true;
01333         };
01334 
01335         if (command == "BPPM") { // Add new breakpoint
01336                 Bit16u seg = (Bit16u)GetHexValue(found,found);found++; // skip ":"
01337                 Bit32u ofs = GetHexValue(found,found);
01338                 CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(seg,ofs);
01339                 if (bp) {
01340                         bp->SetType(BKPNT_MEMORY_PROT);
01341                         DEBUG_ShowMsg("DEBUG: Set prot-mode memory breakpoint at %04X:%08X\n",seg,ofs);
01342                 }
01343                 return true;
01344         };
01345 
01346         if (command == "BPLM") { // Add new breakpoint
01347                 Bit32u ofs = GetHexValue(found,found);
01348                 CBreakpoint* bp = CBreakpoint::AddMemBreakpoint(0,ofs);
01349                 if (bp) bp->SetType(BKPNT_MEMORY_LINEAR);
01350                 DEBUG_ShowMsg("DEBUG: Set linear memory breakpoint at %08X\n",ofs);
01351                 return true;
01352         };
01353 
01354 #endif
01355 
01356         if (command == "BPINT") { // Add Interrupt Breakpoint
01357                 Bit8u intNr     = (Bit8u)GetHexValue(found,found);
01358                 bool all = !(*found);found++;
01359                 Bit8u valAH     = (Bit8u)GetHexValue(found,found);
01360                 if ((valAH==0x00) && (*found=='*' || all)) {
01361                         CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false);
01362                         DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X\n",intNr);
01363                 } else {
01364                         CBreakpoint::AddIntBreakpoint(intNr,valAH,false);
01365                         DEBUG_ShowMsg("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X\n",intNr,valAH);
01366                 }
01367                 return true;
01368         };
01369 
01370         if (command == "BPLIST") {
01371         DEBUG_BeginPagedContent();
01372                 DEBUG_ShowMsg("Breakpoint list:\n");
01373                 DEBUG_ShowMsg("-------------------------------------------------------------------------\n");
01374                 CBreakpoint::ShowList();
01375         DEBUG_EndPagedContent();
01376                 return true;
01377         };
01378 
01379         if (command == "BPDEL") { // Delete Breakpoints
01380                 Bit8u bpNr      = (Bit8u)GetHexValue(found,found); 
01381                 if ((bpNr==0x00) && (*found=='*')) { // Delete all
01382                         CBreakpoint::DeleteAll();               
01383                         DEBUG_ShowMsg("DEBUG: Breakpoints deleted.\n");
01384                 } else {                
01385                         // delete single breakpoint
01386                         DEBUG_ShowMsg("DEBUG: Breakpoint deletion %s.\n",(CBreakpoint::DeleteByIndex(bpNr)?"success":"failure"));
01387                 }
01388                 return true;
01389         };
01390 
01391     if (command == "RUN") {
01392         DrawRegistersUpdateOld();
01393         debugging=false;
01394 
01395         logBuffSuppressConsole = false;
01396         if (logBuffSuppressConsoleNeedUpdate) {
01397             logBuffSuppressConsoleNeedUpdate = false;
01398             DEBUG_RefreshPage(0);
01399         }
01400 
01401         CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);                                             
01402         ignoreAddressOnce = SegPhys(cs)+reg_eip;
01403                 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu);
01404         DOSBOX_SetNormalLoop(); 
01405         return true;
01406     }
01407 
01408     if (command == "RUNWATCH") {
01409         debug_running = true;
01410         DEBUG_DrawScreen();
01411         return true;
01412     }
01413 
01414     if (command == "A20") {
01415         void MEM_A20_Enable(bool enabled);
01416         bool MEM_A20_Enabled(void);
01417 
01418                 stream >> command;
01419 
01420         if (command == "ON" || command == "1")
01421             MEM_A20_Enable(true);
01422         else if (command == "OFF" || command == "0")
01423             MEM_A20_Enable(false);
01424         else
01425             DEBUG_ShowMsg("A20 gate is %s",MEM_A20_Enabled() ? "ON" : "OFF");
01426 
01427         return true;
01428     }
01429 
01430     if (command == "PIC") { // interrupt controller state/controls
01431         void DEBUG_PICSignal(int irq,bool raise);
01432         void DEBUG_PICMask(int irq,bool mask);
01433         void DEBUG_PICAck(int irq);
01434         void DEBUG_LogPIC(void);
01435 
01436         DEBUG_BeginPagedContent();
01437 
01438                 stream >> command;
01439 
01440         if (command == "MASKIRQ") {
01441             std::string what;
01442             stream >> what;
01443             int irq = atoi(what.c_str());
01444             DEBUG_PICMask(irq,true);
01445         }
01446         else if (command == "UNMASKIRQ") {
01447             std::string what;
01448             stream >> what;
01449             int irq = atoi(what.c_str());
01450             DEBUG_PICMask(irq,false);
01451         }
01452         else if (command == "ACKIRQ") { /* debugging: manually acknowledge an IRQ where the DOS program failed to do so */
01453             std::string what;
01454             stream >> what;
01455             int irq = atoi(what.c_str());
01456             DEBUG_PICAck(irq);
01457         }
01458         else if (command == "LOWERIRQ") { /* manually lower an IRQ signal */
01459             std::string what;
01460             stream >> what;
01461             int irq = atoi(what.c_str());
01462             DEBUG_PICSignal(irq,false);
01463         }
01464         else if (command == "RAISEIRQ") { /* manually raise an IRQ signal */
01465             std::string what;
01466             stream >> what;
01467             int irq = atoi(what.c_str());
01468             DEBUG_PICSignal(irq,true);
01469         }
01470         else {
01471             DEBUG_LogPIC();
01472         }
01473 
01474         DEBUG_EndPagedContent();
01475 
01476         return true;
01477     }
01478 
01479         if (command == "C") { // Set code overview
01480                 Bit16u codeSeg = (Bit16u)GetHexValue(found,found); found++;
01481                 Bit32u codeOfs = GetHexValue(found,found);
01482                 DEBUG_ShowMsg("DEBUG: Set code overview to %04X:%04X\n",codeSeg,codeOfs);
01483                 codeViewData.useCS      = codeSeg;
01484                 codeViewData.useEIP = codeOfs;
01485                 codeViewData.cursorPos = 0;
01486                 return true;
01487         };
01488 
01489         if (command == "D") { // Set data overview
01490                 dataSeg = (Bit16u)GetHexValue(found,found); found++;
01491                 dataOfs = GetHexValue(found,found);
01492         dbg.set_data_view(DBGBlock::DATV_SEGMENTED);
01493                 DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs);
01494                 return true;
01495         };
01496 
01497         if (command == "DV") { // Set data overview
01498         dataSeg = 0;
01499                 dataOfs = GetHexValue(found,found);
01500         dbg.set_data_view(DBGBlock::DATV_VIRTUAL);
01501                 DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs);
01502                 return true;
01503         };
01504 
01505         if (command == "DP") { // Set data overview
01506         dataSeg = 0;
01507                 dataOfs = GetHexValue(found,found);
01508         dbg.set_data_view(DBGBlock::DATV_PHYSICAL);
01509                 DEBUG_ShowMsg("DEBUG: Set data overview to %04X:%04X\n",dataSeg,dataOfs);
01510                 return true;
01511         };
01512 
01513 #if C_HEAVY_DEBUG
01514 
01515         if (command == "LOG") { // Create Cpu normal log file
01516                 cpuLogType = 1;
01517                 command = "logcode";
01518         }
01519 
01520         if (command == "LOGS") { // Create Cpu short log file
01521                 cpuLogType = 0;
01522                 command = "logcode";
01523         }
01524 
01525         if (command == "LOGL") { // Create Cpu long log file
01526                 cpuLogType = 2;
01527                 command = "logcode";
01528         }
01529 
01530         if (command == "logcode") { //Shared code between all logs
01531                 DEBUG_ShowMsg("DEBUG: Starting log\n");
01532                 cpuLogFile.open("LOGCPU.TXT");
01533                 if (!cpuLogFile.is_open()) {
01534                         DEBUG_ShowMsg("DEBUG: Logfile couldn't be created.\n");
01535                         return false;
01536                 }
01537                 //Initialize log object
01538                 cpuLogFile << hex << noshowbase << setfill('0') << uppercase;
01539                 cpuLog = true;
01540                 cpuLogCounter = (int)GetHexValue(found,found);
01541 
01542                 debugging = false;
01543                 CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);                                             
01544                 ignoreAddressOnce = SegPhys(cs)+reg_eip;
01545                 DOSBOX_SetNormalLoop(); 
01546                 return true;
01547         };
01548 
01549 #endif
01550 
01551         if (command == "INTT") { //trace int.
01552                 Bit8u intNr = (Bit8u)GetHexValue(found,found);
01553                 DEBUG_ShowMsg("DEBUG: Tracing INT %02X\n",intNr);
01554                 CPU_HW_Interrupt(intNr);
01555                 SetCodeWinStart();
01556                 return true;
01557         };
01558 
01559         if (command == "INT") { // start int.
01560                 Bit8u intNr = (Bit8u)GetHexValue(found,found);
01561                 DEBUG_ShowMsg("DEBUG: Starting INT %02X\n",intNr);
01562                 CBreakpoint::AddBreakpoint(SegValue(cs),reg_eip, true);
01563                 CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true);
01564                 debugging = false;
01565                 DrawCode();
01566                 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu);
01567                 DOSBOX_SetNormalLoop();
01568                 CPU_HW_Interrupt(intNr);
01569                 return true;
01570         };      
01571 
01572         if (command == "SELINFO") {
01573                 while (found[0] == ' ') found++;
01574                 char out1[200],out2[200];
01575                 GetDescriptorInfo(found,out1,out2);
01576                 DEBUG_ShowMsg("SelectorInfo %s:\n%s\n%s\n",found,out1,out2);
01577                 return true;
01578         };
01579 
01580         if (command == "DOS") {
01581                 stream >> command;
01582                 if (command == "MCBS") LogMCBS();
01583         else if (command == "KERN") LogDOSKernMem();
01584         else if (command == "XMS") LogXMS();
01585         else if (command == "EMS") LogEMS();
01586                 return true;
01587         }
01588 
01589     if (command == "BIOS") {
01590         stream >> command;
01591 
01592         if (command == "MEM") LogBIOSMem();
01593 
01594         return true;
01595     }
01596 
01597     if (command == "CALLBACKS") {
01598         DEBUG_BeginPagedContent();
01599 
01600         void DBG_CALLBACK_Dump(void);
01601         DBG_CALLBACK_Dump();
01602 
01603         DEBUG_EndPagedContent();
01604         return true;
01605     }
01606 
01607         if (command == "GDT") {LogGDT(); return true;}
01608         
01609         if (command == "LDT") {LogLDT(); return true;}
01610         
01611         if (command == "IDT") {LogIDT(); return true;}
01612         
01613         if (command == "PAGING") {LogPages(found); return true;}
01614 
01615         if (command == "CPU") {LogCPUInfo(); return true;}
01616 
01617         if (command == "INTVEC") {
01618                 if (found[0] != 0) {
01619                         OutputVecTable(found);
01620                         return true;
01621                 }
01622         };
01623 
01624         if (command == "INTHAND") {
01625                 if (found[0] != 0) {
01626                         Bit8u intNr = (Bit8u)GetHexValue(found,found);
01627                         DEBUG_ShowMsg("DEBUG: Set code overview to interrupt handler %X\n",intNr);
01628                         codeViewData.useCS      = mem_readw(intNr*4u+2u);
01629                         codeViewData.useEIP = mem_readw(intNr*4u);
01630                         codeViewData.cursorPos = 0;
01631                         return true;
01632                 }
01633         };
01634 
01635         if(command == "EXTEND") { //Toggle additional data.     
01636                 showExtend = !showExtend;
01637                 return true;
01638         };
01639 
01640         if(command == "TIMERIRQ") { //Start a timer irq
01641                 DEBUG_RaiseTimerIrq(); 
01642                 DEBUG_ShowMsg("Debug: Timer Int started.\n");
01643                 return true;
01644         };
01645 
01646 
01647 #if C_HEAVY_DEBUG
01648         if (command == "HEAVYLOG") { // Create Cpu log file
01649                 logHeavy = !logHeavy;
01650                 DEBUG_ShowMsg("DEBUG: Heavy cpu logging %s.\n",logHeavy?"on":"off");
01651                 return true;
01652         };
01653 
01654         if (command == "ZEROPROTECT") { //toggle zero protection
01655                 zeroProtect = !zeroProtect;
01656                 DEBUG_ShowMsg("DEBUG: Zero code execution protection %s.\n",zeroProtect?"on":"off");
01657                 return true;
01658         };
01659 
01660 #endif
01661         if (command == "HELP" || command == "?") {
01662         DEBUG_BeginPagedContent();
01663                 DEBUG_ShowMsg("Debugger commands (enter all values in hex or as register):\n");
01664                 DEBUG_ShowMsg("--------------------------------------------------------------------------\n");
01665                 DEBUG_ShowMsg("F3/F6                     - Previous command in history.\n");
01666                 DEBUG_ShowMsg("F4/F7                     - Next command in history.\n");
01667                 DEBUG_ShowMsg("F5                        - Run.\n");
01668                 DEBUG_ShowMsg("F9                        - Set/Remove breakpoint.\n");
01669                 DEBUG_ShowMsg("F10/F11                   - Step over / trace into instruction.\n");
01670                 DEBUG_ShowMsg("ALT + D/E/S/X/B           - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX.\n");
01671                 DEBUG_ShowMsg("Escape                    - Clear input line.");
01672                 DEBUG_ShowMsg("Up/Down                   - Scroll up/down in the current window.\n");
01673                 DEBUG_ShowMsg("Page Up/Down              - Page up/down in the current window.\n");
01674                 DEBUG_ShowMsg("Home/End                  - Move to begin/end of the current window.\n");
01675         DEBUG_ShowMsg("TAB                       - Select next window\n");
01676                 DEBUG_ShowMsg("BP     [segment]:[offset] - Set breakpoint.\n");
01677                 DEBUG_ShowMsg("BPINT  [intNr] *          - Set interrupt breakpoint.\n");
01678                 DEBUG_ShowMsg("BPINT  [intNr] [ah]       - Set interrupt breakpoint with ah.\n");
01679 #if C_HEAVY_DEBUG
01680                 DEBUG_ShowMsg("BPM    [segment]:[offset] - Set memory breakpoint (memory change).\n");
01681                 DEBUG_ShowMsg("BPPM   [selector]:[offset]- Set pmode-memory breakpoint (memory change).\n");
01682                 DEBUG_ShowMsg("BPLM   [linear address]   - Set linear memory breakpoint (memory change).\n");
01683 #endif
01684                 DEBUG_ShowMsg("BPLIST                    - List breakpoints.\n");               
01685                 DEBUG_ShowMsg("BPDEL  [bpNr] / *         - Delete breakpoint nr / all.\n");
01686                 DEBUG_ShowMsg("C / D  [segment]:[offset] - Set code / data view address.\n");
01687                 DEBUG_ShowMsg("DOS MCBS                  - Show Memory Control Block chain.\n");
01688                 DEBUG_ShowMsg("INT [nr] / INTT [nr]      - Execute / Trace into interrupt.\n");
01689 #if C_HEAVY_DEBUG
01690                 DEBUG_ShowMsg("LOG [num]                 - Write cpu log file.\n");
01691                 DEBUG_ShowMsg("LOGS/LOGL [num]           - Write short/long cpu log file.\n");
01692                 DEBUG_ShowMsg("HEAVYLOG                  - Enable/Disable automatic cpu log when dosbox exits.\n");
01693                 DEBUG_ShowMsg("ZEROPROTECT               - Enable/Disable zero code execution detecion.\n");
01694 #endif
01695                 DEBUG_ShowMsg("SR [reg] [value]          - Set register value.\n");
01696                 DEBUG_ShowMsg("SM [seg]:[off] [val] [.]..- Set memory with following values.\n");       
01697         
01698                 DEBUG_ShowMsg("IV [seg]:[off] [name]     - Create var name for memory address.\n");
01699                 DEBUG_ShowMsg("SV [filename]             - Save var list in file.\n");
01700                 DEBUG_ShowMsg("LV [filename]             - Load var list from file.\n");
01701 
01702                 DEBUG_ShowMsg("MEMDUMP [seg]:[off] [len] - Write memory to file memdump.txt.\n");
01703                 DEBUG_ShowMsg("MEMDUMPBIN [s]:[o] [len]  - Write memory to file memdump.bin.\n");
01704                 DEBUG_ShowMsg("SELINFO [segName]         - Show selector info.\n");
01705 
01706                 DEBUG_ShowMsg("INTVEC [filename]         - Writes interrupt vector table to file.\n");
01707                 DEBUG_ShowMsg("INTHAND [intNum]          - Set code view to interrupt handler.\n");
01708 
01709                 DEBUG_ShowMsg("CPU                       - Display CPU status information.\n");
01710                 DEBUG_ShowMsg("GDT                       - Lists descriptors of the GDT.\n");
01711                 DEBUG_ShowMsg("LDT                       - Lists descriptors of the LDT.\n");
01712                 DEBUG_ShowMsg("IDT                       - Lists descriptors of the IDT.\n");
01713                 DEBUG_ShowMsg("PAGING [page]             - Display content of page table.\n");
01714                 DEBUG_ShowMsg("EXTEND                    - Toggle additional info.\n");
01715                 DEBUG_ShowMsg("TIMERIRQ                  - Run the system timer.\n");
01716 
01717                 DEBUG_ShowMsg("HELP                      - Help\n");
01718         DEBUG_EndPagedContent();
01719                 
01720                 return true;
01721         }
01722 
01723         return false;
01724 }
01725 
01726 char* AnalyzeInstruction(char* inst, bool saveSelector) {
01727         static char result[256];
01728         
01729         char instu[256];
01730         char prefix[3];
01731         Bit16u seg;
01732 
01733         strcpy(instu,inst);
01734         upcase(instu);
01735 
01736         result[0] = 0;
01737         char* pos = strchr(instu,'[');
01738         if (pos) {
01739                 // Segment prefix ?
01740                 if (*(pos-1)==':') {
01741                         char* segpos = pos-3;
01742                         prefix[0] = tolower(*segpos);
01743                         prefix[1] = tolower(*(segpos+1));
01744                         prefix[2] = 0;
01745                         seg = (Bit16u)GetHexValue(segpos,segpos);
01746                 } else {
01747                         if (strstr(pos,"SP") || strstr(pos,"BP")) {
01748                                 seg = SegValue(ss);
01749                                 strcpy(prefix,"ss");
01750                         } else {
01751                                 seg = SegValue(ds);
01752                                 strcpy(prefix,"ds");
01753                         };
01754                 };
01755 
01756                 pos++;
01757                 Bit32u adr = GetHexValue(pos,pos);
01758                 while (*pos!=']') {
01759                         if (*pos=='+') {
01760                                 pos++;
01761                                 adr += GetHexValue(pos,pos);
01762                         } else if (*pos=='-') {
01763                                 pos++;
01764                                 adr -= GetHexValue(pos,pos); 
01765                         } else 
01766                                 pos++;
01767                 };
01768                 Bit32u address = (Bit32u)GetAddress(seg,adr);
01769                 if (!(get_tlb_readhandler(address)->flags & PFLAG_INIT)) {
01770                         static char outmask[] = "%s:[%04X]=%02X";
01771                         
01772                         if (cpu.pmode) outmask[6] = '8';
01773                                 switch (DasmLastOperandSize()) {
01774                                 case 8 : {      Bit8u val = mem_readb(address);
01775                                                         outmask[12] = '2';
01776                                                         sprintf(result,outmask,prefix,adr,val);
01777                                                 }       break;
01778                                 case 16: {      Bit16u val = mem_readw(address);
01779                                                         outmask[12] = '4';
01780                                                         sprintf(result,outmask,prefix,adr,val);
01781                                                 }       break;
01782                                 case 32: {      Bit32u val = mem_readd(address);
01783                                                         outmask[12] = '8';
01784                                                         sprintf(result,outmask,prefix,adr,val);
01785                                                 }       break;
01786                         }
01787                 } else {
01788                         sprintf(result,"[illegal]");
01789                 }
01790                 // Variable found ?
01791                 CDebugVar* var = CDebugVar::FindVar(address);
01792                 if (var) {
01793                         // Replace occurence
01794                         char* pos1 = strchr(inst,'[');
01795                         char* pos2 = strchr(inst,']');
01796                         if (pos1 && pos2) {
01797                                 char temp[256];
01798                                 strcpy(temp,pos2);                              // save end
01799                                 pos1++; *pos1 = 0;                              // cut after '['
01800                                 strcat(inst,var->GetName());    // add var name
01801                                 strcat(inst,temp);                              // add end
01802                         };
01803                 };
01804                 // show descriptor info, if available
01805                 if ((cpu.pmode) && saveSelector) {
01806                         strcpy(curSelectorName,prefix);
01807                 };
01808         };
01809         // If it is a callback add additional info
01810         pos = strstr(inst,"callback");
01811         if (pos) {
01812                 pos += 9;
01813                 Bitu nr = GetHexValue(pos,pos);
01814                 const char* descr = CALLBACK_GetDescription(nr);
01815                 if (descr) {
01816                         strcat(inst,"  ("); strcat(inst,descr); strcat(inst,")");
01817                 }
01818         };
01819         // Must be a jump
01820         if (instu[0] == 'J')
01821         {
01822                 bool jmp = false;
01823                 switch (instu[1]) {
01824                 case 'A' :      {       jmp = (get_CF()?false:true) && (get_ZF()?false:true); // JA
01825                                         }       break;
01826                 case 'B' :      {       if (instu[2] == 'E') {
01827                                                         jmp = (get_CF()?true:false) || (get_ZF()?true:false); // JBE
01828                                                 } else {
01829                                                         jmp = get_CF()?true:false; // JB
01830                                                 }
01831                                         }       break;
01832                 case 'C' :      {       if (instu[2] == 'X') {
01833                                                         jmp = reg_cx == 0; // JCXZ
01834                                                 } else {
01835                                                         jmp = get_CF()?true:false; // JC
01836                                                 }
01837                                         }       break;
01838                 case 'E' :      {       jmp = get_ZF()?true:false; // JE
01839                                         }       break;
01840                 case 'G' :      {       if (instu[2] == 'E') {
01841                                                         jmp = (get_SF()?true:false)==(get_OF()?true:false); // JGE
01842                                                 } else {
01843                                                         jmp = (get_ZF()?false:true) && ((get_SF()?true:false)==(get_OF()?true:false)); // JG
01844                                                 }
01845                                         }       break;
01846                 case 'L' :      {       if (instu[2] == 'E') {
01847                                                         jmp = (get_ZF()?true:false) || ((get_SF()?true:false)!=(get_OF()?true:false)); // JLE
01848                                                 } else {
01849                                                         jmp = (get_SF()?true:false)!=(get_OF()?true:false); // JL
01850                                                 }
01851                                         }       break;
01852                 case 'M' :      {       jmp = true; // JMP
01853                                         }       break;
01854                 case 'N' :      {       switch (instu[2]) {
01855                                                 case 'B' :      
01856                                                 case 'C' :      {       jmp = get_CF()?false:true;      // JNB / JNC
01857                                                                         }       break;
01858                                                 case 'E' :      {       jmp = get_ZF()?false:true;      // JNE
01859                                                                         }       break;
01860                                                 case 'O' :      {       jmp = get_OF()?false:true;      // JNO
01861                                                                         }       break;
01862                                                 case 'P' :      {       jmp = get_PF()?false:true;      // JNP
01863                                                                         }       break;
01864                                                 case 'S' :      {       jmp = get_SF()?false:true;      // JNS
01865                                                                         }       break;
01866                                                 case 'Z' :      {       jmp = get_ZF()?false:true;      // JNZ
01867                                                                         }       break;
01868                                                 }
01869                                         }       break;
01870                 case 'O' :      {       jmp = get_OF()?true:false; // JO
01871                                         }       break;
01872                 case 'P' :      {       if (instu[2] == 'O') {
01873                                                         jmp = get_PF()?false:true; // JPO
01874                                                 } else {
01875                                                         jmp = get_SF()?true:false; // JP / JPE
01876                                                 }
01877                                         }       break;
01878                 case 'S' :      {       jmp = get_SF()?true:false; // JS
01879                                         }       break;
01880                 case 'Z' :      {       jmp = get_ZF()?true:false; // JZ
01881                                         }       break;
01882                 }
01883                 if (jmp) {
01884                         pos = strchr(instu,'$');
01885                         if (pos) {
01886                                 pos = strchr(instu,'+');
01887                                 if (pos) {
01888                                         strcpy(result,"(down)");
01889                                 } else {
01890                                         strcpy(result,"(up)");
01891                                 }
01892                         }
01893                 } else {
01894                         sprintf(result,"(no jmp)");
01895                 }
01896         }
01897         return result;
01898 }
01899 
01900 // data window
01901 void win_data_ui_down(int count) {
01902     if (count > 0)
01903         dataOfs += (unsigned)count * 16;
01904 }
01905 
01906 void win_data_ui_up(int count) {
01907     if (count > 0)
01908         dataOfs -= (unsigned)count * 16;
01909 }
01910 
01911 // code window
01912 void win_code_ui_down(int count) {
01913     if (dbg.win_code != NULL) {
01914         int y,x;
01915 
01916         getmaxyx(dbg.win_code,y,x);
01917 
01918         while (count-- > 0) {
01919             if (codeViewData.cursorPos < (y-1)) codeViewData.cursorPos++;
01920             else codeViewData.useEIP += codeViewData.firstInstSize;
01921         }
01922     }
01923 }
01924 
01925 void win_code_ui_up(int count) {
01926     if (dbg.win_code != NULL) {
01927         int y,x;
01928 
01929         getmaxyx(dbg.win_code,y,x);
01930 
01931         (void)y; // SET, BUT UNUSED
01932 
01933         while (count-- > 0) {
01934             if (codeViewData.cursorPos>0)
01935                 codeViewData.cursorPos--;
01936             else {
01937                 Bitu bytes = 0;
01938                 char dline[200];
01939                 Bitu size = 0;
01940                 Bit32u newEIP = codeViewData.useEIP - 1;
01941                 if(codeViewData.useEIP) {
01942                     for (; bytes < 10; bytes++) {
01943                         PhysPt start = (PhysPt)GetAddress(codeViewData.useCS,newEIP);
01944                         size = DasmI386(dline, start, newEIP, cpu.code.big);
01945                         if(codeViewData.useEIP == newEIP+size) break;
01946                         newEIP--;
01947                     }
01948                     if (bytes>=10) newEIP = codeViewData.useEIP - 1;
01949                 }
01950                 codeViewData.useEIP = newEIP;
01951             }
01952         }
01953     }
01954 }
01955 
01956 Bit32u DEBUG_CheckKeys(void) {
01957         Bits ret=0;
01958         int key=getch();
01959 
01960         /* FIXME: This is supported by PDcurses, except I cannot figure out how to trigger it.
01961                   The Windows console resizes around the console set by pdcurses and does not notify us as far as I can tell. */
01962     if (key == KEY_RESIZE) {
01963         void DEBUG_GUI_OnResize(void);
01964         DEBUG_GUI_OnResize();
01965         DEBUG_DrawScreen();
01966         return 0;
01967     }
01968 
01969         if (key>0) {
01970 #if defined(WIN32) && defined(__PDCURSES__)
01971                 switch (key) {
01972                 case PADENTER:  key=0x0A;       break;
01973                 case PADSLASH:  key='/';        break;
01974                 case PADSTAR:   key='*';        break;
01975                 case PADMINUS:  key='-';        break;
01976                 case PADPLUS:   key='+';        break;
01977                 case ALT_D:
01978                         if (ungetch('D') != ERR) key=27;
01979                         break;
01980                 case ALT_E:
01981                         if (ungetch('E') != ERR) key=27;
01982                         break;
01983                 case ALT_X:
01984                         if (ungetch('X') != ERR) key=27;
01985                         break;
01986                 case ALT_B:
01987                         if (ungetch('B') != ERR) key=27;
01988                         break;
01989                 case ALT_S:
01990                         if (ungetch('S') != ERR) key=27;
01991                         break;
01992                 }
01993 #endif
01994                 switch (toupper(key)) {
01995                 case 27:        // escape (a bit slow): Clears line. and processes alt commands.
01996                         key=getch();
01997                         if(key < 0) { //Purely escape Clear line
01998                                 ClearInputLine();
01999                                 break;
02000                         }
02001 
02002                         switch(toupper(key)) {
02003                         case 'D' : // ALT - D: DS:SI
02004                                 dataSeg = SegValue(ds);
02005                                 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_esi;
02006                                 else dataOfs = reg_si;
02007                                 break;
02008                         case 'E' : //ALT - E: es:di
02009                                 dataSeg = SegValue(es);
02010                                 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_edi;
02011                                 else dataOfs = reg_di;
02012                                 break;
02013                         case 'X': //ALT - X: ds:dx
02014                                 dataSeg = SegValue(ds);
02015                                 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_edx;
02016                                 else dataOfs = reg_dx;
02017                                 break;
02018                         case 'B' : //ALT -B: es:bx
02019                                 dataSeg = SegValue(es);
02020                                 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_ebx;
02021                                 else dataOfs = reg_bx;
02022                                 break;
02023                         case 'S': //ALT - S: ss:sp
02024                                 dataSeg = SegValue(ss);
02025                                 if (cpu.pmode && !(reg_flags & FLAG_VM)) dataOfs = reg_esp;
02026                                 else dataOfs = reg_sp;
02027                                 break;
02028                         default:
02029                                 break;
02030                         }
02031                         break;
02032         case KEY_PPAGE: // page up
02033             switch (dbg.active_win) {
02034                 case DBGBlock::WINI_CODE:
02035                     if (dbg.win_code != NULL) {
02036                         int w,h;
02037 
02038                         getmaxyx(dbg.win_code,h,w);
02039                         win_code_ui_up(h-1);
02040                     }
02041                     break;
02042                 case DBGBlock::WINI_DATA:
02043                      if (dbg.win_data != NULL) {
02044                         int w,h;
02045 
02046                         getmaxyx(dbg.win_data,h,w);
02047                         win_data_ui_up(h);
02048                     }
02049                     break;
02050                 case DBGBlock::WINI_OUT:
02051                     if (dbg.win_out != NULL) {
02052                         int w,h;
02053 
02054                         getmaxyx(dbg.win_out,h,w);
02055                         DEBUG_RefreshPage(-h);
02056                     }
02057                     break;
02058             }
02059             break;
02060 
02061         case KEY_NPAGE: // page down
02062             switch (dbg.active_win) {
02063                 case DBGBlock::WINI_CODE:
02064                     if (dbg.win_code != NULL) {
02065                         int w,h;
02066 
02067                         getmaxyx(dbg.win_code,h,w);
02068                         win_code_ui_down(h-1);
02069                     }
02070                     break;
02071                 case DBGBlock::WINI_DATA:
02072                      if (dbg.win_data != NULL) {
02073                         int w,h;
02074 
02075                         getmaxyx(dbg.win_data,h,w);
02076                         win_data_ui_down(h);
02077                     }
02078                     break;
02079                 case DBGBlock::WINI_OUT:
02080                     if (dbg.win_out != NULL) {
02081                         int w,h;
02082 
02083                         getmaxyx(dbg.win_out,h,w);
02084                         DEBUG_RefreshPage(h);
02085                     }
02086                     break;
02087             }
02088             break;
02089 
02090                 case KEY_DOWN:  // down
02091                 switch (dbg.active_win) {
02092                     case DBGBlock::WINI_CODE:
02093                         win_code_ui_down(1);
02094                         break;
02095                     case DBGBlock::WINI_DATA:
02096                         win_data_ui_down(1);
02097                         break;
02098                     case DBGBlock::WINI_OUT:
02099                         DEBUG_RefreshPage(1);
02100                         break;
02101                 }
02102                 break;
02103         case KEY_UP:    // up 
02104                 switch (dbg.active_win) {
02105                     case DBGBlock::WINI_CODE:
02106                         win_code_ui_up(1);
02107                         break;
02108                     case DBGBlock::WINI_DATA:
02109                         win_data_ui_up(1);
02110                         break;
02111                     case DBGBlock::WINI_OUT:
02112                         DEBUG_RefreshPage(-1);
02113                         break;
02114                 }
02115                                 break;
02116 
02117                 case KEY_HOME:  // Home
02118                 switch (dbg.active_win) {
02119                     case DBGBlock::WINI_CODE:
02120                         // and do what?
02121                         break;
02122                     case DBGBlock::WINI_DATA:
02123                         // and do what?
02124                         break;
02125                     case DBGBlock::WINI_OUT:
02126                         void DEBUG_ScrollHomeOutput(void);
02127                         DEBUG_ScrollHomeOutput();
02128                         break;
02129                 }
02130                                 break;
02131 
02132                 case KEY_END:   // End
02133                 switch (dbg.active_win) {
02134                     case DBGBlock::WINI_CODE:
02135                         // and do what?
02136                         break;
02137                     case DBGBlock::WINI_DATA:
02138                         // and do what?
02139                         break;
02140                     case DBGBlock::WINI_OUT:
02141                         void DEBUG_ScrollToEndOutput(void);
02142                         DEBUG_ScrollToEndOutput();
02143                         break;
02144                 }
02145                                 break;
02146 
02147         case KEY_IC:    // Insert: toggle insert/overwrite
02148                                 codeViewData.ovrMode = !codeViewData.ovrMode;
02149                                 break;
02150                 case KEY_LEFT:  // move to the left in command line
02151                                 if (codeViewData.inputPos > 0) codeViewData.inputPos--;
02152                                 break;
02153                 case KEY_RIGHT: // move to the right in command line
02154                                 if (codeViewData.inputStr[codeViewData.inputPos]) codeViewData.inputPos++;
02155                                 break;
02156                 case KEY_F(6):  // previous command (f1-f4 generate rubbish at my place)
02157                 case KEY_F(3):  // previous command 
02158                                 if (histBuffPos == histBuff.begin()) break;
02159                                 if (histBuffPos == histBuff.end()) {
02160                                         // copy inputStr to suspInputStr so we can restore it
02161                                         safe_strncpy(codeViewData.suspInputStr, codeViewData.inputStr, sizeof(codeViewData.suspInputStr));
02162                                 }
02163                                 safe_strncpy(codeViewData.inputStr,(*--histBuffPos).c_str(),sizeof(codeViewData.inputStr));
02164                                 codeViewData.inputPos = (int)strlen(codeViewData.inputStr);
02165                                 break;
02166                 case KEY_F(7):  // next command (f1-f4 generate rubbish at my place)
02167                 case KEY_F(4):  // next command
02168                                 if (histBuffPos == histBuff.end()) break;
02169                                 if (++histBuffPos != histBuff.end()) {
02170                                         safe_strncpy(codeViewData.inputStr,(*histBuffPos).c_str(),sizeof(codeViewData.inputStr));
02171                                 } else {
02172                                         // copy suspInputStr back into inputStr
02173                                         safe_strncpy(codeViewData.inputStr, codeViewData.suspInputStr, sizeof(codeViewData.inputStr));
02174                                 }
02175                                 codeViewData.inputPos = (int)strlen(codeViewData.inputStr);
02176                                 break; 
02177                 case KEY_F(5):  // Run Program
02178                 DrawRegistersUpdateOld();
02179                                 debugging=false;
02180 
02181                 logBuffSuppressConsole = false;
02182                 if (logBuffSuppressConsoleNeedUpdate) {
02183                     logBuffSuppressConsoleNeedUpdate = false;
02184                     DEBUG_RefreshPage(0);
02185                 }
02186 
02187                 Bits DEBUG_NullCPUCore(void);
02188 
02189                 if (cpudecoder == DEBUG_NullCPUCore)
02190                     ret = -1; /* DEBUG_Loop() must exit */
02191 
02192                                 CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);                                             
02193                                 ignoreAddressOnce = SegPhys(cs)+reg_eip;
02194                                 mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu);
02195                                 DOSBOX_SetNormalLoop(); 
02196                                 break;
02197                 case KEY_F(9):  // Set/Remove Breakpoint
02198                                 {       PhysPt ptr = (PhysPt)GetAddress(codeViewData.cursorSeg,codeViewData.cursorOfs);
02199                                         if (CBreakpoint::IsBreakpoint(ptr)) {
02200                                                 CBreakpoint::DeleteBreakpoint(ptr);
02201                                                 DEBUG_ShowMsg("DEBUG: Breakpoint deletion success.\n");
02202                                         }
02203                                         else {
02204                                                 CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false);
02205                                                 DEBUG_ShowMsg("DEBUG: Set breakpoint at %04X:%04X\n",codeViewData.cursorSeg,codeViewData.cursorOfs);
02206                                         }
02207                                 }
02208                                 break;
02209                 case KEY_F(10): // Step over inst
02210                 DrawRegistersUpdateOld();
02211                                 if (StepOver()) return 0;
02212                                 else {
02213                                         exitLoop = false;
02214                                         skipFirstInstruction = true; // for heavy debugger
02215                                         CPU_Cycles = 1;
02216                                         ret=(*cpudecoder)();
02217                                         SetCodeWinStart();
02218                                         CBreakpoint::ignoreOnce = 0;
02219                                 }
02220                                 break;
02221                 case KEY_F(11): // trace into
02222                 DrawRegistersUpdateOld();
02223                                 exitLoop = false;
02224                                 skipFirstInstruction = true; // for heavy debugger
02225                                 CPU_Cycles = 1;
02226                                 ret = (*cpudecoder)();
02227                                 SetCodeWinStart();
02228                                 CBreakpoint::ignoreOnce = 0;
02229                                 break;
02230         case 0x09: //TAB
02231                 void DBGUI_NextWindow(void);
02232                 DBGUI_NextWindow();
02233                 break;
02234                 case 0x0A: //Parse typed Command
02235                                 codeViewData.inputStr[MAXCMDLEN] = '\0';
02236                                 if(ParseCommand(codeViewData.inputStr)) {
02237                                         char* cmd = ltrim(codeViewData.inputStr);
02238                                         if (histBuff.empty() || *--histBuff.end()!=cmd)
02239                                                 histBuff.push_back(cmd);
02240                                         if (histBuff.size() > MAX_HIST_BUFFER) histBuff.pop_front();
02241                                         histBuffPos = histBuff.end();
02242                                         ClearInputLine();
02243                                 } else { 
02244                                         codeViewData.inputPos = (int)strlen(codeViewData.inputStr);
02245                                 } 
02246                                 break;
02247                 case KEY_BACKSPACE: //backspace (linux)
02248                 case 0x7f:      // backspace in some terminal emulators (linux)
02249                 case 0x08:      // delete 
02250                                 if (codeViewData.inputPos == 0) break;
02251                                 codeViewData.inputPos--;
02252                                 // fallthrough
02253                 case KEY_DC: // delete character 
02254                                 if ((codeViewData.inputPos<0) || (codeViewData.inputPos>=MAXCMDLEN)) break;
02255                                 if (codeViewData.inputStr[codeViewData.inputPos] != 0) {
02256                                                 codeViewData.inputStr[MAXCMDLEN] = '\0';
02257                                                 for(char* p=&codeViewData.inputStr[codeViewData.inputPos];(*p=*(p+1));p++) {}
02258                                 }
02259                                 break;
02260                 default:
02261                                 if ((key>=32) && (key<127)) {
02262                                         if ((codeViewData.inputPos<0) || (codeViewData.inputPos>=MAXCMDLEN)) break;
02263                                         codeViewData.inputStr[MAXCMDLEN] = '\0';
02264                                         if (codeViewData.inputStr[codeViewData.inputPos] == 0) {
02265                                                         codeViewData.inputStr[codeViewData.inputPos++] = char(key);
02266                                                         codeViewData.inputStr[codeViewData.inputPos] = '\0';
02267                                         } else if (!codeViewData.ovrMode) {
02268                                                 int len = (int) strlen(codeViewData.inputStr);
02269                                                 if (len < MAXCMDLEN) { 
02270                                                         for(len++;len>codeViewData.inputPos;len--)
02271                                                                 codeViewData.inputStr[len]=codeViewData.inputStr[len-1];
02272                                                         codeViewData.inputStr[codeViewData.inputPos++] = char(key);
02273                                                 }
02274                                         } else {
02275                                                 codeViewData.inputStr[codeViewData.inputPos++] = char(key);
02276                                         }
02277                                 } else if (key==killchar()) {
02278                                         ClearInputLine();
02279                                 }
02280                                 break;
02281                 }
02282                 if (ret<0) return ret;
02283                 if (ret>0) {
02284                         if (GCC_UNLIKELY(ret >= CB_MAX)) 
02285                                 ret = 0;
02286                         else
02287                                 ret = (Bits)(*CallBack_Handlers[ret])();
02288                         if (ret) {
02289                                 exitLoop=true;
02290                                 CPU_Cycles=CPU_CycleLeft=0;
02291                                 return ret;
02292                         }
02293                 }
02294                 ret=0;
02295                 DEBUG_DrawScreen();
02296         }
02297         return ret;
02298 }
02299 
02300 Bitu DEBUG_LastRunningUpdate = 0;
02301 
02302 LoopHandler *DOSBOX_GetLoop(void);
02303 Bitu DEBUG_Loop(void);
02304 
02305 void DEBUG_Wait(void) {
02306     while (DOSBOX_GetLoop() == DEBUG_Loop)
02307         DOSBOX_RunMachine();
02308 }
02309 
02310 Bits DEBUG_NullCPUCore(void) {
02311     return CBRET_NONE;
02312 }
02313 
02314 void DEBUG_WaitNoExecute(void) {
02315     /* the caller uses this version to indicate a fatal error
02316      * in a condition where single-stepping or executing any
02317      * more x86 instructions is very unwise */
02318     auto oldcore = cpudecoder;
02319     cpudecoder = DEBUG_NullCPUCore;
02320     DEBUG_Wait();
02321     cpudecoder = oldcore;
02322 }
02323 
02324 Bitu DEBUG_Loop(void) {
02325     if (debug_running) {
02326         Bitu now = SDL_GetTicks();
02327 
02328         if ((DEBUG_LastRunningUpdate + 33) < now) {
02329             DEBUG_LastRunningUpdate = now;
02330             SetCodeWinStart();
02331             DEBUG_DrawScreen();
02332         }
02333 
02334         return old_loop();
02335     }
02336     else {
02337         //TODO Disable sound
02338         GFX_Events();
02339         // Interrupt started ? - then skip it
02340         Bit16u oldCS    = SegValue(cs);
02341         Bit32u oldEIP   = reg_eip;
02342         PIC_runIRQs();
02343         SDL_Delay(1);
02344         if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
02345             CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
02346             CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
02347             debugging=false;
02348 
02349             logBuffSuppressConsole = false;
02350             if (logBuffSuppressConsoleNeedUpdate) {
02351                 logBuffSuppressConsoleNeedUpdate = false;
02352                 DEBUG_RefreshPage(0);
02353             }
02354 
02355                         mainMenu.get_item("mapper_debugger").check(false).refresh_item(mainMenu);
02356             DOSBOX_SetNormalLoop();
02357             DrawRegistersUpdateOld();
02358             return 0;
02359         }
02360 
02361         /* between DEBUG_Enable and DEBUG_Loop CS:EIP can change */
02362         if (check_rescroll) {
02363             Bitu ocs,oip,ocr;
02364 
02365             check_rescroll = false;
02366             ocs = codeViewData.useCS;
02367             oip = codeViewData.useEIP;
02368             ocr = (Bitu)codeViewData.cursorPos;
02369             SetCodeWinStart();
02370             if (ocs != codeViewData.useCS ||
02371                     oip != codeViewData.useEIP) {
02372                 DEBUG_DrawScreen();
02373             }
02374             else {
02375                 /* SetCodeWinStart() resets cursor position */
02376                 codeViewData.cursorPos = ocr;
02377             }
02378         }
02379 
02380         if (logBuffSuppressConsoleNeedUpdate) {
02381             logBuffSuppressConsoleNeedUpdate = false;
02382             DEBUG_RefreshPage(0);
02383         }
02384 
02385         return DEBUG_CheckKeys();
02386     }
02387 }
02388 
02389 void DEBUG_Enable(bool pressed) {
02390         if (!pressed)
02391                 return;
02392         static bool showhelp=false;
02393 
02394 #if defined(MACOSX) || defined(LINUX)
02395         /* Mac OS X does not have a console for us to just allocate on a whim like Windows does.
02396            So the debugger interface is useless UNLESS the user has started us from a terminal
02397            (whether over SSH or from the Terminal app). */
02398     bool allow = true;
02399 
02400     if (!isatty(0) || !isatty(1) || !isatty(2))
02401             allow = false;
02402 
02403     if (!allow) {
02404 # if defined(MACOSX)
02405             LOG_MSG("Debugger in Mac OS X is not available unless you start DOSBox-X from a terminal or from the Terminal application");
02406 # else
02407             LOG_MSG("Debugger is not available unless you start DOSBox-X from a terminal");
02408 # endif
02409             return;
02410     }
02411 #endif
02412 
02413     CPU_CycleLeft+=CPU_Cycles;
02414     CPU_Cycles=0;
02415 
02416     logBuffSuppressConsole = true;
02417 
02418     LoopHandler *ol = DOSBOX_GetLoop();
02419     if (ol != DEBUG_Loop) old_loop = ol;
02420 
02421         debugging=true;
02422     debug_running=false;
02423     check_rescroll=true;
02424     DrawRegistersUpdateOld();
02425     DEBUG_SetupConsole();
02426         SetCodeWinStart();
02427         DEBUG_DrawScreen();
02428         DOSBOX_SetLoop(&DEBUG_Loop);
02429         mainMenu.get_item("mapper_debugger").check(true).refresh_item(mainMenu);
02430         if(!showhelp) { 
02431                 showhelp=true;
02432                 DEBUG_ShowMsg("***| TYPE HELP (+ENTER) TO GET AN OVERVIEW OF ALL COMMANDS |***\n");
02433         }
02434         KEYBOARD_ClrBuffer();
02435 }
02436 
02437 void DEBUG_DrawScreen(void) {
02438         DrawData();
02439         DrawCode();
02440     DrawInput();
02441         DrawRegisters();
02442         DrawVariables();
02443 }
02444 
02445 static void DEBUG_RaiseTimerIrq(void) {
02446         PIC_ActivateIRQ(0);
02447 }
02448 
02449 // Display the content of the MCB chain starting with the MCB at the specified segment.
02450 static void LogMCBChain(Bit16u mcb_segment) {
02451         DOS_MCB mcb(mcb_segment);
02452         char filename[9]; // 8 characters plus a terminating NUL
02453         const char *psp_seg_note;
02454         PhysPt dataAddr = PhysMake(dataSeg,dataOfs);// location being viewed in the "Data Overview"
02455 
02456         // loop forever, breaking out of the loop once we've processed the last MCB
02457         while (true) {
02458                 // verify that the type field is valid
02459                 if (mcb.GetType()!=0x4d && mcb.GetType()!=0x5a) {
02460                         LOG(LOG_MISC,LOG_ERROR)("MCB chain broken at %04X:0000!",mcb_segment);
02461                         return;
02462                 }
02463 
02464                 mcb.GetFileName(filename);
02465 
02466                 // some PSP segment values have special meanings
02467                 switch (mcb.GetPSPSeg()) {
02468                         case MCB_FREE:
02469                                 psp_seg_note = "(free)";
02470                                 break;
02471                         case MCB_DOS:
02472                                 psp_seg_note = "(DOS)";
02473                                 break;
02474                         default:
02475                                 psp_seg_note = "";
02476                 }
02477 
02478                 LOG(LOG_MISC,LOG_ERROR)("   %04X  %12u     %04X %-7s  %s",mcb_segment,mcb.GetSize() << 4,mcb.GetPSPSeg(), psp_seg_note, filename);
02479 
02480                 // print a message if dataAddr is within this MCB's memory range
02481                 PhysPt mcbStartAddr = PhysMake(mcb_segment+1,0);
02482                 PhysPt mcbEndAddr = PhysMake(mcb_segment+1+mcb.GetSize(),0);
02483                 if (dataAddr >= mcbStartAddr && dataAddr < mcbEndAddr) {
02484                         LOG(LOG_MISC,LOG_ERROR)("   (data addr %04hX:%04X is %u bytes past this MCB)",dataSeg,dataOfs,dataAddr - mcbStartAddr);
02485                 }
02486 
02487                 // if we've just processed the last MCB in the chain, break out of the loop
02488                 if (mcb.GetType()==0x5a) {
02489                         break;
02490                 }
02491                 // else, move to the next MCB in the chain
02492                 mcb_segment+=mcb.GetSize()+1;
02493                 mcb.SetPt(mcb_segment);
02494         }
02495 }
02496 
02497 #include "regionalloctracking.h"
02498 
02499 extern bool dos_kernel_disabled;
02500 extern RegionAllocTracking rombios_alloc;
02501 
02502 static void LogBIOSMem(void) {
02503     char tmp[192];
02504 
02505     DEBUG_BeginPagedContent();
02506 
02507     LOG(LOG_MISC,LOG_ERROR)("BIOS memory blocks:");
02508     LOG(LOG_MISC,LOG_ERROR)("Region            Status What");
02509     for (auto i=rombios_alloc.alist.begin();i!=rombios_alloc.alist.end();i++) {
02510         sprintf(tmp,"%08lx-%08lx %s",
02511             (unsigned long)(i->start),
02512             (unsigned long)(i->end),
02513             i->free ? "FREE  " : "ALLOC ");
02514         LOG(LOG_MISC,LOG_ERROR)("%s %s",tmp,i->who.c_str());
02515     }
02516 
02517     DEBUG_EndPagedContent();
02518 }
02519 
02520 Bitu XMS_GetTotalHandles(void);
02521 bool XMS_GetHandleInfo(Bitu &phys_location,Bitu &size,Bitu &lockcount,bool &free,Bitu handle);
02522 
02523 bool EMS_GetHandle(Bitu &size,PhysPt &addr,std::string &name,Bitu handle);
02524 const char *EMS_Type_String(void);
02525 Bitu EMS_Max_Handles(void);
02526 bool EMS_Active(void);
02527 
02528 static void LogEMS(void) {
02529     Bitu h_size;
02530     PhysPt h_addr;
02531     std::string h_name;
02532 
02533     if (dos_kernel_disabled) {
02534         LOG(LOG_MISC,LOG_ERROR)("Cannot enumerate EMS memory while DOS kernel is inactive.");
02535         return;
02536     }
02537 
02538     if (!EMS_Active()) {
02539         LOG(LOG_MISC,LOG_ERROR)("Cannot enumerate EMS memory while EMS is inactive.");
02540         return;
02541     }
02542 
02543     DEBUG_BeginPagedContent();
02544 
02545     LOG(LOG_MISC,LOG_ERROR)("EMS memory (type %s) handles:",EMS_Type_String());
02546     LOG(LOG_MISC,LOG_ERROR)("Handle Address  Size (bytes)    Name");
02547     for (Bitu h=0;h < EMS_Max_Handles();h++) {
02548         if (EMS_GetHandle(/*&*/h_size,/*&*/h_addr,/*&*/h_name,h)) {
02549             LOG(LOG_MISC,LOG_ERROR)("%6lu %08lx %08lx %s",
02550                 (unsigned long)h,
02551                 (unsigned long)h_addr,
02552                 (unsigned long)h_size,
02553                 h_name.c_str());
02554         }
02555     }
02556 
02557     bool EMS_GetMapping(Bitu &handle,Bitu &log_page,Bitu ems_page);
02558     Bitu GetEMSPageFrameSegment(void);
02559     Bitu GetEMSPageFrameSize(void);
02560 
02561     LOG(LOG_MISC,LOG_ERROR)("EMS page frame 0x%08lx-0x%08lx",
02562         GetEMSPageFrameSegment()*16UL,
02563         (GetEMSPageFrameSegment()*16UL)+GetEMSPageFrameSize()-1UL);
02564     LOG(LOG_MISC,LOG_ERROR)("Handle Page(p/l) Address");
02565 
02566     for (Bitu p=0;p < (GetEMSPageFrameSize() >> 14UL);p++) {
02567         Bitu log_page,handle;
02568 
02569         if (EMS_GetMapping(handle,log_page,p)) {
02570             char tmp[192] = {0};
02571 
02572             h_addr = 0;
02573             h_size = 0;
02574             h_name.clear();
02575             EMS_GetHandle(/*&*/h_size,/*&*/h_addr,/*&*/h_name,handle);
02576 
02577             if (h_addr != 0)
02578                 sprintf(tmp," virt -> %08lx-%08lx phys",
02579                     (unsigned long)h_addr + (log_page << 14UL),
02580                     (unsigned long)h_addr + (log_page << 14UL) + (1 << 14UL) - 1);
02581 
02582             LOG(LOG_MISC,LOG_ERROR)("%6lu %4lu/%4lu %08lx-%08lx%s",(unsigned long)handle,
02583                 (unsigned long)p,(unsigned long)log_page,
02584                 (GetEMSPageFrameSegment()*16UL)+(p << 14UL),
02585                 (GetEMSPageFrameSegment()*16UL)+((p+1UL) << 14UL)-1,
02586                 tmp);
02587         }
02588         else {
02589             LOG(LOG_MISC,LOG_ERROR)("--     %4lu/     %08lx-%08lx",(unsigned long)p,
02590                 (GetEMSPageFrameSegment()*16UL)+(p << 14UL),
02591                 (GetEMSPageFrameSegment()*16UL)+((p+1UL) << 14UL)-1);
02592         }
02593     }
02594 
02595     DEBUG_EndPagedContent();
02596 }
02597 
02598 static void LogXMS(void) {
02599     Bitu phys_location;
02600     Bitu lockcount;
02601     bool free;
02602     Bitu size;
02603 
02604     if (dos_kernel_disabled) {
02605         LOG(LOG_MISC,LOG_ERROR)("Cannot enumerate XMS memory while DOS kernel is inactive.");
02606         return;
02607     }
02608 
02609     if (!XMS_Active()) {
02610         LOG(LOG_MISC,LOG_ERROR)("Cannot enumerate XMS memory while XMS is inactive.");
02611         return;
02612     }
02613 
02614     DEBUG_BeginPagedContent();
02615 
02616     LOG(LOG_MISC,LOG_ERROR)("XMS memory handles:");
02617     LOG(LOG_MISC,LOG_ERROR)("Handle Status Location Size (bytes)");
02618     for (Bitu h=1;h < XMS_GetTotalHandles();h++) {
02619         if (XMS_GetHandleInfo(/*&*/phys_location,/*&*/size,/*&*/lockcount,/*&*/free,h)) {
02620             if (!free) {
02621                 LOG(LOG_MISC,LOG_ERROR)("%6lu %s 0x%08lx %lu",
02622                         (unsigned long)h,
02623                         free ? "FREE  " : "ALLOC ",
02624                         (unsigned long)phys_location,
02625                         (unsigned long)size << 10UL); /* KB -> bytes */
02626             }
02627         }
02628     }
02629 
02630     DEBUG_EndPagedContent();
02631 }
02632 
02633 static void LogDOSKernMem(void) {
02634     char tmp[192];
02635 
02636     if (dos_kernel_disabled) {
02637         LOG(LOG_MISC,LOG_ERROR)("Cannot enumerate DOS kernel memory while DOS kernel is inactive.");
02638         return;
02639     }
02640 
02641     DEBUG_BeginPagedContent();
02642 
02643     LOG(LOG_MISC,LOG_ERROR)("DOS kernel memory blocks:");
02644     LOG(LOG_MISC,LOG_ERROR)("Seg      Size (bytes)     What");
02645     for (auto i=DOS_GetMemLog.begin();i!=DOS_GetMemLog.end();i++) {
02646         sprintf(tmp,"%04x     %8lu     ",
02647                 (unsigned int)(i->segbase),
02648                 (unsigned long)(i->pages << 4UL));
02649 
02650         LOG(LOG_MISC,LOG_ERROR)("%s    %s",tmp,i->who.c_str());
02651     }
02652 
02653     DEBUG_EndPagedContent();
02654 }
02655 
02656 // Display the content of all Memory Control Blocks.
02657 static void LogMCBS(void)
02658 {
02659     if (dos_kernel_disabled) {
02660         LOG(LOG_MISC,LOG_ERROR)("Cannot enumerate MCB list while DOS kernel is inactive.");
02661         return;
02662     }
02663 
02664     DEBUG_BeginPagedContent();
02665 
02666     LOG(LOG_MISC,LOG_ERROR)("MCB Seg  Size (bytes)  PSP Seg (notes)  Filename");
02667     LOG(LOG_MISC,LOG_ERROR)("Conventional memory:");
02668     LogMCBChain(dos.firstMCB);
02669 
02670     if (dos_infoblock.GetStartOfUMBChain() != 0xFFFF) {
02671         LOG(LOG_MISC,LOG_ERROR)("Upper memory:");
02672         LogMCBChain(dos_infoblock.GetStartOfUMBChain());
02673     }
02674 
02675     DEBUG_EndPagedContent();
02676 }
02677 
02678 static void LogGDT(void)
02679 {
02680         char out1[512];
02681         Descriptor desc;
02682         Bitu length = cpu.gdt.GetLimit();
02683         PhysPt address = cpu.gdt.GetBase();
02684         PhysPt max         = address + length;
02685         Bitu i = 0;
02686 
02687     DEBUG_BeginPagedContent();
02688 
02689         LOG(LOG_MISC,LOG_ERROR)("GDT Base:%08lX Limit:%08lX",(unsigned long)address,(unsigned long)length);
02690         while (address<max) {
02691                 desc.Load(address);
02692                 sprintf(out1,"%04X: b:%08lX type: %02X parbg",(int)(i<<3),(unsigned long)desc.GetBase(),desc.saved.seg.type);
02693                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02694                 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);
02695                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02696                 address+=8; i++;
02697         }
02698 
02699     DEBUG_EndPagedContent();
02700 }
02701 
02702 static void LogLDT(void) {
02703         char out1[512];
02704         Descriptor desc;
02705         Bitu ldtSelector = cpu.gdt.SLDT();
02706         if (!cpu.gdt.GetDescriptor(ldtSelector,desc)) return;
02707         Bitu length = desc.GetLimit();
02708         PhysPt address = desc.GetBase();
02709         PhysPt max         = address + length;
02710         Bitu i = 0;
02711 
02712     DEBUG_BeginPagedContent();
02713 
02714         LOG(LOG_MISC,LOG_ERROR)("LDT Base:%08lX Limit:%08lX",(unsigned long)address,(unsigned long)length);
02715         while (address<max) {
02716                 desc.Load(address);
02717                 sprintf(out1,"%04X: b:%08lX type: %02X parbg",(int)((i<<3)|4),(unsigned long)desc.GetBase(),desc.saved.seg.type);
02718                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02719                 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);
02720                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02721                 address+=8; i++;
02722         }
02723 
02724     DEBUG_EndPagedContent();
02725 }
02726 
02727 static void LogIDT(void) {
02728         char out1[512];
02729         Descriptor desc;
02730         Bitu address = 0;
02731 
02732     DEBUG_BeginPagedContent();
02733 
02734         while (address<256*8) {
02735                 if (cpu.idt.GetDescriptor(address,desc)) {
02736                         sprintf(out1,"%04X: sel:%04X off:%02X",(unsigned int)(address/8),(int)desc.GetSelector(),(int)desc.GetOffset());
02737                         LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02738                 }
02739                 address+=8;
02740         }
02741 
02742     DEBUG_EndPagedContent();
02743 }
02744 
02745 void LogPages(char* selname) {
02746         char out1[512];
02747 
02748     DEBUG_BeginPagedContent();
02749 
02750         if (paging.enabled) {
02751                 Bitu sel = GetHexValue(selname,selname);
02752                 if ((sel==0x00) && ((*selname==0) || (*selname=='*'))) {
02753                         for (unsigned int i=0; i<0xfffff; i++) {
02754                                 Bitu table_addr=((Bitu)paging.base.page<<12u)+(i >> 10u)*4u;
02755                                 X86PageEntry table;
02756                                 table.load=phys_readd(table_addr);
02757                                 if (table.block.p) {
02758                                         X86PageEntry entry;
02759                                         Bitu entry_addr=((Bitu)table.block.base<<12u)+(i & 0x3ffu)*4u;
02760                                         entry.load=phys_readd(entry_addr);
02761                                         if (entry.block.p) {
02762                                                 sprintf(out1,"page %05Xxxx -> %04Xxxx  flags [uw] %x:%x::%x:%x [d=%x|a=%x]",
02763                                                         i,entry.block.base,entry.block.us,table.block.us,
02764                                                         entry.block.wr,table.block.wr,entry.block.d,entry.block.a);
02765                                                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02766                                         }
02767                                 }
02768                         }
02769                 } else {
02770                         Bitu table_addr=(paging.base.page<<12u)+(sel >> 10u)*4u;
02771                         X86PageEntry table;
02772                         table.load=phys_readd(table_addr);
02773                         if (table.block.p) {
02774                                 X86PageEntry entry;
02775                                 Bitu entry_addr=((Bitu)table.block.base<<12u)+(sel & 0x3ffu)*4u;
02776                                 entry.load=phys_readd(entry_addr);
02777                                 sprintf(out1,"page %05lXxxx -> %04lXxxx  flags [puw] %x:%x::%x:%x::%x:%x",
02778                                         (unsigned long)sel,
02779                                         (unsigned long)entry.block.base,
02780                                         entry.block.p,table.block.p,entry.block.us,table.block.us,entry.block.wr,table.block.wr);
02781                                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02782                         } else {
02783                                 sprintf(out1,"pagetable %03X not present, flags [puw] %x::%x::%x",
02784                                         (int)(sel >> 10),
02785                                         (int)table.block.p,
02786                                         (int)table.block.us,
02787                                         (int)table.block.wr);
02788                                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02789                         }
02790                 }
02791         }
02792 
02793     DEBUG_EndPagedContent();
02794 }
02795 
02796 static void LogCPUInfo(void) {
02797         char out1[512];
02798 
02799     DEBUG_BeginPagedContent();
02800 
02801         sprintf(out1,"cr0:%08lX cr2:%08lX cr3:%08lX  cpl=%lx",
02802                 (unsigned long)cpu.cr0,
02803                 (unsigned long)paging.cr2,
02804                 (unsigned long)paging.cr3,
02805                 (unsigned long)cpu.cpl);
02806         LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02807         sprintf(out1,"eflags:%08lX [vm=%x iopl=%x nt=%x]",
02808                 (unsigned long)reg_flags,
02809                 (int)(GETFLAG(VM)>>17),
02810                 (int)(GETFLAG(IOPL)>>12),
02811                 (int)(GETFLAG(NT)>>14));
02812         LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02813         sprintf(out1,"GDT base=%08lX limit=%08lX",
02814                 (unsigned long)cpu.gdt.GetBase(),
02815                 (unsigned long)cpu.gdt.GetLimit());
02816         LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02817         sprintf(out1,"IDT base=%08lX limit=%08lX",
02818                 (unsigned long)cpu.idt.GetBase(),
02819                 (unsigned long)cpu.idt.GetLimit());
02820         LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02821 
02822         Bitu sel=CPU_STR();
02823         Descriptor desc;
02824         if (cpu.gdt.GetDescriptor(sel,desc)) {
02825                 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);
02826                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02827         }
02828         sel=CPU_SLDT();
02829         if (cpu.gdt.GetDescriptor(sel,desc)) {
02830                 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);
02831                 LOG(LOG_MISC,LOG_ERROR)("%s",out1);
02832         }
02833 
02834     DEBUG_EndPagedContent();
02835 }
02836 
02837 #if C_HEAVY_DEBUG
02838 static void LogInstruction(Bit16u segValue, Bit32u eipValue,  ofstream& out) {
02839         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 };
02840 
02841         PhysPt start = GetAddress(segValue,eipValue);
02842         char dline[200];Bitu size;
02843         size = DasmI386(dline, start, reg_eip, cpu.code.big);
02844         char* res = empty;
02845         if (showExtend && (cpuLogType > 0) ) {
02846                 res = AnalyzeInstruction(dline,false);
02847                 if (!res || !(*res)) res = empty;
02848                 Bitu reslen = strlen(res);
02849                 if (reslen<22) for (Bitu i=0; i<22-reslen; i++) res[reslen+i] = ' '; res[22] = 0;
02850         };
02851         Bitu len = strlen(dline);
02852         if (len<30) for (Bitu i=0; i<30-len; i++) dline[len + i] = ' '; dline[30] = 0;
02853 
02854         // Get register values
02855 
02856         if(cpuLogType == 0) {
02857                 out << setw(4) << SegValue(cs) << ":" << setw(4) << reg_eip << "  " << dline;
02858         } else if (cpuLogType == 1) {
02859                 out << setw(4) << SegValue(cs) << ":" << setw(8) << reg_eip << "  " << dline << "  " << res;
02860         } else if (cpuLogType == 2) {
02861                 char ibytes[200]="";    char tmpc[200];
02862                 for (Bitu i=0; i<size; i++) {
02863                         Bit8u value;
02864                         if (mem_readb_checked(start+i,&value)) sprintf(tmpc,"%s","?? ");
02865                         else sprintf(tmpc,"%02X ",value);
02866                         strcat(ibytes,tmpc);
02867                 }
02868                 len = strlen(ibytes);
02869                 if (len<21) { for (Bitu i=0; i<21-len; i++) ibytes[len + i] =' '; ibytes[21]=0;} //NOTE THE BRACKETS
02870                 out << setw(4) << SegValue(cs) << ":" << setw(8) << reg_eip << "  " << dline << "  " << res << "  " << ibytes;
02871         }
02872    
02873         out << " EAX:" << setw(8) << reg_eax << " EBX:" << setw(8) << reg_ebx 
02874             << " ECX:" << setw(8) << reg_ecx << " EDX:" << setw(8) << reg_edx
02875             << " ESI:" << setw(8) << reg_esi << " EDI:" << setw(8) << reg_edi 
02876             << " EBP:" << setw(8) << reg_ebp << " ESP:" << setw(8) << reg_esp 
02877             << " DS:"  << setw(4) << SegValue(ds)<< " ES:"  << setw(4) << SegValue(es);
02878 
02879         if(cpuLogType == 0) {
02880                 out << " SS:"  << setw(4) << SegValue(ss) << " C"  << (get_CF()>0)  << " Z"   << (get_ZF()>0)  
02881                     << " S" << (get_SF()>0) << " O"  << (get_OF()>0) << " I"  << GETFLAGBOOL(IF);
02882         } else {
02883                 out << " FS:"  << setw(4) << SegValue(fs) << " GS:"  << setw(4) << SegValue(gs)
02884                     << " SS:"  << setw(4) << SegValue(ss)
02885                     << " CF:"  << (get_CF()>0)  << " ZF:"   << (get_ZF()>0)  << " SF:"  << (get_SF()>0)
02886                     << " OF:"  << (get_OF()>0)  << " AF:"   << (get_AF()>0)  << " PF:"  << (get_PF()>0)
02887                     << " IF:"  << GETFLAGBOOL(IF);
02888         }
02889         if(cpuLogType == 2) {
02890                 out << " TF:" << GETFLAGBOOL(TF) << " VM:" << GETFLAGBOOL(VM) <<" FLG:" << setw(8) << reg_flags 
02891                     << " CR0:" << setw(8) << cpu.cr0;   
02892         }
02893         out << endl;
02894 }
02895 #endif
02896 
02897 #if 0
02898 // DEBUG.COM stuff
02899 
02900 class DEBUG : public Program {
02901 public:
02902         DEBUG()         { pDebugcom     = this; active = false; };
02903         ~DEBUG()        { pDebugcom     = 0; };
02904 
02905         bool IsActive() { return active; };
02906 
02907         void Run(void)
02908         {
02909                 if(cmd->FindExist("/NOMOUSE",false)) {
02910                         real_writed(0,0x33<<2,0);
02911                         return;
02912                 }
02913            
02914                 char filename[128];
02915                 char args[256+1];
02916         
02917                 cmd->FindCommand(1,temp_line);
02918                 safe_strncpy(filename,temp_line.c_str(),128);
02919                 // Read commandline
02920                 Bit16u i        =2;
02921                 args[0]         = 0;
02922                 for (;cmd->FindCommand(i++,temp_line)==true;) {
02923                         strncat(args,temp_line.c_str(),256);
02924                         strncat(args," ",256);
02925                 }
02926                 // Start new shell and execute prog             
02927                 active = true;
02928                 // Save cpu state....
02929                 Bit16u oldcs    = SegValue(cs);
02930                 Bit32u oldeip   = reg_eip;      
02931                 Bit16u oldss    = SegValue(ss);
02932                 Bit32u oldesp   = reg_esp;
02933 
02934                 // Workaround : Allocate Stack Space
02935                 Bit16u segment;
02936                 Bit16u size = 0x200 / 0x10;
02937                 if (DOS_AllocateMemory(&segment,&size)) {
02938                         SegSet16(ss,segment);
02939                         reg_sp = 0x200;
02940                         // Start shell
02941                         DOS_Shell shell;
02942                         shell.Execute(filename,args);
02943                         DOS_FreeMemory(segment);
02944                 }
02945                 // set old reg values
02946                 SegSet16(ss,oldss);
02947                 reg_esp = oldesp;
02948                 SegSet16(cs,oldcs);
02949                 reg_eip = oldeip;
02950         };
02951 
02952 private:
02953         bool    active;
02954 };
02955 #endif
02956 
02957 #if C_DEBUG
02958 extern bool debugger_break_on_exec;
02959 #endif
02960 
02961 void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off)
02962 {
02963 #if C_DEBUG
02964     if (debugger_break_on_exec) {
02965                 CBreakpoint::AddBreakpoint(seg,off,true);               
02966                 CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);     
02967         debugger_break_on_exec = false;
02968     }
02969 #endif
02970 #if 0
02971         if (pDebugcom && pDebugcom->IsActive()) {
02972                 CBreakpoint::AddBreakpoint(seg,off,true);               
02973                 CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);     
02974                 pDebugcom = 0;
02975         };
02976 #endif
02977 }
02978 
02979 Bitu DEBUG_EnableDebugger(void)
02980 {
02981         exitLoop = true;
02982         DEBUG_Enable(true);
02983         CPU_Cycles=CPU_CycleLeft=0;
02984         return 0;
02985 }
02986 
02987 // INIT 
02988 
02989 void DBGBlock::set_data_view(unsigned int view) {
02990     void DrawBars(void);
02991 
02992     if (data_view != view) {
02993         data_view  = view;
02994 
02995         switch (view) {
02996             case DATV_SEGMENTED:
02997                 win_title[DBGBlock::WINI_DATA] = "Data view (segmented)";
02998                 break;
02999             case DATV_VIRTUAL:
03000                 win_title[DBGBlock::WINI_DATA] = "Data view (virtual)";
03001                 break;
03002             case DATV_PHYSICAL:
03003                 win_title[DBGBlock::WINI_DATA] = "Data view (physical)";
03004                 break;
03005         }
03006 
03007         DrawBars();
03008     }
03009 }
03010 
03011 void DEBUG_SetupConsole(void) {
03012         if (dbg.win_main == NULL) {
03013                 LOG(LOG_MISC,LOG_DEBUG)("DEBUG_SetupConsole initializing GUI");
03014 
03015         dbg.set_data_view(DBGBlock::DATV_SEGMENTED);
03016 
03017 #ifdef WIN32
03018                 WIN32_Console();
03019 #else
03020                 tcgetattr(0,&consolesettings);
03021 #endif  
03022                 //      dbg.active_win=3;
03023                 /* Start the Debug Gui */
03024                 DBGUI_StartUp();
03025         }
03026 }
03027 
03028 void DEBUG_ShutDown(Section * /*sec*/) {
03029         CBreakpoint::DeleteAll();
03030         CDebugVar::DeleteAll();
03031         if (dbg.win_main != NULL) {
03032                 LOG(LOG_MISC,LOG_DEBUG)("DEBUG_Shutdown freeing ncurses state");
03033                 curs_set(old_cursor_state);
03034 
03035         void DEBUG_GUI_DestroySubWindows(void);
03036         DEBUG_GUI_DestroySubWindows();
03037 
03038 //      if (dbg.win_main) delwin(dbg.win_main);
03039                 dbg.win_main = NULL;
03040 
03041         endwin();
03042 
03043 #ifndef WIN32
03044                 tcsetattr(0,TCSANOW,&consolesettings);
03045 #endif
03046         }
03047 }
03048 
03049 Bitu debugCallback;
03050 
03051 void DEBUG_ReinitCallback(void) {
03052     /* this is REQUIRED after loading a custom BIOS */
03053         debugCallback=CALLBACK_Allocate();
03054         CALLBACK_Setup(debugCallback,DEBUG_EnableDebugger,CB_RETF,"debugger");
03055 }
03056 
03057 void DEBUG_Init() {
03058         DOSBoxMenu::item *item;
03059 
03060         LOG(LOG_MISC,LOG_DEBUG)("Initializing debug system");
03061 
03062         /* Add some keyhandlers */
03063         #if defined(MACOSX)
03064                 // OSX NOTE: ALT-F12 to launch debugger. pause maps to F16 on macOS,
03065                 // which is not easy to input on a modern mac laptop
03066                 MAPPER_AddHandler(DEBUG_Enable,MK_f12,MMOD2,"debugger","Debugger", &item);
03067         #else
03068                 MAPPER_AddHandler(DEBUG_Enable,MK_pause,MMOD2,"debugger","Debugger",&item);
03069         #endif
03070         item->set_text("Debugger");
03071         /* Reset code overview and input line */
03072         memset((void*)&codeViewData,0,sizeof(codeViewData));
03073         /* Setup callback */
03074         debugCallback=CALLBACK_Allocate();
03075         CALLBACK_Setup(debugCallback,DEBUG_EnableDebugger,CB_RETF,"debugger");
03076 
03077 #if defined(MACOSX) || defined(LINUX)
03078         /* Mac OS X does not have a console for us to just allocate on a whim like Windows does.
03079            So the debugger interface is useless UNLESS the user has started us from a terminal
03080            (whether over SSH or from the Terminal app).
03081        
03082        Linux/X11 also does not have a console we can allocate on a whim. You either run
03083        this program from XTerm for the debugger, or not. */
03084     bool allow = true;
03085 
03086     if (!isatty(0) || !isatty(1) || !isatty(2))
03087             allow = false;
03088 
03089     mainMenu.get_item("mapper_debugger").enable(allow).refresh_item(mainMenu);
03090 #endif
03091 
03092         /* shutdown function */
03093         AddExitFunction(AddExitFunctionFuncPair(DEBUG_ShutDown));
03094 }
03095 
03096 // DEBUGGING VAR STUFF
03097 
03098 void CDebugVar::InsertVariable(char* name, PhysPt adr)
03099 {
03100         varList.push_back(new CDebugVar(name,adr));
03101 }
03102 
03103 void CDebugVar::DeleteAll(void) 
03104 {
03105         std::list<CDebugVar*>::iterator i;
03106         CDebugVar* bp;
03107         for(i=varList.begin(); i != varList.end(); i++) {
03108                 bp = static_cast<CDebugVar*>(*i);
03109                 delete bp;
03110         }
03111         (varList.clear)();
03112 }
03113 
03114 CDebugVar* CDebugVar::FindVar(PhysPt pt)
03115 {
03116         std::list<CDebugVar*>::iterator i;
03117         CDebugVar* bp;
03118         for(i=varList.begin(); i != varList.end(); i++) {
03119                 bp = static_cast<CDebugVar*>(*i);
03120                 if (bp->GetAdr()==pt) return bp;
03121         }
03122         return 0;
03123 }
03124 
03125 bool CDebugVar::SaveVars(char* name) {
03126         if (varList.size()>65535) return false;
03127 
03128         FILE* f = fopen(name,"wb+");
03129         if (!f) return false;
03130 
03131         // write number of vars
03132         Bit16u num = (Bit16u)varList.size();
03133         fwrite(&num,1,sizeof(num),f);
03134 
03135         std::list<CDebugVar*>::iterator i;
03136         CDebugVar* bp;
03137         for(i=varList.begin(); i != varList.end(); i++) {
03138                 bp = static_cast<CDebugVar*>(*i);
03139                 // name
03140                 fwrite(bp->GetName(),1,16,f);
03141                 // adr
03142                 PhysPt adr = bp->GetAdr();
03143                 fwrite(&adr,1,sizeof(adr),f);
03144         };
03145         fclose(f);
03146         return true;
03147 }
03148 
03149 bool CDebugVar::LoadVars(char* name)
03150 {
03151         FILE* f = fopen(name,"rb");
03152         if (!f) return false;
03153 
03154         // read number of vars
03155         Bit16u num;
03156         if (fread(&num,sizeof(num),1,f) != 1) return false;
03157 
03158         for (Bit16u i=0; i<num; i++) {
03159                 char name[16];
03160                 // name
03161                 if (fread(name,16,1,f) != 1) break;
03162                 // adr
03163                 PhysPt adr;
03164                 if (fread(&adr,sizeof(adr),1,f) != 1) break;
03165                 // insert
03166                 InsertVariable(name,adr);
03167         };
03168         fclose(f);
03169         return true;
03170 }
03171 
03172 static void SaveMemory(Bit16u seg, Bit32u ofs1, Bit32u num) {
03173         FILE* f = fopen("MEMDUMP.TXT","wt");
03174         if (!f) {
03175                 DEBUG_ShowMsg("DEBUG: Memory dump failed.\n");
03176                 return;
03177         }
03178         
03179         char buffer[128];
03180         char temp[16];
03181 
03182         while (num>16) {
03183                 sprintf(buffer,"%04X:%04X   ",seg,ofs1);
03184                 for (Bit16u x=0; x<16; x++) {
03185                         Bit8u value;
03186                         if (mem_readb_checked((PhysPt)GetAddress(seg,ofs1+x),&value)) sprintf(temp,"%s","?? ");
03187                         else sprintf(temp,"%02X ",value);
03188                         strcat(buffer,temp);
03189                 }
03190                 ofs1+=16;
03191                 num-=16;
03192 
03193                 fprintf(f,"%s\n",buffer);
03194         }
03195         if (num>0) {
03196                 sprintf(buffer,"%04X:%04X   ",seg,ofs1);
03197                 for (Bit16u x=0; x<num; x++) {
03198                         Bit8u value;
03199                         if (mem_readb_checked((PhysPt)GetAddress(seg,ofs1+x),&value)) sprintf(temp,"%s","?? ");
03200                         else sprintf(temp,"%02X ",value);
03201                         strcat(buffer,temp);
03202                 }
03203                 fprintf(f,"%s\n",buffer);
03204         }
03205         fclose(f);
03206         DEBUG_ShowMsg("DEBUG: Memory dump success.\n");
03207 }
03208 
03209 static void SaveMemoryBin(Bit16u seg, Bit32u ofs1, Bit32u num) {
03210         FILE* f = fopen("MEMDUMP.BIN","wb");
03211         if (!f) {
03212                 DEBUG_ShowMsg("DEBUG: Memory binary dump failed.\n");
03213                 return;
03214         }
03215 
03216         for (Bitu x = 0; x < num;x++) {
03217                 Bit8u val;
03218                 if (mem_readb_checked((PhysPt)GetAddress(seg,ofs1+x),&val)) val=0;
03219                 fwrite(&val,1,1,f);
03220         }
03221 
03222         fclose(f);
03223         DEBUG_ShowMsg("DEBUG: Memory dump binary success.\n");
03224 }
03225 
03226 static void OutputVecTable(char* filename) {
03227         FILE* f = fopen(filename, "wt");
03228         if (!f)
03229         {
03230                 DEBUG_ShowMsg("DEBUG: Output of interrupt vector table failed.\n");
03231                 return;
03232         }
03233 
03234         for (unsigned int i=0; i<256; i++)
03235                 fprintf(f,"INT %02X:  %04X:%04X\n", i, mem_readw(i * 4u + 2u), mem_readw(i * 4u));
03236 
03237         fclose(f);
03238         DEBUG_ShowMsg("DEBUG: Interrupt vector table written to %s.\n", filename);
03239 }
03240 
03241 #define DEBUG_VAR_BUF_LEN 16
03242 static void DrawVariables(void) {
03243         if (CDebugVar::varList.empty()) return;
03244 
03245         std::list<CDebugVar*>::iterator i;
03246         CDebugVar *dv;
03247         char buffer[DEBUG_VAR_BUF_LEN];
03248 
03249         int idx = 0;
03250         for(i=CDebugVar::varList.begin(); i != CDebugVar::varList.end(); i++, idx++) {
03251 
03252                 if (idx == 4*3) {
03253                         /* too many variables */
03254                         break;
03255                 }
03256 
03257                 dv = static_cast<CDebugVar*>(*i);
03258 
03259                 Bit16u value;
03260                 if (mem_readw_checked(dv->GetAdr(),&value))
03261                         snprintf(buffer,DEBUG_VAR_BUF_LEN, "%s", "??????");
03262                 else
03263                         snprintf(buffer,DEBUG_VAR_BUF_LEN, "0x%04x", value);
03264 
03265                 int y = idx / 3;
03266                 int x = (idx % 3) * 26;
03267                 mvwprintw(dbg.win_var, y, x, dv->GetName());
03268                 mvwprintw(dbg.win_var, y,  (x + DEBUG_VAR_BUF_LEN + 1) , buffer);
03269         }
03270 
03271         wrefresh(dbg.win_var);
03272 }
03273 #undef DEBUG_VAR_BUF_LEN
03274 // HEAVY DEBUGGING STUFF
03275 
03276 #if C_HEAVY_DEBUG
03277 
03278 const Bit32u LOGCPUMAX = 20000;
03279 
03280 static Bit32u logCount = 0;
03281 
03282 struct TLogInst {
03283         Bit16u s_cs;
03284         Bit32u eip;
03285         Bit32u eax;
03286         Bit32u ebx;
03287         Bit32u ecx;
03288         Bit32u edx;
03289         Bit32u esi;
03290         Bit32u edi;
03291         Bit32u ebp;
03292         Bit32u esp;
03293         Bit16u s_ds;
03294         Bit16u s_es;
03295         Bit16u s_fs;
03296         Bit16u s_gs;
03297         Bit16u s_ss;
03298         bool c;
03299         bool z;
03300         bool s;
03301         bool o;
03302         bool a;
03303         bool p;
03304         bool i;
03305         char dline[31];
03306         char res[23];
03307 };
03308 
03309 TLogInst logInst[LOGCPUMAX];
03310 
03311 void DEBUG_HeavyLogInstruction(void) {
03312 
03313         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 };
03314 
03315         PhysPt start = GetAddress(SegValue(cs),reg_eip);
03316         char dline[200];
03317         DasmI386(dline, start, reg_eip, cpu.code.big);
03318         char* res = empty;
03319         if (showExtend) {
03320                 res = AnalyzeInstruction(dline,false);
03321                 if (!res || !(*res)) res = empty;
03322                 Bitu reslen = strlen(res);
03323                 if (reslen<22) for (Bitu i=0; i<22-reslen; i++) res[reslen+i] = ' '; res[22] = 0;
03324         };
03325 
03326         Bitu len = strlen(dline);
03327         if (len < 30) for (Bitu i=0; i < 30-len; i++) dline[len+i] = ' ';
03328         dline[30] = 0;
03329 
03330         TLogInst & inst = logInst[logCount];
03331         strcpy(inst.dline,dline);
03332         inst.s_cs = SegValue(cs);
03333         inst.eip  = reg_eip;
03334         strcpy(inst.res,res);
03335         inst.eax  = reg_eax;
03336         inst.ebx  = reg_ebx;
03337         inst.ecx  = reg_ecx;
03338         inst.edx  = reg_edx;
03339         inst.esi  = reg_esi;
03340         inst.edi  = reg_edi;
03341         inst.ebp  = reg_ebp;
03342         inst.esp  = reg_esp;
03343         inst.s_ds = SegValue(ds);
03344         inst.s_es = SegValue(es);
03345         inst.s_fs = SegValue(fs);
03346         inst.s_gs = SegValue(gs);
03347         inst.s_ss = SegValue(ss);
03348         inst.c    = get_CF()>0;
03349         inst.z    = get_ZF()>0;
03350         inst.s    = get_SF()>0;
03351         inst.o    = get_OF()>0;
03352         inst.a    = get_AF()>0;
03353         inst.p    = get_PF()>0;
03354         inst.i    = GETFLAGBOOL(IF);
03355 
03356         if (++logCount >= LOGCPUMAX) logCount = 0;
03357 }
03358 
03359 void DEBUG_HeavyWriteLogInstruction(void) {
03360         if (!logHeavy) return;
03361         logHeavy = false;
03362         
03363         DEBUG_ShowMsg("DEBUG: Creating cpu log LOGCPU_INT_CD.TXT\n");
03364 
03365         ofstream out("LOGCPU_INT_CD.TXT");
03366         if (!out.is_open()) {
03367                 DEBUG_ShowMsg("DEBUG: Failed.\n");      
03368                 return;
03369         }
03370         out << hex << noshowbase << setfill('0') << uppercase;
03371         Bit32u startLog = logCount;
03372         do {
03373                 // Write Instructions
03374                 TLogInst & inst = logInst[startLog];
03375                 out << setw(4) << inst.s_cs << ":" << setw(8) << inst.eip << "  " 
03376                     << inst.dline << "  " << inst.res << " EAX:" << setw(8)<< inst.eax
03377                     << " EBX:" << setw(8) << inst.ebx << " ECX:" << setw(8) << inst.ecx
03378                     << " EDX:" << setw(8) << inst.edx << " ESI:" << setw(8) << inst.esi
03379                     << " EDI:" << setw(8) << inst.edi << " EBP:" << setw(8) << inst.ebp
03380                     << " ESP:" << setw(8) << inst.esp << " DS:"  << setw(4) << inst.s_ds
03381                     << " ES:"  << setw(4) << inst.s_es<< " FS:"  << setw(4) << inst.s_fs
03382                     << " GS:"  << setw(4) << inst.s_gs<< " SS:"  << setw(4) << inst.s_ss
03383                     << " CF:"  << inst.c  << " ZF:"   << inst.z  << " SF:"  << inst.s
03384                     << " OF:"  << inst.o  << " AF:"   << inst.a  << " PF:"  << inst.p
03385                     << " IF:"  << inst.i  << endl;
03386 
03387 /*              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",
03388                         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,
03389                         logInst[startLog].s_ds,logInst[startLog].s_es,logInst[startLog].s_fs,logInst[startLog].s_gs,logInst[startLog].s_ss,
03390                         logInst[startLog].c,logInst[startLog].z,logInst[startLog].s,logInst[startLog].o,logInst[startLog].a,logInst[startLog].p,logInst[startLog].i);*/
03391                 if (++startLog >= LOGCPUMAX) startLog = 0;
03392         } while (startLog != logCount);
03393         
03394         out.close();
03395         DEBUG_ShowMsg("DEBUG: Done.\n");        
03396 }
03397 
03398 bool DEBUG_HeavyIsBreakpoint(void) {
03399         static Bitu zero_count = 0;
03400         if (cpuLog) {
03401                 if (cpuLogCounter>0) {
03402                         LogInstruction(SegValue(cs),reg_eip,cpuLogFile);
03403                         cpuLogCounter--;
03404                 }
03405                 if (cpuLogCounter<=0) {
03406                         cpuLogFile.close();
03407                         DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT created\n");
03408                         cpuLog = false;
03409                         DEBUG_EnableDebugger();
03410                         return true;
03411                 }
03412         }
03413         // LogInstruction
03414         if (logHeavy) DEBUG_HeavyLogInstruction();
03415         if (zeroProtect) {
03416                 Bit32u value=0;
03417                 if (!mem_readd_checked(SegPhys(cs)+reg_eip,&value)) {
03418                         if (value == 0) zero_count++;
03419                         else zero_count = 0;
03420                 }
03421                 if (GCC_UNLIKELY(zero_count == 10)) E_Exit("running zeroed code");
03422         }
03423 
03424         if (skipFirstInstruction) {
03425                 skipFirstInstruction = false;
03426                 return false;
03427         }
03428         if (CBreakpoint::CheckBreakpoint(SegValue(cs),reg_eip)) {
03429                 return true;    
03430         }
03431         return false;
03432 }
03433 
03434 /* this is for the BIOS, to stop the log upon BIOS POST. */
03435 void DEBUG_StopLog(void) {
03436         if (cpuLog) {
03437         cpuLogCounter = 0;
03438         cpuLogFile.close();
03439         DEBUG_ShowMsg("DEBUG: cpu log LOGCPU.TXT stopped\n");
03440         cpuLog = false;
03441     }
03442 }
03443 
03444 #endif // HEAVY DEBUG
03445 
03446 
03447 #endif // DEBUG
03448 
03449