2009-05-02 23:03:37 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2002 The DOSBox Team
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
#include "programs.h"
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#include <string.h>
|
2009-05-02 23:12:18 +02:00
|
|
|
#include <list>
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#include "dosbox.h"
|
2009-05-02 23:12:18 +02:00
|
|
|
#if C_DEBUG
|
2009-05-02 23:03:37 +02:00
|
|
|
#include "debug.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "video.h"
|
|
|
|
#include "pic.h"
|
|
|
|
#include "keyboard.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "callback.h"
|
|
|
|
#include "inout.h"
|
|
|
|
#include "mixer.h"
|
|
|
|
#include "debug_inc.h"
|
2009-05-02 23:20:05 +02:00
|
|
|
#include "timer.h"
|
|
|
|
#include "..\shell\shell_inc.h"
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
void WIN32_Console();
|
|
|
|
#endif
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
// Forwards
|
|
|
|
static void DrawCode(void);
|
|
|
|
static bool DEBUG_Log_Loop(int count);
|
|
|
|
static void DEBUG_RaiseTimerIrq(void);
|
|
|
|
class DEBUG;
|
|
|
|
|
|
|
|
DEBUG* pDebugcom = 0;
|
|
|
|
bool exitLoop = false;
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
static struct {
|
|
|
|
Bit32u eax,ebx,ecx,edx,esi,edi,ebp,esp,eip;
|
|
|
|
} oldregs;
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
static Segment oldsegs[6];
|
|
|
|
static Flag_Info oldflags;
|
|
|
|
DBGBlock dbg;
|
|
|
|
static char input_line[256];
|
|
|
|
static Bitu input_count;
|
|
|
|
Bitu cycle_count;
|
|
|
|
static bool debugging;
|
|
|
|
static void SetColor(bool test) {
|
|
|
|
if (test) {
|
|
|
|
if (has_colors()) { wattrset(dbg.win_reg,COLOR_PAIR(PAIR_BYELLOW_BLACK));}
|
|
|
|
} else {
|
|
|
|
if (has_colors()) { wattrset(dbg.win_reg,0);}
|
|
|
|
}
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
|
|
|
|
struct SCodeViewData {
|
|
|
|
int cursorPos;
|
|
|
|
Bit16u firstInstSize;
|
|
|
|
Bit16u useCS;
|
|
|
|
Bit32u useEIPlast, useEIPmid;
|
|
|
|
Bit32u useEIP;
|
|
|
|
Bit16u cursorSeg;
|
|
|
|
Bit32u cursorOfs;
|
|
|
|
bool inputMode;
|
|
|
|
char inputStr[255];
|
|
|
|
|
|
|
|
} codeViewData;
|
|
|
|
|
|
|
|
static Bit16u dataSeg,dataOfs;
|
|
|
|
|
|
|
|
/********************/
|
|
|
|
/* Breakpoint stuff */
|
|
|
|
/********************/
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
bool skipFirstInstruction = false;
|
|
|
|
|
|
|
|
enum EBreakpoint { BKPNT_UNKNOWN, BKPNT_PHYSICAL, BKPNT_INTERRUPT };
|
2009-05-02 23:12:18 +02:00
|
|
|
|
|
|
|
#define BPINT_ALL 0x100
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
class CBreakpoint
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CBreakpoint (void) { location = 0; active = once = false; segment = 0; offset = 0; intNr = 0; ahValue = 0; type = BKPNT_UNKNOWN; };
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
void SetAddress (Bit16u seg, Bit32u off) { location = PhysMake(seg,off); type = BKPNT_PHYSICAL; segment = seg; offset = off; };
|
|
|
|
void SetAddress (PhysPt adr) { location = adr; type = BKPNT_PHYSICAL; };
|
|
|
|
void SetInt (Bit8u _intNr, Bit16u ah) { intNr = _intNr, ahValue = ah; type = BKPNT_INTERRUPT; };
|
|
|
|
void SetOnce (bool _once) { once = _once; };
|
|
|
|
|
|
|
|
bool IsActive (void) { return active; };
|
|
|
|
void Activate (bool _active);
|
|
|
|
|
|
|
|
EBreakpoint GetType (void) { return type; };
|
|
|
|
bool GetOnce (void) { return once; };
|
|
|
|
PhysPt GetLocation (void) { if (GetType()==BKPNT_PHYSICAL) return location; else return 0; };
|
|
|
|
Bit16u GetSegment (void) { return segment; };
|
|
|
|
Bit32u GetOffset (void) { return offset; };
|
|
|
|
Bit8u GetIntNr (void) { if (GetType()==BKPNT_INTERRUPT) return intNr; else return 0; };
|
|
|
|
Bit16u GetValue (void) { if (GetType()==BKPNT_INTERRUPT) return ahValue; else return 0; };
|
|
|
|
|
|
|
|
// statics
|
|
|
|
static CBreakpoint* AddBreakpoint (Bit16u seg, Bit32u off, bool once);
|
|
|
|
static CBreakpoint* AddIntBreakpoint (Bit8u intNum, Bit16u ah, bool once);
|
|
|
|
static void ActivateBreakpoints (PhysPt adr, bool activate);
|
|
|
|
static bool CheckBreakpoint (PhysPt adr);
|
|
|
|
static bool CheckIntBreakpoint (PhysPt adr, Bit8u intNr, Bit16u ahValue);
|
|
|
|
static bool IsBreakpoint (PhysPt where);
|
|
|
|
static bool IsBreakpointDrawn (PhysPt where);
|
|
|
|
static bool DeleteBreakpoint (PhysPt where);
|
|
|
|
static bool DeleteByIndex (Bit16u index);
|
|
|
|
static void DeleteAll (void);
|
|
|
|
static void ShowList (void);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
EBreakpoint type;
|
|
|
|
// Physical
|
|
|
|
PhysPt location;
|
|
|
|
Bit8u oldData;
|
|
|
|
Bit16u segment;
|
|
|
|
Bit32u offset;
|
|
|
|
// Int
|
|
|
|
Bit8u intNr;
|
|
|
|
Bit16u ahValue;
|
|
|
|
// Shared
|
|
|
|
bool active;
|
|
|
|
bool once;
|
|
|
|
|
|
|
|
static std::list<CBreakpoint*> BPoints;
|
|
|
|
static CBreakpoint* ignoreOnce;
|
|
|
|
};
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
void CBreakpoint::Activate(bool _active)
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
if (GetType()==BKPNT_PHYSICAL) {
|
|
|
|
#if !C_HEAVY_DEBUG
|
|
|
|
if (_active) {
|
|
|
|
// Set 0xCC and save old value
|
|
|
|
Bit8u data = mem_readb(location);
|
|
|
|
if (data!=0xCC) {
|
|
|
|
oldData = data;
|
|
|
|
mem_writeb(location,0xCC);
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
// Remove 0xCC and set old value
|
|
|
|
if (mem_readb (location)==0xCC) {
|
|
|
|
mem_writeb(location,oldData);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:20:05 +02:00
|
|
|
active = _active;
|
2009-05-02 23:03:37 +02:00
|
|
|
};
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
// Statics
|
|
|
|
std::list<CBreakpoint*> CBreakpoint::BPoints;
|
|
|
|
CBreakpoint* CBreakpoint::ignoreOnce = 0;
|
|
|
|
|
|
|
|
CBreakpoint* CBreakpoint::AddBreakpoint(Bit16u seg, Bit32u off, bool once)
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint* bp = new CBreakpoint();
|
|
|
|
bp->SetAddress (seg,off);
|
|
|
|
bp->SetOnce (once);
|
|
|
|
BPoints.push_front (bp);
|
|
|
|
return bp;
|
|
|
|
};
|
|
|
|
|
|
|
|
CBreakpoint* CBreakpoint::AddIntBreakpoint(Bit8u intNum, Bit16u ah, bool once)
|
|
|
|
{
|
|
|
|
CBreakpoint* bp = new CBreakpoint();
|
|
|
|
bp->SetInt (intNum,ah);
|
|
|
|
bp->SetOnce (once);
|
|
|
|
BPoints.push_front (bp);
|
|
|
|
return bp;
|
|
|
|
};
|
|
|
|
|
|
|
|
void CBreakpoint::ActivateBreakpoints(PhysPt adr, bool activate)
|
|
|
|
{
|
|
|
|
ignoreOnce = 0;
|
|
|
|
// activate all breakpoints
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
2009-05-02 23:12:18 +02:00
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
2009-05-02 23:20:05 +02:00
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
// Do not activate, when bp is an actual adress
|
|
|
|
if (activate && (bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
|
|
|
|
ignoreOnce = bp;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bp->Activate(activate);
|
|
|
|
};
|
|
|
|
};
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
bool CBreakpoint::CheckBreakpoint(PhysPt adr)
|
|
|
|
// Checks if breakpoint is valid an should stop execution
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
// if breakpoint is same address as started, it's not valid...
|
|
|
|
if (ignoreOnce) {
|
|
|
|
ignoreOnce->Activate(true);
|
|
|
|
ignoreOnce = 0;
|
|
|
|
}
|
|
|
|
// Search matching breakpoint
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
2009-05-02 23:12:18 +02:00
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
2009-05-02 23:20:05 +02:00
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
if ((bp->GetType()==BKPNT_PHYSICAL) && bp->IsActive() && (bp->GetLocation()==adr)) {
|
|
|
|
// Found,
|
|
|
|
if (bp->GetOnce()) {
|
|
|
|
// delete it, if it should only be used once
|
|
|
|
(BPoints.erase)(i);
|
|
|
|
bp->Activate(false);
|
|
|
|
delete bp;
|
|
|
|
}
|
|
|
|
return true;
|
2009-05-02 23:12:18 +02:00
|
|
|
};
|
2009-05-02 23:20:05 +02:00
|
|
|
};
|
|
|
|
return false;
|
|
|
|
};
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
bool CBreakpoint::CheckIntBreakpoint(PhysPt adr, Bit8u intNr, Bit16u ahValue)
|
|
|
|
// Checks if interrupt breakpoint is valid an should stop execution
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
// if breakpoint is same address as started, it's not valid...
|
|
|
|
if (ignoreOnce) {
|
|
|
|
ignoreOnce->Activate(true);
|
|
|
|
ignoreOnce = 0;
|
|
|
|
}
|
|
|
|
// Search matching breakpoint
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
2009-05-02 23:12:18 +02:00
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
2009-05-02 23:20:05 +02:00
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
if ((bp->GetType()==BKPNT_INTERRUPT) && bp->IsActive() && (bp->GetIntNr()==intNr)) {
|
|
|
|
if ((bp->GetValue()==BPINT_ALL) || (bp->GetValue()==ahValue)) {
|
|
|
|
// Found
|
|
|
|
if (bp->GetOnce()) {
|
|
|
|
// delete it, if it should only be used once
|
|
|
|
(BPoints.erase)(i);
|
|
|
|
bp->Activate(false);
|
|
|
|
delete bp;
|
|
|
|
}
|
|
|
|
return true;
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
};
|
2009-05-02 23:20:05 +02:00
|
|
|
};
|
|
|
|
return false;
|
|
|
|
};
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
void CBreakpoint::DeleteAll()
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
bp->Activate(false);
|
|
|
|
delete bp;
|
|
|
|
};
|
|
|
|
(BPoints.clear)();
|
|
|
|
};
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
bool CBreakpoint::DeleteByIndex(Bit16u index)
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
// Search matching breakpoint
|
|
|
|
int nr = 0;
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
|
|
|
if (nr==index) {
|
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
(BPoints.erase)(i);
|
|
|
|
bp->Activate(false);
|
|
|
|
delete bp;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
return false;
|
2009-05-02 23:12:18 +02:00
|
|
|
};
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
bool CBreakpoint::DeleteBreakpoint(PhysPt where)
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
// Search matching breakpoint
|
|
|
|
int nr = 0;
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
2009-05-02 23:12:18 +02:00
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
2009-05-02 23:20:05 +02:00
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==where)) {
|
|
|
|
(BPoints.erase)(i);
|
|
|
|
bp->Activate(false);
|
|
|
|
delete bp;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool CBreakpoint::IsBreakpoint(PhysPt adr)
|
|
|
|
// is there a breakpoint at address ?
|
|
|
|
{
|
|
|
|
// Search matching breakpoint
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
|
2009-05-02 23:12:18 +02:00
|
|
|
return true;
|
|
|
|
};
|
2009-05-02 23:20:05 +02:00
|
|
|
};
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool CBreakpoint::IsBreakpointDrawn(PhysPt adr)
|
|
|
|
// valid breakpoint, that should be drawn ?
|
|
|
|
{
|
|
|
|
// Search matching breakpoint
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
CBreakpoint* bp;
|
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
|
|
|
bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
if ((bp->GetType()==BKPNT_PHYSICAL) && (bp->GetLocation()==adr)) {
|
|
|
|
// Only draw, if breakpoint is not only once,
|
|
|
|
return !bp->GetOnce();
|
|
|
|
};
|
|
|
|
};
|
2009-05-02 23:12:18 +02:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
void CBreakpoint::ShowList(void)
|
|
|
|
{
|
|
|
|
// iterate list
|
|
|
|
int nr = 0;
|
|
|
|
std::list<CBreakpoint*>::iterator i;
|
|
|
|
for(i=BPoints.begin(); i != BPoints.end(); i++) {
|
|
|
|
CBreakpoint* bp = static_cast<CBreakpoint*>(*i);
|
|
|
|
if (bp->GetType()==BKPNT_PHYSICAL) {
|
|
|
|
PhysPt adr = bp->GetLocation();
|
|
|
|
|
|
|
|
wprintw(dbg.win_out,"%02X. BP %04X:%04X\n",nr,bp->GetSegment(),bp->GetOffset);
|
|
|
|
nr++;
|
|
|
|
} else if (bp->GetType()==BKPNT_INTERRUPT) {
|
|
|
|
if (bp->GetValue()==BPINT_ALL) wprintw(dbg.win_out,"%02X. BPINT %02X\n",nr,bp->GetIntNr());
|
|
|
|
else wprintw(dbg.win_out,"%02X. BPINT %02X AH=%02X\n",nr,bp->GetIntNr(),bp->GetValue());
|
|
|
|
nr++;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
wrefresh(dbg.win_out);
|
|
|
|
};
|
|
|
|
|
|
|
|
bool DEBUG_Breakpoint(void)
|
|
|
|
{
|
|
|
|
/* First get the phyiscal address and check for a set Breakpoint */
|
|
|
|
PhysPt where=SegPhys(cs)+reg_eip-1;
|
|
|
|
if (!CBreakpoint::CheckBreakpoint(where)) return false;
|
|
|
|
// Found. Breakpoint is valid
|
|
|
|
reg_eip -= 1;
|
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,false); // Deactivate all breakpoints
|
|
|
|
exitLoop = true;
|
|
|
|
DEBUG_Enable();
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool DEBUG_IntBreakpoint(Bit8u intNum)
|
|
|
|
{
|
|
|
|
/* First get the phyiscal address and check for a set Breakpoint */
|
|
|
|
PhysPt where=SegPhys(cs)+reg_eip-2;
|
|
|
|
if (!CBreakpoint::CheckIntBreakpoint(where,intNum,reg_ah)) return false;
|
|
|
|
// Found. Breakpoint is valid
|
|
|
|
reg_eip -= 2;
|
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,false); // Deactivate all breakpoints
|
|
|
|
exitLoop = true;
|
|
|
|
DEBUG_Enable();
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
static bool StepOver()
|
|
|
|
{
|
|
|
|
PhysPt start=Segs[cs].phys+reg_eip;
|
|
|
|
char dline[200];Bitu size;
|
|
|
|
size=DasmI386(dline, start, reg_eip, false);
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
if (strstr(dline,"call") || strstr(dline,"int") || strstr(dline,"loop") || strstr(dline,"rep")) {
|
|
|
|
CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip+size, true);
|
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip, true);
|
2009-05-02 23:12:18 +02:00
|
|
|
debugging=false;
|
|
|
|
DrawCode();
|
|
|
|
DOSBOX_SetNormalLoop();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
bool DEBUG_ExitLoop(void)
|
2009-05-02 23:12:18 +02:00
|
|
|
{
|
2009-05-02 23:20:05 +02:00
|
|
|
if (exitLoop) {
|
|
|
|
exitLoop = false;
|
|
|
|
return true;
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
2009-05-02 23:20:05 +02:00
|
|
|
return false;
|
2009-05-02 23:12:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/********************/
|
|
|
|
/* Draw windows */
|
|
|
|
/********************/
|
|
|
|
|
|
|
|
static void DrawData(void) {
|
|
|
|
|
|
|
|
Bit16u add = dataOfs;
|
|
|
|
/* Data win */
|
|
|
|
for (int y=0; y<8; y++) {
|
|
|
|
// Adress
|
|
|
|
mvwprintw (dbg.win_data,1+y,0,"%04X:%04X ",dataSeg,add);
|
|
|
|
for (int x=0; x<16; x++) {
|
|
|
|
Bit8u ch = real_readb(dataSeg,add);
|
|
|
|
mvwprintw (dbg.win_data,1+y,11+3*x,"%02X",ch);
|
|
|
|
if (ch<32) ch='.';
|
|
|
|
mvwprintw (dbg.win_data,1+y,60+x,"%c",ch);
|
|
|
|
add++;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
wrefresh(dbg.win_data);
|
|
|
|
};
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
static void DrawRegisters(void) {
|
|
|
|
/* Main Registers */
|
|
|
|
SetColor(reg_eax!=oldregs.eax);oldregs.eax=reg_eax;mvwprintw (dbg.win_reg,0,4,"%08X",reg_eax);
|
|
|
|
SetColor(reg_ebx!=oldregs.ebx);oldregs.ebx=reg_ebx;mvwprintw (dbg.win_reg,1,4,"%08X",reg_ebx);
|
|
|
|
SetColor(reg_ecx!=oldregs.ecx);oldregs.ecx=reg_ecx;mvwprintw (dbg.win_reg,2,4,"%08X",reg_ecx);
|
|
|
|
SetColor(reg_edx!=oldregs.edx);oldregs.edx=reg_edx;mvwprintw (dbg.win_reg,3,4,"%08X",reg_edx);
|
|
|
|
|
|
|
|
SetColor(reg_esi!=oldregs.esi);oldregs.esi=reg_esi;mvwprintw (dbg.win_reg,0,18,"%08X",reg_esi);
|
|
|
|
SetColor(reg_edi!=oldregs.edi);oldregs.edi=reg_edi;mvwprintw (dbg.win_reg,1,18,"%08X",reg_edi);
|
|
|
|
SetColor(reg_ebp!=oldregs.ebp);oldregs.ebp=reg_ebp;mvwprintw (dbg.win_reg,2,18,"%08X",reg_ebp);
|
|
|
|
SetColor(reg_esp!=oldregs.esp);oldregs.esp=reg_esp;mvwprintw (dbg.win_reg,3,18,"%08X",reg_esp);
|
|
|
|
SetColor(reg_eip!=oldregs.eip);oldregs.eip=reg_eip;mvwprintw (dbg.win_reg,1,42,"%08X",reg_eip);
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
SetColor(SegValue(ds)!=oldsegs[ds].val);oldsegs[ds].val=SegValue(ds);mvwprintw (dbg.win_reg,0,31,"%04X",SegValue(ds));
|
|
|
|
SetColor(SegValue(es)!=oldsegs[es].val);oldsegs[es].val=SegValue(es);mvwprintw (dbg.win_reg,0,41,"%04X",SegValue(es));
|
|
|
|
SetColor(SegValue(fs)!=oldsegs[fs].val);oldsegs[fs].val=SegValue(fs);mvwprintw (dbg.win_reg,0,51,"%04X",SegValue(fs));
|
|
|
|
SetColor(SegValue(gs)!=oldsegs[gs].val);oldsegs[gs].val=SegValue(gs);mvwprintw (dbg.win_reg,0,61,"%04X",SegValue(gs));
|
|
|
|
SetColor(SegValue(ss)!=oldsegs[ss].val);oldsegs[ss].val=SegValue(ss);mvwprintw (dbg.win_reg,0,71,"%04X",SegValue(ss));
|
|
|
|
SetColor(SegValue(cs)!=oldsegs[cs].val);oldsegs[cs].val=SegValue(cs);mvwprintw (dbg.win_reg,1,31,"%04X",SegValue(cs));
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
/*Individual flags*/
|
|
|
|
|
|
|
|
flags.cf=get_CF();SetColor(flags.cf!=oldflags.cf);oldflags.cf=flags.cf;mvwprintw (dbg.win_reg,1,53,"%01X",flags.cf);
|
|
|
|
flags.zf=get_ZF();SetColor(flags.zf!=oldflags.zf);oldflags.zf=flags.zf;mvwprintw (dbg.win_reg,1,56,"%01X",flags.zf);
|
|
|
|
flags.sf=get_SF();SetColor(flags.sf!=oldflags.sf);oldflags.sf=flags.sf;mvwprintw (dbg.win_reg,1,59,"%01X",flags.sf);
|
|
|
|
flags.of=get_OF();SetColor(flags.of!=oldflags.of);oldflags.of=flags.of;mvwprintw (dbg.win_reg,1,62,"%01X",flags.of);
|
|
|
|
flags.af=get_AF();SetColor(flags.af!=oldflags.af);oldflags.af=flags.af;mvwprintw (dbg.win_reg,1,65,"%01X",flags.af);
|
|
|
|
flags.pf=get_PF();SetColor(flags.pf!=oldflags.pf);oldflags.pf=flags.pf;mvwprintw (dbg.win_reg,1,68,"%01X",flags.pf);
|
|
|
|
|
|
|
|
|
|
|
|
SetColor(flags.df!=oldflags.df);oldflags.df=flags.df;mvwprintw (dbg.win_reg,1,71,"%01X",flags.df);
|
|
|
|
SetColor(flags.intf!=oldflags.intf);oldflags.intf=flags.intf;mvwprintw (dbg.win_reg,1,74,"%01X",flags.intf);
|
|
|
|
SetColor(flags.tf!=oldflags.tf);oldflags.tf=flags.tf;mvwprintw (dbg.win_reg,1,77,"%01X",flags.tf);
|
|
|
|
|
|
|
|
wattrset(dbg.win_reg,0);
|
|
|
|
mvwprintw(dbg.win_reg,3,60,"%d ",cycle_count);
|
|
|
|
wrefresh(dbg.win_reg);
|
|
|
|
};
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
static void DrawCode(void)
|
|
|
|
{
|
|
|
|
Bit32u disEIP = codeViewData.useEIP;
|
|
|
|
PhysPt start = codeViewData.useCS*16 + codeViewData.useEIP;
|
2009-05-02 23:03:37 +02:00
|
|
|
char dline[200];Bitu size;Bitu c;
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
for (Bit32u i=0;i<10;i++) {
|
2009-05-02 23:12:18 +02:00
|
|
|
if (has_colors()) {
|
|
|
|
if ((codeViewData.useCS==SegValue(cs)) && (disEIP == reg_eip)) {
|
|
|
|
wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREEN_BLACK));
|
|
|
|
if (codeViewData.cursorPos==-1) {
|
|
|
|
codeViewData.cursorPos = i; // Set Cursor
|
|
|
|
codeViewData.cursorSeg = SegValue(cs);
|
|
|
|
codeViewData.cursorOfs = disEIP;
|
|
|
|
}
|
|
|
|
} else if (i == codeViewData.cursorPos) {
|
|
|
|
wattrset(dbg.win_code,COLOR_PAIR(PAIR_BLACK_GREY));
|
|
|
|
codeViewData.cursorSeg = codeViewData.useCS;
|
|
|
|
codeViewData.cursorOfs = disEIP;
|
2009-05-02 23:20:05 +02:00
|
|
|
} else if (CBreakpoint::IsBreakpointDrawn(start)) {
|
2009-05-02 23:12:18 +02:00
|
|
|
wattrset(dbg.win_code,COLOR_PAIR(PAIR_GREY_RED));
|
|
|
|
} else {
|
|
|
|
wattrset(dbg.win_code,0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size=DasmI386(dline, start, disEIP, false);
|
|
|
|
mvwprintw(dbg.win_code,i,0,"%04X:%04X ",codeViewData.useCS,disEIP);
|
2009-05-02 23:03:37 +02:00
|
|
|
for (c=0;c<size;c++) wprintw(dbg.win_code,"%02X",mem_readb(start+c));
|
|
|
|
for (c=20;c>=size*2;c--) waddch(dbg.win_code,' ');
|
|
|
|
waddstr(dbg.win_code,dline);
|
|
|
|
for (c=30-strlen(dline);c>0;c--) waddch(dbg.win_code,' ');
|
|
|
|
start+=size;
|
2009-05-02 23:12:18 +02:00
|
|
|
disEIP+=size;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
if (i==0) codeViewData.firstInstSize = size;
|
|
|
|
if (i==4) codeViewData.useEIPmid = disEIP;
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
codeViewData.useEIPlast = disEIP;
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
wattrset(dbg.win_code,0);
|
|
|
|
if (!debugging) {
|
|
|
|
mvwprintw(dbg.win_code,10,0,"(Running)",codeViewData.inputStr);
|
|
|
|
} else if (codeViewData.inputMode) {
|
|
|
|
mvwprintw(dbg.win_code,10,0,"-> %s_ ",codeViewData.inputStr);
|
|
|
|
} else {
|
|
|
|
mvwprintw(dbg.win_code,10,0," ");
|
|
|
|
for (c=0;c<50;c++) waddch(dbg.win_code,' ');
|
|
|
|
};
|
|
|
|
|
|
|
|
wrefresh(dbg.win_code);
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
static void SetCodeWinStart()
|
|
|
|
{
|
|
|
|
if ((SegValue(cs)==codeViewData.useCS) && (reg_eip>=codeViewData.useEIP) && (reg_eip<=codeViewData.useEIPlast)) {
|
|
|
|
// in valid window - scroll ?
|
|
|
|
if (reg_eip>=codeViewData.useEIPmid) codeViewData.useEIP += codeViewData.firstInstSize;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// totally out of range.
|
|
|
|
codeViewData.useCS = SegValue(cs);
|
|
|
|
codeViewData.useEIP = reg_eip;
|
|
|
|
}
|
|
|
|
codeViewData.cursorPos = -1; // Recalc Cursor position
|
|
|
|
};
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
/********************/
|
|
|
|
/* User input */
|
|
|
|
/********************/
|
|
|
|
|
|
|
|
Bit32u GetHexValue(char* str, char*& hex)
|
|
|
|
{
|
|
|
|
Bit32u value = 0;
|
|
|
|
|
|
|
|
hex = str;
|
|
|
|
while (*hex==' ') hex++;
|
|
|
|
if (strstr(hex,"AX")==hex) { hex+=2; return reg_ax; };
|
|
|
|
if (strstr(hex,"BX")==hex) { hex+=2; return reg_bx; };
|
|
|
|
if (strstr(hex,"CX")==hex) { hex+=2; return reg_cx; };
|
|
|
|
if (strstr(hex,"DX")==hex) { hex+=2; return reg_dx; };
|
|
|
|
if (strstr(hex,"SI")==hex) { hex+=2; return reg_si; };
|
|
|
|
if (strstr(hex,"DI")==hex) { hex+=2; return reg_di; };
|
|
|
|
if (strstr(hex,"BP")==hex) { hex+=2; return reg_bp; };
|
|
|
|
if (strstr(hex,"SP")==hex) { hex+=2; return reg_sp; };
|
|
|
|
if (strstr(hex,"IP")==hex) { hex+=2; return reg_ip; };
|
|
|
|
if (strstr(hex,"CS")==hex) { hex+=2; return SegValue(cs); };
|
|
|
|
if (strstr(hex,"DS")==hex) { hex+=2; return SegValue(ds); };
|
|
|
|
if (strstr(hex,"ES")==hex) { hex+=2; return SegValue(es); };
|
|
|
|
if (strstr(hex,"FS")==hex) { hex+=2; return SegValue(fs); };
|
|
|
|
if (strstr(hex,"GS")==hex) { hex+=2; return SegValue(gs); };
|
|
|
|
if (strstr(hex,"SS")==hex) { hex+=2; return SegValue(ss); };
|
|
|
|
if (strstr(hex,"EAX")==hex) { hex+=3; return reg_eax; };
|
|
|
|
if (strstr(hex,"EBX")==hex) { hex+=3; return reg_ebx; };
|
|
|
|
if (strstr(hex,"ECX")==hex) { hex+=3; return reg_ecx; };
|
|
|
|
if (strstr(hex,"EDX")==hex) { hex+=3; return reg_edx; };
|
|
|
|
if (strstr(hex,"ESI")==hex) { hex+=3; return reg_esi; };
|
|
|
|
if (strstr(hex,"EDI")==hex) { hex+=3; return reg_edi; };
|
|
|
|
if (strstr(hex,"EBP")==hex) { hex+=3; return reg_ebp; };
|
|
|
|
if (strstr(hex,"ESP")==hex) { hex+=3; return reg_esp; };
|
|
|
|
if (strstr(hex,"EIP")==hex) { hex+=3; return reg_eip; };
|
|
|
|
|
|
|
|
while (*hex) {
|
|
|
|
if ((*hex>='0') && (*hex<='9')) value = (value<<4)+*hex-'0'; else
|
|
|
|
if ((*hex>='A') && (*hex<='F')) value = (value<<4)+*hex-'A'+10;
|
|
|
|
else break; // No valid char
|
|
|
|
hex++;
|
|
|
|
};
|
|
|
|
return value;
|
|
|
|
};
|
2009-05-02 23:03:37 +02:00
|
|
|
|
2009-05-02 23:12:18 +02:00
|
|
|
bool ParseCommand(char* str)
|
|
|
|
{
|
|
|
|
char* found = str;
|
|
|
|
while (*found) *found++=toupper(*found);
|
|
|
|
found = strstr(str,"BP ");
|
|
|
|
if (found) { // Add new breakpoint
|
|
|
|
found+=3;
|
|
|
|
Bit16u seg = GetHexValue(found,found);found++; // skip ":"
|
|
|
|
Bit32u ofs = GetHexValue(found,found);
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::AddBreakpoint(seg,ofs,false);
|
2009-05-02 23:12:18 +02:00
|
|
|
LOG_DEBUG("DEBUG: Set breakpoint at %04X:%04X",seg,ofs);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
found = strstr(str,"BPINT");
|
|
|
|
if (found) { // Add Interrupt Breakpoint
|
|
|
|
found+=5;
|
|
|
|
Bit8u intNr = GetHexValue(found,found); found++;
|
|
|
|
Bit8u valAH = GetHexValue(found,found);
|
|
|
|
if ((valAH==0x00) && (*found=='*')) {
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::AddIntBreakpoint(intNr,BPINT_ALL,false);
|
2009-05-02 23:12:18 +02:00
|
|
|
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X",intNr);
|
|
|
|
} else {
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::AddIntBreakpoint(intNr,valAH,false);
|
2009-05-02 23:12:18 +02:00
|
|
|
LOG_DEBUG("DEBUG: Set interrupt breakpoint at INT %02X AH=%02X",intNr,valAH);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
found = strstr(str,"BPLIST");
|
|
|
|
if (found) {
|
|
|
|
wprintw(dbg.win_out,"Breakpoint list:\n");
|
|
|
|
wprintw(dbg.win_out,"-------------------------------------------------------------------------\n");
|
|
|
|
Bit32u nr = 0;
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::ShowList();
|
2009-05-02 23:12:18 +02:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
found = strstr(str,"BPDEL");
|
|
|
|
if (found) { // Delete Breakpoints
|
|
|
|
found+=5;
|
|
|
|
Bit8u bpNr = GetHexValue(found,found);
|
|
|
|
if ((bpNr==0x00) && (*found=='*')) { // Delete all
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::DeleteAll();
|
2009-05-02 23:12:18 +02:00
|
|
|
LOG_DEBUG("DEBUG: Breakpoints deleted.");
|
|
|
|
} else {
|
|
|
|
// delete single breakpoint
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::DeleteByIndex(bpNr);
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
found = strstr(str,"C ");
|
|
|
|
if (found) { // Set code overview
|
|
|
|
found++;
|
|
|
|
Bit16u codeSeg = GetHexValue(found,found); found++;
|
|
|
|
Bit32u codeOfs = GetHexValue(found,found);
|
|
|
|
LOG_DEBUG("DEBUG: Set code overview to %04X:%04X",codeSeg,codeOfs);
|
|
|
|
codeViewData.useCS = codeSeg;
|
|
|
|
codeViewData.useEIP = codeOfs;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
found = strstr(str,"D ");
|
|
|
|
if (found) { // Set data overview
|
|
|
|
found++;
|
|
|
|
dataSeg = GetHexValue(found,found); found++;
|
|
|
|
dataOfs = GetHexValue(found,found);
|
|
|
|
LOG_DEBUG("DEBUG: Set data overview to %04X:%04X",dataSeg,dataOfs);
|
|
|
|
return true;
|
|
|
|
}
|
2009-05-02 23:20:05 +02:00
|
|
|
found = strstr(str,"LOG ");
|
|
|
|
if (found) { // Create Cpu log file
|
|
|
|
found+=4;
|
|
|
|
LOG_DEBUG("DEBUG: Starting log");
|
|
|
|
DEBUG_Log_Loop(GetHexValue(found,found));
|
|
|
|
LOG_DEBUG("DEBUG: Logfile LOGCPU.TXT created.");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
found = strstr(str,"INTT ");
|
|
|
|
if (found) { // Create Cpu log file
|
|
|
|
found+=4;
|
|
|
|
Bit8u intNr = GetHexValue(found,found);
|
|
|
|
LOG_DEBUG("DEBUG: Tracing INT %02X",intNr);
|
|
|
|
Interrupt(intNr);
|
|
|
|
SetCodeWinStart();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
found = strstr(str,"INT ");
|
|
|
|
if (found) { // Create Cpu log file
|
|
|
|
found+=4;
|
|
|
|
Bit8u intNr = GetHexValue(found,found);
|
|
|
|
LOG_DEBUG("DEBUG: Starting INT %02X",intNr);
|
|
|
|
CBreakpoint::AddBreakpoint (SegValue(cs),reg_eip, true);
|
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip-1,true);
|
|
|
|
debugging=false;
|
|
|
|
DrawCode();
|
|
|
|
DOSBOX_SetNormalLoop();
|
|
|
|
Interrupt(intNr);
|
|
|
|
return true;
|
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
if ((*str=='H') || (*str=='?')) {
|
|
|
|
wprintw(dbg.win_out,"Debugger keys:\n");
|
|
|
|
wprintw(dbg.win_out,"--------------------------------------------------------------------------\n");
|
|
|
|
wprintw(dbg.win_out,"F5 - Run\n");
|
|
|
|
wprintw(dbg.win_out,"F9 - Set/Remove breakpoint\n");
|
|
|
|
wprintw(dbg.win_out,"F10/F11 - Step over / trace into instruction\n");
|
|
|
|
wprintw(dbg.win_out,"Up/Down - Move code view cursor\n");
|
|
|
|
wprintw(dbg.win_out,"Return - Enable command line input\n");
|
|
|
|
wprintw(dbg.win_out,"D/E/S/X/B - Set data view to DS:SI/ES:DI/SS:SP/DS:DX/ES:BX\n");
|
|
|
|
wprintw(dbg.win_out,"R/F - Scroll data view\n");
|
|
|
|
wprintw(dbg.win_out,"Debugger commands (enter all values in hex or as register):\n");
|
|
|
|
wprintw(dbg.win_out,"--------------------------------------------------------------------------\n");
|
|
|
|
wprintw(dbg.win_out,"BP [segment]:[offset] - Set breakpoint\n");
|
|
|
|
wprintw(dbg.win_out,"BPINT [intNr] * - Set interrupt breakpoint\n");
|
|
|
|
wprintw(dbg.win_out,"BPINT [intNr] [ah] - Set interrupt breakpoint with ah\n");
|
|
|
|
wprintw(dbg.win_out,"BPLIST - List breakpoints\n");
|
|
|
|
wprintw(dbg.win_out,"BPDEL [bpNr] / * - Delete breakpoint nr / all\n");
|
|
|
|
wprintw(dbg.win_out,"C / D [segment]:[offset] - Set code / data view address\n");
|
2009-05-02 23:20:05 +02:00
|
|
|
wprintw(dbg.win_out,"INT [nr] / INTT [nr] - Execute / Trace into Iinterrupt\n");
|
|
|
|
wprintw(dbg.win_out,"LOG [num] - Write cpu log file\n");
|
2009-05-02 23:12:18 +02:00
|
|
|
wprintw(dbg.win_out,"H - Help\n");
|
|
|
|
wrefresh(dbg.win_out);
|
|
|
|
return TRUE;
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
|
|
|
return false;
|
2009-05-02 23:12:18 +02:00
|
|
|
};
|
2009-05-02 23:03:37 +02:00
|
|
|
|
|
|
|
Bit32u DEBUG_CheckKeys(void) {
|
2009-05-02 23:12:18 +02:00
|
|
|
|
|
|
|
if (codeViewData.inputMode) {
|
|
|
|
int key = getch();
|
|
|
|
if (key>0) {
|
|
|
|
switch (key) {
|
|
|
|
case 0x0A: codeViewData.inputMode = FALSE;
|
|
|
|
ParseCommand(codeViewData.inputStr);
|
|
|
|
break;
|
|
|
|
case 0x08: // delete
|
|
|
|
if (strlen(codeViewData.inputStr)>0) codeViewData.inputStr[strlen(codeViewData.inputStr)-1] = 0;
|
|
|
|
break;
|
|
|
|
default : if ((key>=32) && (key<=128) && (strlen(codeViewData.inputStr)<253)) {
|
|
|
|
Bit32u len = strlen(codeViewData.inputStr);
|
|
|
|
codeViewData.inputStr[len] = char(key);
|
|
|
|
codeViewData.inputStr[len+1] = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
DEBUG_DrawScreen();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
int key=getch();
|
|
|
|
Bit32u ret=0;
|
|
|
|
if (key>0) {
|
2009-05-02 23:12:18 +02:00
|
|
|
switch (toupper(key)) {
|
2009-05-02 23:03:37 +02:00
|
|
|
case '1':
|
|
|
|
ret=(*cpudecoder)(100);
|
|
|
|
break;
|
|
|
|
case '2':
|
|
|
|
ret=(*cpudecoder)(500);
|
|
|
|
break;
|
|
|
|
case '3':
|
|
|
|
ret=(*cpudecoder)(1000);
|
|
|
|
break;
|
|
|
|
case '4':
|
|
|
|
ret=(*cpudecoder)(5000);
|
|
|
|
break;
|
|
|
|
case '5':
|
|
|
|
ret=(*cpudecoder)(10000);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
ret=(*cpudecoder)(5);
|
|
|
|
break;
|
2009-05-02 23:12:18 +02:00
|
|
|
case 'D': dataSeg = SegValue(ds);
|
|
|
|
dataOfs = reg_si;
|
|
|
|
break;
|
|
|
|
case 'E': dataSeg = SegValue(es);
|
|
|
|
dataOfs = reg_di;
|
|
|
|
break;
|
|
|
|
case 'X': dataSeg = SegValue(ds);
|
|
|
|
dataOfs = reg_dx;
|
|
|
|
break;
|
|
|
|
case 'B': dataSeg = SegValue(es);
|
|
|
|
dataOfs = reg_bx;
|
|
|
|
break;
|
|
|
|
case 'S': dataSeg = SegValue(ss);
|
|
|
|
dataOfs = reg_sp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'R' : dataOfs -= 16; break;
|
|
|
|
case 'F' : dataOfs += 16; break;
|
|
|
|
case 'H' : strcpy(codeViewData.inputStr,"H ");
|
|
|
|
ParseCommand(codeViewData.inputStr);
|
|
|
|
break;
|
2009-05-02 23:20:05 +02:00
|
|
|
case 'T' : DEBUG_RaiseTimerIrq();
|
|
|
|
LOG_DEBUG("Debug: Timer Int started.");
|
|
|
|
break;
|
2009-05-02 23:12:18 +02:00
|
|
|
|
|
|
|
case 0x0A : // Return : input
|
|
|
|
codeViewData.inputMode = true;
|
|
|
|
codeViewData.inputStr[0] = 0;
|
|
|
|
break;
|
|
|
|
case KEY_DOWN: // down
|
|
|
|
if (codeViewData.cursorPos<9) codeViewData.cursorPos++;
|
|
|
|
else codeViewData.useEIP += codeViewData.firstInstSize;
|
|
|
|
break;
|
|
|
|
case KEY_UP: // up
|
|
|
|
if (codeViewData.cursorPos>0) codeViewData.cursorPos--;
|
|
|
|
else codeViewData.useEIP -= 1;
|
|
|
|
break;
|
|
|
|
case KEY_F(5): // Run Programm
|
|
|
|
debugging=false;
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
|
2009-05-02 23:12:18 +02:00
|
|
|
DOSBOX_SetNormalLoop();
|
|
|
|
break;
|
|
|
|
case KEY_F(9): // Set/Remove TBreakpoint
|
|
|
|
{ PhysPt ptr = PhysMake(codeViewData.cursorSeg,codeViewData.cursorOfs);
|
2009-05-02 23:20:05 +02:00
|
|
|
if (CBreakpoint::IsBreakpoint(ptr)) CBreakpoint::DeleteBreakpoint(ptr);
|
|
|
|
else CBreakpoint::AddBreakpoint(codeViewData.cursorSeg, codeViewData.cursorOfs, false);
|
2009-05-02 23:12:18 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_F(10): // Step over inst
|
|
|
|
if (StepOver()) return 0;
|
|
|
|
else {
|
2009-05-02 23:20:05 +02:00
|
|
|
skipFirstInstruction = true; // for heavy debugger
|
2009-05-02 23:12:18 +02:00
|
|
|
Bitu ret=(*cpudecoder)(1);
|
|
|
|
SetCodeWinStart();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case KEY_F(11): // trace into
|
2009-05-02 23:20:05 +02:00
|
|
|
skipFirstInstruction = true; // for heavy debugger
|
2009-05-02 23:12:18 +02:00
|
|
|
ret = (*cpudecoder)(1);
|
|
|
|
SetCodeWinStart();
|
|
|
|
break;
|
|
|
|
|
|
|
|
// default:
|
|
|
|
// // FIXME : Is this correct ?
|
|
|
|
// if (key<0x200) ret=(*cpudecoder)(1);
|
|
|
|
// break;
|
2009-05-02 23:03:37 +02:00
|
|
|
};
|
|
|
|
DEBUG_DrawScreen();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
|
|
|
Bitu DEBUG_Loop(void) {
|
|
|
|
//TODO Disable sound
|
|
|
|
GFX_Events();
|
2009-05-02 23:12:18 +02:00
|
|
|
// Interrupt started ? - then skip it
|
|
|
|
Bit16u oldCS = SegValue(cs);
|
|
|
|
Bit32u oldEIP = reg_eip;
|
2009-05-02 23:03:37 +02:00
|
|
|
PIC_runIRQs();
|
2009-05-02 23:12:18 +02:00
|
|
|
if ((oldCS!=SegValue(cs)) || (oldEIP!=reg_eip)) {
|
2009-05-02 23:20:05 +02:00
|
|
|
CBreakpoint::AddBreakpoint(oldCS,oldEIP,true);
|
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
|
2009-05-02 23:12:18 +02:00
|
|
|
debugging=false;
|
|
|
|
DOSBOX_SetNormalLoop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
return DEBUG_CheckKeys();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DEBUG_Enable(void) {
|
2009-05-02 23:20:05 +02:00
|
|
|
|
2009-05-02 23:03:37 +02:00
|
|
|
debugging=true;
|
2009-05-02 23:12:18 +02:00
|
|
|
SetCodeWinStart();
|
|
|
|
DEBUG_DrawScreen();
|
2009-05-02 23:03:37 +02:00
|
|
|
DOSBOX_SetLoop(&DEBUG_Loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DEBUG_DrawScreen(void) {
|
|
|
|
DrawRegisters();
|
2009-05-02 23:12:18 +02:00
|
|
|
DrawData();
|
2009-05-02 23:03:37 +02:00
|
|
|
DrawCode();
|
|
|
|
}
|
|
|
|
static void DEBUG_RaiseTimerIrq(void) {
|
|
|
|
PIC_ActivateIRQ(0);
|
|
|
|
}
|
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
static bool DEBUG_Log_Loop(int count) {
|
|
|
|
|
|
|
|
char buffer[512];
|
|
|
|
getcwd(buffer,512);
|
|
|
|
|
|
|
|
FILE* f = fopen("LOGCPU.TXT","wt");
|
|
|
|
if (!f) return false;
|
|
|
|
|
|
|
|
do {
|
|
|
|
// PIC_runIRQs();
|
|
|
|
|
|
|
|
Bitu ret;
|
|
|
|
do {
|
|
|
|
// Get disasm
|
|
|
|
Bit16u csValue = SegValue(cs);
|
|
|
|
Bit32u eipValue = reg_eip;
|
|
|
|
PhysPt start=Segs[cs].phys+reg_eip;
|
|
|
|
char dline[200];Bitu size;
|
|
|
|
size = DasmI386(dline, start, reg_eip, false);
|
|
|
|
Bitu len = strlen(dline);
|
|
|
|
if (len<30) for (Bitu i=0; i<30-len; i++) strcat(dline," ");
|
|
|
|
|
|
|
|
PIC_IRQAgain=false;
|
|
|
|
ret=(*cpudecoder)(1);
|
|
|
|
|
|
|
|
// Get register values
|
|
|
|
char buffer[512];
|
|
|
|
sprintf(buffer,"%04X:%08X %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\n",csValue,eipValue,dline,reg_eax,reg_ebx,reg_ecx,reg_edx,reg_esi,reg_edi,reg_ebp,reg_esp,SegValue(ds),SegValue(ds),SegValue(es),SegValue(fs),SegValue(gs),SegValue(ss),get_CF(),get_ZF(),get_SF(),get_OF(),get_AF(),get_PF());
|
|
|
|
fprintf(f,"%s",buffer);
|
|
|
|
count--;
|
|
|
|
if (count==0) break;
|
|
|
|
|
|
|
|
} while (!ret && PIC_IRQAgain);
|
|
|
|
if (ret) break;
|
|
|
|
} while (count>0);
|
|
|
|
|
|
|
|
fclose(f);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// DEBUG.COM stuff
|
|
|
|
|
|
|
|
class DEBUG : public Program {
|
|
|
|
public:
|
|
|
|
DEBUG() { pDebugcom = this; active = false; };
|
|
|
|
~DEBUG() { pDebugcom = 0; };
|
|
|
|
|
|
|
|
bool IsActive() { return active; };
|
|
|
|
|
|
|
|
void Run(void)
|
|
|
|
{
|
|
|
|
char filename[128];
|
|
|
|
char args[128];
|
|
|
|
cmd->FindCommand(1,temp_line);
|
|
|
|
strncpy(filename,temp_line.c_str(),128);
|
|
|
|
cmd->FindCommand(2,temp_line);
|
|
|
|
strncpy(args,temp_line.c_str(),128);
|
|
|
|
// Start new shell and execute prog
|
|
|
|
active = true;
|
|
|
|
DOS_Shell shell;
|
|
|
|
shell.Execute(filename,args);
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool active;
|
|
|
|
};
|
|
|
|
|
|
|
|
void DEBUG_CheckExecuteBreakpoint(Bit16u seg, Bit32u off)
|
|
|
|
{
|
|
|
|
if (pDebugcom && pDebugcom->IsActive()) {
|
|
|
|
CBreakpoint::AddBreakpoint(seg,off,true);
|
|
|
|
CBreakpoint::ActivateBreakpoints(SegPhys(cs)+reg_eip,true);
|
|
|
|
pDebugcom = 0;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
static void DEBUG_ProgramStart(Program * * make) {
|
|
|
|
*make=new DEBUG;
|
|
|
|
}
|
|
|
|
|
|
|
|
// INIT
|
|
|
|
|
|
|
|
void DEBUG_SetupConsole(void)
|
|
|
|
{
|
2009-05-02 23:03:37 +02:00
|
|
|
#ifdef WIN32
|
|
|
|
WIN32_Console();
|
2009-05-02 23:20:05 +02:00
|
|
|
#endif
|
2009-05-02 23:03:37 +02:00
|
|
|
memset((void *)&dbg,0,sizeof(dbg));
|
|
|
|
debugging=false;
|
|
|
|
dbg.active_win=3;
|
|
|
|
input_count=0;
|
|
|
|
/* Start the Debug Gui */
|
|
|
|
DBGUI_StartUp();
|
2009-05-02 23:20:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static void DEBUG_ShutDown(Section * sec)
|
|
|
|
{
|
|
|
|
CBreakpoint::DeleteAll();
|
|
|
|
};
|
|
|
|
|
|
|
|
void DEBUG_Init(Section* sec) {
|
|
|
|
|
|
|
|
MSG_Add("DEBUG_CONFIGFILE_HELP","Nothing to setup yet!\n");
|
2009-05-02 23:03:37 +02:00
|
|
|
DEBUG_DrawScreen();
|
|
|
|
/* Add some keyhandlers */
|
|
|
|
KEYBOARD_AddEvent(KBD_kpminus,0,DEBUG_Enable);
|
|
|
|
KEYBOARD_AddEvent(KBD_kpplus,0,DEBUG_RaiseTimerIrq);
|
2009-05-02 23:12:18 +02:00
|
|
|
/* Clear the TBreakpoint list */
|
|
|
|
memset((void*)&codeViewData,0,sizeof(codeViewData));
|
2009-05-02 23:20:05 +02:00
|
|
|
/* setup debug.com */
|
|
|
|
PROGRAMS_MakeFile("DEBUG.COM",DEBUG_ProgramStart);
|
|
|
|
/* shutdown function */
|
|
|
|
sec->AddDestroyFunction(&DEBUG_ShutDown);
|
2009-05-02 23:03:37 +02:00
|
|
|
}
|
2009-05-02 23:12:18 +02:00
|
|
|
|
2009-05-02 23:20:05 +02:00
|
|
|
// HEAVY DEBUGGING STUFF
|
|
|
|
|
|
|
|
#if C_HEAVY_DEBUG
|
|
|
|
|
|
|
|
bool DEBUG_HeavyIsBreakpoint(void)
|
|
|
|
{
|
|
|
|
if (skipFirstInstruction) {
|
|
|
|
skipFirstInstruction = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
PhysPt where = SegPhys(cs)+reg_eip;
|
|
|
|
if (CBreakpoint::CheckBreakpoint(where)) {
|
|
|
|
exitLoop = true;
|
|
|
|
DEBUG_Enable();
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // HEAVY DEBUG
|
|
|
|
|
|
|
|
#endif // DEBUG
|
2009-05-02 23:12:18 +02:00
|
|
|
|