mirror of https://github.com/stella-emu/stella.git
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:
parent
6ef90324bf
commit
f5321fcfa4
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue