First pass at making the debugger be asynchronous from the debugger parser,

meaning that if a command is running, it can be interrupted, and Stella
doesn't lock up in the process.  It all feels like sort of a hack, but
for now it's the best we can do.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1183 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-12-05 22:05:35 +00:00
parent dcb74722ad
commit 3c93be914a
10 changed files with 161 additions and 154 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.cxx,v 1.105 2006-12-02 23:25:53 stephena Exp $ // $Id: Debugger.cxx,v 1.106 2006-12-05 22:05:33 stephena Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -334,12 +334,6 @@ const string Debugger::run(const string& command)
return myParser->run(command); return myParser->run(command);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::cancel()
{
myParser->cancel();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string Debugger::valueToString(int value, BaseFormat outputBase) const string Debugger::valueToString(int value, BaseFormat outputBase)
{ {
@ -841,10 +835,10 @@ void Debugger::disassemble(IntArray& addr, StringList& addrLabel,
void Debugger::nextScanline(int lines) void Debugger::nextScanline(int lines)
{ {
saveOldState(); saveOldState();
// mySystem->unlockDataBus(); // mySystem->unlockDataBus();
unlockState(); unlockState();
myTiaOutput->advanceScanline(lines); myTiaOutput->advanceScanline(lines);
// mySystem->lockDataBus(); // mySystem->lockDataBus();
lockState(); lockState();
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.hxx,v 1.83 2006-12-02 23:25:53 stephena Exp $ // $Id: Debugger.hxx,v 1.84 2006-12-05 22:05:33 stephena Exp $
//============================================================================ //============================================================================
#ifndef DEBUGGER_HXX #ifndef DEBUGGER_HXX
@ -44,19 +44,9 @@ class Expression;
#include "Rect.hxx" #include "Rect.hxx"
#include "bspf.hxx" #include "bspf.hxx"
typedef multimap<string,string> ListFile;
typedef ListFile::const_iterator ListIter;
typedef map<string,Expression*> FunctionMap; typedef map<string,Expression*> FunctionMap;
typedef map<string,string> FunctionDefMap; typedef map<string,string> FunctionDefMap;
enum {
kDebuggerWidth = 1023,
kDebuggerHeight = 700,
kDebuggerLineHeight = 15, // based on the height of the console font
kDebuggerLines = 27,
};
// Constants for RAM area // Constants for RAM area
enum { enum {
kRamStart = 0x80, kRamStart = 0x80,
@ -79,7 +69,7 @@ typedef uInt16 (Debugger::*DEBUGGER_WORD_METHOD)();
for all debugging operations in Stella (parser, 6502 debugger, etc). for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony @author Stephen Anthony
@version $Id: Debugger.hxx,v 1.83 2006-12-02 23:25:53 stephena Exp $ @version $Id: Debugger.hxx,v 1.84 2006-12-05 22:05:33 stephena Exp $
*/ */
class Debugger : public DialogContainer class Debugger : public DialogContainer
{ {
@ -170,9 +160,10 @@ class Debugger : public DialogContainer
const string run(const string& command); const string run(const string& command);
/** /**
Cancel the currently running debugger command. Indicate if the debugger is currently running a command
(it shouldn't be exited in this case)
*/ */
void cancel(); bool isBlocked() { return myParser->commandRunning(); }
/** /**
Give the contents of the CPU registers and disassembly of Give the contents of the CPU registers and disassembly of
@ -364,7 +355,17 @@ class Debugger : public DialogContainer
const string invIfChanged(int reg, int oldReg); const string invIfChanged(int reg, int oldReg);
protected: private:
enum {
kDebuggerWidth = 1023,
kDebuggerHeight = 700,
kDebuggerLineHeight = 15, // based on the height of the console font
kDebuggerLines = 27,
};
typedef multimap<string,string> ListFile;
typedef ListFile::const_iterator ListIter;
Console* myConsole; Console* myConsole;
System* mySystem; System* mySystem;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: DebuggerParser.cxx,v 1.90 2006-12-02 23:25:53 stephena Exp $ // $Id: DebuggerParser.cxx,v 1.91 2006-12-05 22:05:33 stephena Exp $
//============================================================================ //============================================================================
#include <fstream> #include <fstream>
@ -40,9 +40,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DebuggerParser::DebuggerParser(Debugger* d) DebuggerParser::DebuggerParser(Debugger* d)
: debugger(d) : debugger(d),
myRunningFlag(false),
myCancelFlag(false)
{ {
cancelCommand = false;
defaultBase = kBASE_16; defaultBase = kBASE_16;
} }
@ -100,14 +101,16 @@ string DebuggerParser::run(const string& command)
cerr << "Expression count: " << refCount << endl; cerr << "Expression count: " << refCount << endl;
#endif #endif
commandResult = ""; commandResult = "";
cancelCommand = false; myCancelFlag = false;
for(int i = 0; i < kNumCommands; ++i) for(int i = 0; i < kNumCommands; ++i)
{ {
if(verb == commands[i].cmdString) if(verb == commands[i].cmdString)
{ {
myRunningFlag = true;
if(validateArgs(i)) if(validateArgs(i))
CALL_METHOD(commands[i].executor); CALL_METHOD(commands[i].executor);
myRunningFlag = false;
if(commands[i].refreshRequired) if(commands[i].refreshRequired)
debugger->myBaseDialog->loadConfig(); debugger->myBaseDialog->loadConfig();
@ -123,10 +126,8 @@ string DebuggerParser::run(const string& command)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerParser::cancel() void DebuggerParser::cancel()
{ {
cerr << "DebuggerParser::cancel()\n"; // Indicate to any blocking commands that it's time to quit
// Let the running command know it should stop myCancelFlag = true;
// Hopefully, it's actually checking this variable!
cancelCommand = true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -364,62 +365,72 @@ string DebuggerParser::showWatches()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool DebuggerParser::getArgs(const string& command, string& verb) bool DebuggerParser::getArgs(const string& command, string& verb)
{ {
int state = kIN_COMMAND; int state = kIN_COMMAND, i = 0, length = command.length();
string curArg = ""; string curArg = "";
verb = ""; verb = "";
const char *c = command.c_str();
argStrings.clear(); argStrings.clear();
args.clear(); args.clear();
// cerr << "Parsing \"" << command << "\"" << endl; // cerr << "Parsing \"" << command << "\"" << ", length = " << command.length() << endl;
// First, pick apart string into space-separated tokens. // First, pick apart string into space-separated tokens.
// The first token is the command verb, the rest go in an array // The first token is the command verb, the rest go in an array
do { do
// cerr << "State " << state << ", *c '" << *c << "'" << endl; {
switch(state) { char c = command[i++];
switch(state)
{
case kIN_COMMAND: case kIN_COMMAND:
if(*c == ' ') if(c == ' ')
state = kIN_SPACE; state = kIN_SPACE;
else else
verb += *c; verb += c;
break; break;
case kIN_SPACE: case kIN_SPACE:
if(*c == '{') if(c == '{')
state = kIN_BRACE; state = kIN_BRACE;
else if(*c != ' ') { else if(c != ' ') {
state = kIN_ARG; state = kIN_ARG;
curArg += *c; curArg += c;
} }
break; break;
case kIN_BRACE: case kIN_BRACE:
if(*c == '}' || *c == '\0') { if(c == '}') {
state = kIN_SPACE; state = kIN_SPACE;
argStrings.push_back(curArg); argStrings.push_back(curArg);
// cerr << "{" << curArg << "}" << endl; // cerr << "{" << curArg << "}" << endl;
curArg = ""; curArg = "";
} else { } else {
curArg += *c; curArg += c;
} }
break; break;
case kIN_ARG: case kIN_ARG:
if(*c == ' ' || *c == '\0') { if(c == ' ') {
state = kIN_SPACE; state = kIN_SPACE;
argStrings.push_back(curArg); argStrings.push_back(curArg);
curArg = ""; curArg = "";
} else { } else {
curArg += *c; curArg += c;
} }
break; break;
} // switch(state) } // switch(state)
} while(*c++ != '\0'); }
while(i < length);
// Take care of the last argument, if there is one
if(curArg != "")
argStrings.push_back(curArg);
argCount = argStrings.size(); argCount = argStrings.size();
/*
cerr << "verb = " << verb << endl;
cerr << "arguments (" << argCount << "):\n";
for(int x = 0; x < argCount; x++)
cerr << "command " << x << ": " << argStrings[x] << endl;
*/
/* /*
// Now decipher each argument, in turn. // Now decipher each argument, in turn.
for(int i=0; i<argCount; i++) { for(int i=0; i<argCount; i++) {
@ -429,12 +440,12 @@ bool DebuggerParser::getArgs(const string& command, string& verb)
} }
*/ */
for(int i=0; i<argCount; i++) { for(int i = 0; i < argCount; i++) {
int err = YaccParser::parse(argStrings[i].c_str()); int err = YaccParser::parse(argStrings[i].c_str());
if(err) { if(err) {
args.push_back(-1); args.push_back(-1);
} else { } else {
Expression *e = YaccParser::getResult(); Expression* e = YaccParser::getResult();
args.push_back( e->evaluate() ); args.push_back( e->evaluate() );
delete e; delete e;
} }
@ -1167,19 +1178,20 @@ void DebuggerParser::executeRunTo()
int cycles = 0, count = 0; int cycles = 0, count = 0;
do { do {
if(myCancelFlag) break;
cycles += debugger->step(); cycles += debugger->step();
if(++count % 100 == 0)
// This command can potentially block forever
// We should yield to the system, and check for cancellation
if(++count % 10000 == 0)
{ {
debugger->prompt()->putchar('.'); debugger->prompt()->putchar('.');
// This command can potentially block forever debugger->getOSystem()->run();
// We should check if the user cancelled it
cerr << "checking for break command ...\n";
if(cancelCommand) break;
} }
string next = debugger->disassemble(debugger->cpuDebug().pc(), 1); string next = debugger->disassemble(debugger->cpuDebug().pc(), 1);
done = (next.find(argStrings[0]) != string::npos); done = (next.find(argStrings[0]) != string::npos);
} while(!done); } while(!done);
commandResult = "executed "; commandResult = "executed ";

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: DebuggerParser.hxx,v 1.44 2006-12-02 23:25:53 stephena Exp $ // $Id: DebuggerParser.hxx,v 1.45 2006-12-05 22:05:34 stephena Exp $
//============================================================================ //============================================================================
#ifndef DEBUGGER_PARSER_HXX #ifndef DEBUGGER_PARSER_HXX
@ -42,6 +42,9 @@ class DebuggerParser
/** Run the given command, and return the result */ /** Run the given command, and return the result */
string run(const string& command); string run(const string& command);
/** Indicate if a command is currently running */
bool commandRunning() { return myRunningFlag; }
/** Cancel the currently running command, if any */ /** Cancel the currently running command, if any */
void cancel(); void cancel();
@ -84,7 +87,7 @@ class DebuggerParser
private: private:
enum { enum {
kNumCommands = 59, kNumCommands = 59,
kMAX_ARG_TYPES = 10 // TODO: put in separate header file Command.hxx kMAX_ARG_TYPES = 10 // TODO: put in separate header file Command.hxx
}; };
@ -123,12 +126,15 @@ class DebuggerParser
// Pointer to our debugger object // Pointer to our debugger object
Debugger* debugger; Debugger* debugger;
// Flag indicating whether a currently running command should be cancelled
bool cancelCommand;
// The results of the currently running command // The results of the currently running command
string commandResult; string commandResult;
// Indicates whether a command is currently running, or a cancel
// event has been received
// Commands which expect to block for long periods of time should
// occasionally check the myCancelFlag
bool myRunningFlag, myCancelFlag;
// Arguments in 'int' and 'string' format for the currently running command // Arguments in 'int' and 'string' format for the currently running command
IntArray args; IntArray args;
StringList argStrings; StringList argStrings;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: PromptWidget.cxx,v 1.10 2006-12-02 23:25:53 stephena Exp $ // $Id: PromptWidget.cxx,v 1.11 2006-12-05 22:05:34 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -179,23 +179,16 @@ bool PromptWidget::handleKeyDown(int ascii, int keycode, int modifiers)
if (len > 0) if (len > 0)
{ {
// We have to allocate the string buffer with new, since VC++ sadly does not // Copy the user input to command
// comply to the C++ standard, so we can't use a dynamic sized stack array. string command;
char *str = new char[len + 1];
// Copy the user input to str
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
str[i] = buffer(_promptStartPos + i) & 0x7f; command += buffer(_promptStartPos + i) & 0x7f;
str[len] = '\0';
// Add the input to the history // Add the input to the history
addToHistory(str); addToHistory(command.c_str());
// Pass the command to the debugger, and print the result // Pass the command to the debugger, and print the result
print( instance()->debugger().run(str) + "\n"); print( instance()->debugger().run(command) + "\n");
// Get rid of the string buffer
delete [] str;
} }
printPrompt(); printPrompt();
@ -528,32 +521,26 @@ void PromptWidget::specialKeys(int keycode)
_currentPos = _promptStartPos; _currentPos = _promptStartPos;
handled = true; handled = true;
break; break;
case 'c': case 'c':
cancelLastCommand(); instance()->debugger().parser()->cancel();
handled = true; handled = true;
break; break;
case 'd': case 'd':
killChar(+1); killChar(+1);
handled = true; handled = true;
break; break;
case 'e': case 'e':
_currentPos = _promptEndPos; _currentPos = _promptEndPos;
handled = true; handled = true;
break; break;
case 'k': case 'k':
killLine(+1); killLine(+1);
handled = true; handled = true;
break; break;
case 'u': case 'u':
killLine(-1); killLine(-1);
handled = true; handled = true;
break; break;
case 'w': case 'w':
killLastWord(); killLastWord();
handled = true; handled = true;
@ -643,12 +630,6 @@ void PromptWidget::killLastWord()
_promptEndPos -= cnt; _promptEndPos -= cnt;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::cancelLastCommand()
{
instance()->debugger().cancel();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::addToHistory(const char *str) void PromptWidget::addToHistory(const char *str)
{ {

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: PromptWidget.hxx,v 1.6 2006-12-02 23:25:53 stephena Exp $ // $Id: PromptWidget.hxx,v 1.7 2006-12-05 22:05:34 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -70,7 +70,6 @@ class PromptWidget : public Widget, public CommandSender
void killChar(int direction); void killChar(int direction);
void killLine(int direction); void killLine(int direction);
void killLastWord(); void killLastWord();
void cancelLastCommand();
// History // History
void addToHistory(const char *str); void addToHistory(const char *str);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EventHandler.cxx,v 1.178 2006-12-02 23:25:53 stephena Exp $ // $Id: EventHandler.cxx,v 1.179 2006-12-05 22:05:34 stephena Exp $
//============================================================================ //============================================================================
#include <sstream> #include <sstream>
@ -2272,6 +2272,10 @@ void EventHandler::leaveDebugMode()
if(myState != S_DEBUGGER) if(myState != S_DEBUGGER)
return; return;
// If for any reason a command is currently running, we can't exit the debugger
if(myOSystem->debugger().isBlocked())
return;
// Make sure debugger quits in a consistent state // Make sure debugger quits in a consistent state
myOSystem->debugger().setQuitState(); myOSystem->debugger().setQuitState();
@ -2564,7 +2568,7 @@ void EventHandler::setSDLMappings()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ActionList EventHandler::ourEmulActionList[kEmulActionListSize] = { EventHandler::ActionList EventHandler::ourEmulActionList[kEmulActionListSize] = {
{ Event::ConsoleSelect, "Select", 0 }, { Event::ConsoleSelect, "Select", 0 },
{ Event::ConsoleReset, "Reset", 0 }, { Event::ConsoleReset, "Reset", 0 },
{ Event::ConsoleColor, "Color TV", 0 }, { Event::ConsoleColor, "Color TV", 0 },
@ -2661,7 +2665,7 @@ ActionList EventHandler::ourEmulActionList[kEmulActionListSize] = {
}; };
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ActionList EventHandler::ourMenuActionList[kMenuActionListSize] = { EventHandler::ActionList EventHandler::ourMenuActionList[kMenuActionListSize] = {
{ Event::UIUp, "Move Up", 0 }, { Event::UIUp, "Move Up", 0 },
{ Event::UIDown, "Move Down", 0 }, { Event::UIDown, "Move Down", 0 },
{ Event::UILeft, "Move Left", 0 }, { Event::UILeft, "Move Left", 0 },

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: EventHandler.hxx,v 1.92 2006-12-01 18:30:18 stephena Exp $ // $Id: EventHandler.hxx,v 1.93 2006-12-05 22:05:35 stephena Exp $
//============================================================================ //============================================================================
#ifndef EVENTHANDLER_HXX #ifndef EVENTHANDLER_HXX
@ -34,16 +34,6 @@ class DialogContainer;
class EventMappingWidget; class EventMappingWidget;
class EventStreamer; class EventStreamer;
// A wrapper around SDL hat events, so we don't drag SDL
// through all the child classes
enum JoyHat {
kJHatUp,
kJHatDown,
kJHatLeft,
kJHatRight,
kJHatCentered
};
enum MouseButton { enum MouseButton {
EVENT_LBUTTONDOWN, EVENT_LBUTTONDOWN,
EVENT_LBUTTONUP, EVENT_LBUTTONUP,
@ -53,54 +43,12 @@ enum MouseButton {
EVENT_WHEELUP EVENT_WHEELUP
}; };
// Structure used for action menu items
struct ActionList {
Event::Type event;
const char* action;
char* key;
};
enum {
kEmulActionListSize = 81,
kMenuActionListSize = 15
};
enum EventMode { enum EventMode {
kEmulationMode = 0, // make sure these are set correctly, kEmulationMode = 0, // make sure these are set correctly,
kMenuMode = 1, // since they'll be used as array indices kMenuMode = 1, // since they'll be used as array indices
kNumModes = 2 kNumModes = 2
}; };
// Joystick related items
enum {
kNumJoysticks = 8,
kNumJoyButtons = 24,
kNumJoyAxis = 16,
kNumJoyHats = 16
};
enum JoyType {
JT_NONE,
JT_REGULAR,
JT_STELLADAPTOR_LEFT,
JT_STELLADAPTOR_RIGHT
};
struct Stella_Joystick {
SDL_Joystick* stick;
JoyType type;
string name;
};
// Used for joystick to mouse emulation
struct JoyMouse {
bool active;
int x, y, x_vel, y_vel, x_max, y_max, x_amt, y_amt, amt,
x_down_count, y_down_count;
unsigned int last_time, delay_time, x_down_time, y_down_time;
int joy_val, old_joy_val;
};
/** /**
This class takes care of event remapping and dispatching for the This class takes care of event remapping and dispatching for the
Stella core, as well as keeping track of the current 'mode'. Stella core, as well as keeping track of the current 'mode'.
@ -114,7 +62,7 @@ struct JoyMouse {
mapping can take place. mapping can take place.
@author Stephen Anthony @author Stephen Anthony
@version $Id: EventHandler.hxx,v 1.92 2006-12-01 18:30:18 stephena Exp $ @version $Id: EventHandler.hxx,v 1.93 2006-12-05 22:05:35 stephena Exp $
*/ */
class EventHandler class EventHandler
{ {
@ -460,7 +408,7 @@ class EventHandler
@param value The value on the given hat @param value The value on the given hat
*/ */
void handleJoyHatEvent(int stick, int hat, int value); void handleJoyHatEvent(int stick, int hat, int value);
/** /**
Detects and changes the eventhandler state Detects and changes the eventhandler state
@ -523,6 +471,51 @@ class EventHandler
void setEventState(State state); void setEventState(State state);
private: private:
enum {
kEmulActionListSize = 81,
kMenuActionListSize = 15
};
// Structure used for action menu items
struct ActionList {
Event::Type event;
const char* action;
char* key;
};
// Joystick related items
enum {
kNumJoysticks = 8,
kNumJoyButtons = 24,
kNumJoyAxis = 16,
kNumJoyHats = 16
};
enum JoyType {
JT_NONE,
JT_REGULAR,
JT_STELLADAPTOR_LEFT,
JT_STELLADAPTOR_RIGHT
};
struct Stella_Joystick {
SDL_Joystick* stick;
JoyType type;
string name;
};
enum JoyHat {
kJHatUp,
kJHatDown,
kJHatLeft,
kJHatRight,
kJHatCentered
};
struct JoyMouse { // Used for joystick to mouse emulation
bool active;
int x, y, x_vel, y_vel, x_max, y_max, x_amt, y_amt, amt,
x_down_count, y_down_count;
unsigned int last_time, delay_time, x_down_time, y_down_time;
int joy_val, old_joy_val;
};
// Global OSystem object // Global OSystem object
OSystem* myOSystem; OSystem* myOSystem;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: OSystem.cxx,v 1.76 2006-12-02 00:43:50 stephena Exp $ // $Id: OSystem.cxx,v 1.77 2006-12-05 22:05:35 stephena Exp $
//============================================================================ //============================================================================
#include <cassert> #include <cassert>
@ -524,6 +524,13 @@ bool OSystem::openROM(const string& rom, string& md5, uInt8** image, int* size)
return true; return true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::run() const
{
myEventHandler->poll(0);
myFrameBuffer->update();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setDefaultJoymap() void OSystem::setDefaultJoymap()
{ {

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: OSystem.hxx,v 1.43 2006-10-22 18:58:46 stephena Exp $ // $Id: OSystem.hxx,v 1.44 2006-12-05 22:05:35 stephena Exp $
//============================================================================ //============================================================================
#ifndef OSYSTEM_HXX #ifndef OSYSTEM_HXX
@ -45,7 +45,7 @@ class VideoDialog;
other objects belong. other objects belong.
@author Stephen Anthony @author Stephen Anthony
@version $Id: OSystem.hxx,v 1.43 2006-10-22 18:58:46 stephena Exp $ @version $Id: OSystem.hxx,v 1.44 2006-12-05 22:05:35 stephena Exp $
*/ */
class OSystem class OSystem
{ {
@ -271,6 +271,16 @@ class OSystem
*/ */
bool openROM(const string& rom, string& md5, uInt8** image, int* size); bool openROM(const string& rom, string& md5, uInt8** image, int* size);
/**
Runs through one iteration of the OSystem loop, which consists of
checking for events, rendering the framebuffer, etc.
This method isn't meant to be used from mainLoop(), but instead is
used as a sort of 'yield' function, whereby other parts of the code
may block for a time, and we need to check for cancellation (used
to emulate a poor man's threading system).
*/
void run() const;
public: public:
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// The following methods are system-specific and must be implemented // The following methods are system-specific and must be implemented