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