Fixed bug(s) whereby the debugger could be entered and exited in

different ways, and hence sometimes certain things were done
and not at other times.  Now there's only one way to enter/exit
the debugger.  This fixes the problem of locking/unlocking the
data bus in debugger mode; a lock is done on entry and released
on exit.

The above change may expose other bugs.  I haven't tested
extensively, but if something has stopped working it's because
it relied on buggy code.

Cleaned up the Debugger class definition a little, adding some
documentation and making certain things private when they didn't
absolutely need to be public.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@631 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-07-10 02:16:01 +00:00
parent 6ef90324bf
commit f5321fcfa4
6 changed files with 144 additions and 93 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.cxx,v 1.58 2005-07-09 23:44:07 urchlay Exp $
// $Id: Debugger.cxx,v 1.59 2005-07-10 02:15:55 stephena Exp $
//============================================================================
#include "bspf.hxx"
@ -142,6 +142,18 @@ void Debugger::setConsole(Console* console)
saveOldState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::start()
{
return myOSystem->eventHandler().enterDebugMode();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::quit()
{
myOSystem->eventHandler().leaveDebugMode();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::autoLoadSymbols(string fileName) {
string file = fileName;
@ -216,9 +228,6 @@ const string Debugger::cpuState()
string result;
char buf[255];
// Lock the bus before every prompt, so we don't disturb anything:
mySystem->lockDataBus();
CpuState state = (CpuState&) myCpuDebug->getState();
CpuState oldstate = (CpuState&) myCpuDebug->getOldState();
@ -475,38 +484,6 @@ const string Debugger::dumpTIA()
return result;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Start the debugger if we aren't already in it.
// Returns false if we were already in the debugger.
bool Debugger::start()
{
if(myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER) {
myOSystem->eventHandler().enterDebugMode();
myPrompt->printPrompt();
return true;
} else {
return false;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::quit()
{
if(myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER) {
mySystem->unlockDataBus();
// execute one instruction on quit, IF we're
// sitting at a breakpoint. This will get us past it.
// Somehow this feels like a hack to me, but I don't know why
// FIXME: do this for traps, too
if(breakPoints->isSet(myCpuDebug->pc()))
mySystem->m6502().execute(1);
myOSystem->eventHandler().leaveDebugMode();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::saveState(int state)
{
@ -764,3 +741,28 @@ void Debugger::saveOldState()
myRamDebug->saveOldState();
myTiaDebug->saveOldState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setStartState()
{
// Lock the bus each time the debugger is entered, so we don't disturb anything
mySystem->lockDataBus();
// FIXME - do we want this to print each time?
// I think it was needed before because of some bugs I've fixed
// myPrompt->printPrompt();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setQuitState()
{
// Bus must be unlocked for normal operation when leaving debugger mode
mySystem->unlockDataBus();
// execute one instruction on quit, IF we're
// sitting at a breakpoint. This will get us past it.
// Somehow this feels like a hack to me, but I don't know why
// FIXME: do this for traps, too
if(breakPoints->isSet(myCpuDebug->pc()))
mySystem->m6502().execute(1);
}

View File

@ -13,14 +13,13 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.hxx,v 1.46 2005-07-08 17:22:40 stephena Exp $
// $Id: Debugger.hxx,v 1.47 2005-07-10 02:15:57 stephena Exp $
//============================================================================
#ifndef DEBUGGER_HXX
#define DEBUGGER_HXX
class OSystem;
class Console;
class System;
class CpuDebug;
@ -53,11 +52,12 @@ enum {
for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony
@version $Id: Debugger.hxx,v 1.46 2005-07-08 17:22:40 stephena Exp $
@version $Id: Debugger.hxx,v 1.47 2005-07-10 02:15:57 stephena Exp $
*/
class Debugger : public DialogContainer
{
friend class DebuggerParser;
friend class EventHandler;
public:
/**
@ -87,24 +87,83 @@ class Debugger : public DialogContainer
void setConsole(Console* console);
/**
Save state of each debugger subsystem
Wrapper method for EventHandler::enterDebugMode() for those classes
that don't have access to EventHandler.
*/
void saveOldState();
bool start();
/**
Wrapper method for EventHandler::leaveDebugMode() for those classes
that don't have access to EventHandler.
*/
void quit();
/**
The debugger subsystem responsible for all CPU state
*/
CpuDebug& cpuDebug() { return *myCpuDebug; }
CpuDebug& cpuDebug() const { return *myCpuDebug; }
/**
The debugger subsystem responsible for all RAM state
*/
RamDebug& ramDebug() { return *myRamDebug; }
RamDebug& ramDebug() const { return *myRamDebug; }
/**
The debugger subsystem responsible for all TIA state
*/
TIADebug& tiaDebug() { return *myTiaDebug; }
TIADebug& tiaDebug() const { return *myTiaDebug; }
/**
List of English-like aliases for 6502 opcodes and operands.
*/
EquateList *equates();
DebuggerParser *parser() { return myParser; }
PackedBitArray *breakpoints() { return breakPoints; }
PackedBitArray *readtraps() { return readTraps; }
PackedBitArray *writetraps() { return writeTraps; }
/**
Run the debugger command and return the result.
*/
const string run(const string& command);
/**
Give the contents of the CPU registers and disassembly of
next instruction.
*/
const string cpuState();
/**
Get contents of RIOT switch & timer registers
*/
const string riotState();
/**
The current cycle count of the System.
*/
int cycles();
/**
Disassemble from the starting address the specified number of lines
and place result in a string.
*/
string disassemble(int start, int lines);
int step();
int trace();
void nextFrame(int frames);
string showWatches();
/**
Convert between string->integer and integer->string, taking into
account the current base format.
*/
int stringToValue(const string& stringval)
{ return myParser->decipher_arg(stringval); }
const string valueToString(int value, BaseFormat outputBase = kBASE_DEFAULT);
/** Convenience methods to convert to hexidecimal values */
static char *to_hex_4(int i)
@ -147,9 +206,21 @@ class Debugger : public DialogContainer
return to_bin(dec, 16, buf);
}
int stringToValue(const string& stringval)
{ return myParser->decipher_arg(stringval); }
const string valueToString(int value, BaseFormat outputBase = kBASE_DEFAULT);
private:
/**
Save state of each debugger subsystem
*/
void saveOldState();
/**
Set initial state before entering the debugger.
*/
void setStartState();
/**
Set final state before leaving the debugger.
*/
void setQuitState();
void toggleBreakPoint(int bp);
@ -161,28 +232,10 @@ class Debugger : public DialogContainer
bool writeTrap(int t);
void clearAllTraps();
string disassemble(int start, int lines);
bool setHeight(int height);
void reloadROM();
public:
/**
Run the debugger command and return the result.
*/
const string run(const string& command);
/**
Give the contents of the CPU registers and disassembly of
next instruction.
*/
const string cpuState();
/**
Get contents of RIOT switch & timer registers
*/
const string riotState();
/**
Return a formatted string containing the contents of the specified
device.
@ -193,31 +246,16 @@ class Debugger : public DialogContainer
// set a bunch of RAM locations at once
const string setRAM(IntArray& args);
bool start();
void quit();
int trace();
int step();
int cycles();
int peek(int addr);
int dpeek(int addr);
void reset();
void autoLoadSymbols(string file);
void nextFrame(int frames);
void clearAllBreakPoints();
void formatFlags(BoolArray& b, char *out);
EquateList *equates();
PromptWidget *prompt() { return myPrompt; }
string showWatches();
void addLabel(string label, int address);
PackedBitArray *breakpoints() { return breakPoints; }
PackedBitArray *readtraps() { return readTraps; }
PackedBitArray *writetraps() { return writeTraps; }
DebuggerParser *parser() { return myParser; }
void addLabel(string label, int address);
bool setBank(int bank);
int bankCount();
@ -227,9 +265,9 @@ class Debugger : public DialogContainer
void saveState(int state);
void loadState(int state);
protected:
const string invIfChanged(int reg, int oldReg);
protected:
Console* myConsole;
System* mySystem;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.cxx,v 1.79 2005-06-30 00:07:59 stephena Exp $
// $Id: EventHandler.cxx,v 1.80 2005-07-10 02:15:58 stephena Exp $
//============================================================================
#include <algorithm>
@ -1333,11 +1333,10 @@ void EventHandler::leaveMenuMode()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::enterDebugMode()
bool EventHandler::enterDebugMode()
{
// paranoia: this should never happen:
if(myState == S_DEBUGGER)
return;
return false;
myState = S_DEBUGGER;
myOSystem->createFrameBuffer();
@ -1348,11 +1347,23 @@ void EventHandler::enterDebugMode()
if(!myPauseFlag) // Pause when entering debugger mode
handleEvent(Event::Pause, 1);
// Make sure debugger starts in a consistent state
myOSystem->debugger().setStartState();
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::leaveDebugMode()
{
// paranoia: this should never happen:
if(myState != S_DEBUGGER)
return;
// Make sure debugger quits in a consistent state
myOSystem->debugger().setQuitState();
myState = S_EMULATE;
myOSystem->createFrameBuffer();
myOSystem->frameBuffer().refreshTIA();

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EventHandler.hxx,v 1.43 2005-06-29 00:31:49 urchlay Exp $
// $Id: EventHandler.hxx,v 1.44 2005-07-10 02:16:00 stephena Exp $
//============================================================================
#ifndef EVENTHANDLER_HXX
@ -74,7 +74,7 @@ struct Stella_Joystick {
mapping can take place.
@author Stephen Anthony
@version $Id: EventHandler.hxx,v 1.43 2005-06-29 00:31:49 urchlay Exp $
@version $Id: EventHandler.hxx,v 1.44 2005-07-10 02:16:00 stephena Exp $
*/
class EventHandler
{
@ -215,7 +215,7 @@ class EventHandler
void enterMenuMode();
void leaveMenuMode();
void enterDebugMode();
bool enterDebugMode();
void leaveDebugMode();
// Holds static strings for the remap menu

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: M6502Hi.cxx,v 1.9 2005-07-01 04:22:37 urchlay Exp $
// $Id: M6502Hi.cxx,v 1.10 2005-07-10 02:16:01 stephena Exp $
//============================================================================
#include "M6502Hi.hxx"
@ -99,7 +99,7 @@ bool M6502High::execute(uInt32 number)
{
if(breakPoints->isSet(PC)) {
if(myDebugger->start()) {
return true;
return true;
}
}
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: TiaWidget.cxx,v 1.7 2005-07-08 21:25:33 stephena Exp $
// $Id: TiaWidget.cxx,v 1.8 2005-07-10 02:16:01 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -281,7 +281,7 @@ void TiaWidget::changeRam()
ram.push_back(addr);
ram.push_back(value);
instance()->debugger().setRAM(ram);
// instance()->debugger().setRAM(ram);
myDecValue->setEditString(instance()->debugger().valueToString(value, kBASE_10));
myBinValue->setEditString(instance()->debugger().valueToString(value, kBASE_2));
}