X11 and SDL versions now fully compile and fully support the new

EventHandler class.  All thats left to do there is integrate the
Snapshot code into the core, but that will have to wait until I
rewrite the PNG handler to not need the PNG library ...

Changed the Settings class to a virtual abstract class, and created
a SettingsUNIX class to derive from it and work with the X11 and SDL
versions.

Some notes on updating the DOS and Windows ports (which I will probably
do eventually), and on porting to other toolkits:

A port needs the following:

 - a main function which takes native events and converts to the core
   format, and generally acts as the dispatcher (mainXXX.cxx)

 - a specific frontend, derived from Frontend.hxx, which sets up port
   specific filename and locations (FrontendXXX.hxx)

 - a specific settings class, derived from Settings.hxx, which deals
   with settings/commandline arguments specific to that port (SettingsXXX.hxx)

 - probably some other stuff that I've forgotten


The next step is get the DOS port working with the new EventHandler (easy)
and attempt to bring the Windows port into the year 2003 (it hasn't been
touched for almost a year, quite hard).

I also have to write a GUI class that will draw menus, etc. and actually let
you remap keys from the emulator itself.  And that may have to wait until
the fabled graphics rewrite that Brad and I will be working on.  It never ends ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@181 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2003-09-11 20:53:51 +00:00
parent 68e30ca3f2
commit b1c31fdd1a
8 changed files with 976 additions and 1115 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: makefile,v 1.36 2003-09-11 00:13:39 stephena Exp $ ## $Id: makefile,v 1.37 2003-09-11 20:53:51 stephena Exp $
##============================================================================ ##============================================================================
##============================================================================ ##============================================================================
@ -31,8 +31,8 @@ OPTIMIZATIONS = $(CXXFLAGS) -Wall -Wno-unused
### comment out all lines to completely disable sound ### comment out all lines to completely disable sound
### ###
SOUND_ALSA = 1 SOUND_ALSA = 1
#SOUND_OSS = 1 SOUND_OSS = 1
#SOUND_SDL = 1 SOUND_SDL = 1
### if your C++ compiler doesn't support the bool type ### if your C++ compiler doesn't support the bool type
# BSPF_BOOL = 1 # BSPF_BOOL = 1
@ -49,7 +49,7 @@ SOUND_ALSA = 1
### to include support for saving snapshots in png format ### to include support for saving snapshots in png format
### (requires PNG library) ### (requires PNG library)
### Only X11 and SDL ports supported for now ### Only X11 and SDL ports supported for now
# SNAPSHOT_SUPPORT = 1 SNAPSHOT_SUPPORT = 1
### comment this out if your system doesn't ### comment this out if your system doesn't
### have the gettimeofday function ### have the gettimeofday function
@ -73,7 +73,7 @@ LD = g++
LDFLAGS = LDFLAGS =
LDLIBS = LDLIBS =
OBJS.X11 = OBJS.X11 =
OPTS.X11 = OPTS.X11 =
LIBS.X11 = LIBS.X11 =
CFLAGS.X11 = CFLAGS.X11 =
@ -83,7 +83,7 @@ OPTS.SDL =
LIBS.SDL = `sdl-config --libs` LIBS.SDL = `sdl-config --libs`
CFLAGS.SDL = `sdl-config --cflags` CFLAGS.SDL = `sdl-config --cflags`
OPTS.DOS = OPTS.DOS = -DDOS=1
SRC = .. SRC = ..
CORE = $(SRC)/emucore CORE = $(SRC)/emucore
@ -193,65 +193,65 @@ unix-x:
make stella.x11 \ make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \ INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="" \ SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \ OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \ OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/X11R6/lib" \ LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.X11)" \ LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \ LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \ LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o" OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o"
OBJS+="$(OBJS.X11)" OBJS+="$(OBJS.X11)"
linux-x: linux-x:
make stella.x11 \ make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \ INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="" \ SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \ OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \ OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/X11R6/lib" \ LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.X11)" \ LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \ LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \ LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o" \ OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o" \
OBJS+="$(OBJS.X11)" OBJS+="$(OBJS.X11)"
linux-sdl: linux-sdl:
make stella.sdl \ make stella.sdl \
INCLUDES="$(INCLUDES) -I$(UI)/sdl -I$(UI)/sound" \ INCLUDES="$(INCLUDES) -I$(UI)/sdl -I$(UI)/sound" \
SYS_INCLUDES="" \ SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \ OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.SDL)" \ OPTIONS+="$(OPTS.SDL)" \
LDFLAGS="-L/usr/X11R6/lib" \ LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.SDL)" \ LDFLAGS+="$(CFLAGS.SDL)" \
LDLIBS="-lX11 -lXext" \ LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.SDL)" \ LDLIBS+="$(LIBS.SDL)" \
OBJS="mainSDL.o RectList.o FrontendUNIX.o" \ OBJS="mainSDL.o RectList.o FrontendUNIX.o SettingsUNIX.o" \
OBJS+="$(OBJS.SDL)" OBJS+="$(OBJS.SDL)"
bsdi-x: bsdi-x:
make stella.x11 \ make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \ INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="-I/usr/X11R6/include" \ SYS_INCLUDES="-I/usr/X11R6/include" \
OPTIONS="-DBSPF_UNIX=1" \ OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \ OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/X11R6/lib" \ LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.X11)" \ LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \ LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \ LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o" OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o"
OBJS+="$(OBJS.X11)" OBJS+="$(OBJS.X11)"
solaris-x: solaris-x:
make stella.x11 \ make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \ INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="-I/usr/openwin/include" \ SYS_INCLUDES="-I/usr/openwin/include" \
OPTIONS="-DBSPF_UNIX=1" \ OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \ OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/openwin/lib" \ LDFLAGS="-L/usr/openwin/lib" \
LDFLAGS+="$(CFLAGS.X11)" \ LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \ LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \ LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o" OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o"
OBJS+="$(OBJS.X11)" OBJS+="$(OBJS.X11)"
############################################################################### ###############################################################################
@ -430,6 +430,9 @@ Deserializer.o: $(CORE)/Deserializer.cxx $(CORE)/Deserializer.hxx
Settings.o: $(CORE)/Settings.cxx $(CORE)/Settings.hxx Settings.o: $(CORE)/Settings.cxx $(CORE)/Settings.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/Settings.cxx $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/Settings.cxx
SettingsUNIX.o: $(UI)/common/SettingsUNIX.cxx $(UI)/common/SettingsUNIX.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(UI)/common/SettingsUNIX.cxx
Terminal.o: $(UI)/x11/Terminal.cxx $(UI)/x11/Terminal.hxx Terminal.o: $(UI)/x11/Terminal.cxx $(UI)/x11/Terminal.hxx
$(CXX) -c $(FLAGS) $(OPTIONS) $(UI)/x11/Terminal.cxx $(CXX) -c $(FLAGS) $(OPTIONS) $(UI)/x11/Terminal.cxx

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: Frontend.hxx,v 1.3 2003-09-07 18:30:28 stephena Exp $ // $Id: Frontend.hxx,v 1.4 2003-09-11 20:53:51 stephena Exp $
//============================================================================ //============================================================================
#ifndef FRONTEND_HXX #ifndef FRONTEND_HXX
@ -27,7 +27,7 @@ class Console;
This class provides an interface for accessing frontend specific data. This class provides an interface for accessing frontend specific data.
@author Stephen Anthony @author Stephen Anthony
@version $Id: Frontend.hxx,v 1.3 2003-09-07 18:30:28 stephena Exp $ @version $Id: Frontend.hxx,v 1.4 2003-09-11 20:53:51 stephena Exp $
*/ */
class Frontend class Frontend
{ {
@ -47,7 +47,7 @@ class Frontend
This method should be called when the emulation core sets This method should be called when the emulation core sets
the console object. the console object.
*/ */
virtual void setConsole(Console* console) = 0; virtual void setConsole(Console* console) = 0;
/** /**
This method should be called when the emulation core receives This method should be called when the emulation core receives

View File

@ -13,463 +13,36 @@
// 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: Settings.cxx,v 1.2 2003-09-07 18:30:28 stephena Exp $ // $Id: Settings.cxx,v 1.3 2003-09-11 20:53:51 stephena Exp $
//============================================================================ //============================================================================
#include <fstream> #include "bspf.hxx"
#include "Console.hxx"
#include "EventHandler.hxx"
#ifdef DEVELOPER_SUPPORT
#include "Props.hxx"
#endif
#include "Settings.hxx" #include "Settings.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings(const string& infile, const string& outfile) Settings::Settings()
: mySettingsInputFilename(infile),
mySettingsOutputFilename(outfile)
{ {
theKeymapList = "";
theJoymapList = "";
theUseFullScreenFlag = false;
theGrabMouseFlag = false;
theCenterWindowFlag = false;
theShowInfoFlag = false;
theHideCursorFlag = false;
theUsePrivateColormapFlag = false;
theMultipleSnapShotFlag = true;
theAccurateTimingFlag = true;
theDesiredVolume = -1;
theDesiredFrameRate = 60;
thePaddleMode = 0;
theAlternateProFile = "";
theSnapShotDir = "";
theSnapShotName = "";
theSoundDriver = "oss";
theWindowSize = 0;
#ifdef DEVELOPER_SUPPORT
userDefinedProperties.set("Display.Format", "-1");
userDefinedProperties.set("Display.XStart", "-1");
userDefinedProperties.set("Display.Width", "-1");
userDefinedProperties.set("Display.YStart", "-1");
userDefinedProperties.set("Display.Height", "-1");
theMergePropertiesFlag = false;
#endif
handleRCFile();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings(const string& infile, const string& outfile)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::~Settings() Settings::~Settings()
{ {
} }
void Settings::setConsole(Console* console) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings(const Settings&)
{ {
myConsole = console;
} }
bool Settings::handleCommandLineArgs(int argc, char* argv[]) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings& Settings::operator = (const Settings&)
{ {
// Make sure we have the correct number of command line arguments assert(false);
if(argc == 1)
return false;
for(Int32 i = 1; i < (argc - 1); ++i) return *this;
{
// See which command line switch they're using
if(string(argv[i]) == "-fps")
{
// They're setting the desired frame rate
Int32 rate = atoi(argv[++i]);
if((rate < 1) || (rate > 300))
{
rate = 60;
}
theDesiredFrameRate = rate;
}
else if(string(argv[i]) == "-paddle")
{
// They're trying to set the paddle emulation mode
if(string(argv[i + 1]) == "real")
{
thePaddleMode = 4;
}
else
{
// Make paddle mode 0 if incorrect input is given
thePaddleMode = atoi(argv[i + 1]);
if((thePaddleMode < 0) || (thePaddleMode > 3))
{
thePaddleMode = 0;
}
}
++i;
}
else if(string(argv[i]) == "-owncmap")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theUsePrivateColormapFlag = true;
else if(option == 0)
theUsePrivateColormapFlag = false;
}
else if(string(argv[i]) == "-fullscreen")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theUseFullScreenFlag = true;
else if(option == 0)
theUseFullScreenFlag = false;
}
else if(string(argv[i]) == "-grabmouse")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theGrabMouseFlag = true;
else if(option == 0)
theGrabMouseFlag = false;
}
else if(string(argv[i]) == "-hidecursor")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theHideCursorFlag = true;
else if(option == 0)
theHideCursorFlag = false;
}
else if(string(argv[i]) == "-center")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theCenterWindowFlag = true;
else if(option == 0)
theCenterWindowFlag = false;
}
else if(string(argv[i]) == "-showinfo")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theShowInfoFlag = true;
else if(option == 0)
theShowInfoFlag = false;
}
else if(string(argv[i]) == "-accurate")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theAccurateTimingFlag = true;
else if(option == 0)
theAccurateTimingFlag = false;
}
else if(string(argv[i]) == "-zoom")
{
uInt32 size = atoi(argv[++i]);
theWindowSize = size;
}
else if(string(argv[i]) == "-volume")
{
// They're setting the desired volume
Int32 volume = atoi(argv[++i]);
if(volume < -1)
volume = -1;
else if(volume > 100)
volume = 100;
theDesiredVolume = volume;
}
else if(string(argv[i]) == "-ssdir")
{
theSnapShotDir = argv[++i];
}
else if(string(argv[i]) == "-ssname")
{
theSnapShotName = argv[++i];
}
else if(string(argv[i]) == "-sssingle")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theMultipleSnapShotFlag = false;
else if(option == 0)
theMultipleSnapShotFlag = true;
}
else if(string(argv[i]) == "-pro")
{
theAlternateProFile = argv[++i];
}
else if(string(argv[i]) == "-sound")
{
theSoundDriver = argv[++i];
}
#ifdef DEVELOPER_SUPPORT
else if(string(argv[i]) == "-Dformat")
{
string option = argv[++i];
if((option == "NTSC") || (option == "PAL"))
userDefinedProperties.set("Display.Format", option);
}
else if(string(argv[i]) == "-Dxstart")
{
string option = argv[i+1];
uInt32 value = atoi(argv[++i]);
if((value >= 0) && (value <= 80) && ((value % 4) == 0))
userDefinedProperties.set("Display.XStart", option);
}
else if(string(argv[i]) == "-Dwidth")
{
string option = argv[i+1];
uInt32 value = atoi(argv[++i]);
if((value >= 80) && (value <= 160) && ((value % 4) == 0))
userDefinedProperties.set("Display.Width", option);
}
else if(string(argv[i]) == "-Dystart")
{
string option = argv[i+1];
uInt32 value = atoi(argv[++i]);
if((value >= 0) && (value <= 64))
userDefinedProperties.set("Display.YStart", option);
}
else if(string(argv[i]) == "-Dheight")
{
string option = argv[i+1];
uInt32 value = atoi(argv[++i]);
if((value >= 100) && (value <= 256))
userDefinedProperties.set("Display.Height", option);
}
else if(string(argv[i]) == "-Dmerge")
{
uInt32 option = atoi(argv[++i]);
if(option == 1)
theMergePropertiesFlag = true;
else if(option == 0)
theMergePropertiesFlag = false;
}
#endif
else
{
cout << "Undefined option " << argv[i] << endl;
}
}
return true;
}
void Settings::handleRCFile()
{
string line, key, value;
uInt32 equalPos;
ifstream in(mySettingsInputFilename.c_str());
if(!in || !in.is_open())
return;
while(getline(in, line))
{
// Strip all whitespace and tabs from the line
uInt32 garbage;
while((garbage = line.find(" ")) != string::npos)
line.erase(garbage, 1);
while((garbage = line.find("\t")) != string::npos)
line.erase(garbage, 1);
// Ignore commented and empty lines
if((line.length() == 0) || (line[0] == ';'))
continue;
// Search for the equal sign and discard the line if its not found
if((equalPos = line.find("=")) == string::npos)
continue;
key = line.substr(0, equalPos);
value = line.substr(equalPos + 1, line.length() - key.length() - 1);
// Check for absent key or value
if((key.length() == 0) || (value.length() == 0))
continue;
// Now set up the options by key
if(key == "fps")
{
// They're setting the desired frame rate
uInt32 rate = atoi(value.c_str());
if((rate < 1) || (rate > 300))
{
rate = 60;
}
theDesiredFrameRate = rate;
}
else if(key == "paddle")
{
// They're trying to set the paddle emulation mode
uInt32 pMode;
if(value == "real")
{
thePaddleMode = 4;
}
else
{
pMode = atoi(value.c_str());
if((pMode > 0) && (pMode < 4))
thePaddleMode = pMode;
}
}
else if(key == "owncmap")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theUsePrivateColormapFlag = true;
else if(option == 0)
theUsePrivateColormapFlag = false;
}
else if(key == "fullscreen")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theUseFullScreenFlag = true;
else if(option == 0)
theUseFullScreenFlag = false;
}
else if(key == "grabmouse")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theGrabMouseFlag = true;
else if(option == 0)
theGrabMouseFlag = false;
}
else if(key == "hidecursor")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theHideCursorFlag = true;
else if(option == 0)
theHideCursorFlag = false;
}
else if(key == "center")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theCenterWindowFlag = true;
else if(option == 0)
theCenterWindowFlag = false;
}
else if(key == "showinfo")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theShowInfoFlag = true;
else if(option == 0)
theShowInfoFlag = false;
}
else if(key == "accurate")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theAccurateTimingFlag = true;
else if(option == 0)
theAccurateTimingFlag = false;
}
else if(key == "zoom")
{
// They're setting the initial window size
// Don't do bounds checking here, it will be taken care of later
uInt32 size = atoi(value.c_str());
theWindowSize = size;
}
else if(key == "volume")
{
// They're setting the desired volume
Int32 volume = atoi(value.c_str());
if(volume < -1)
volume = -1;
else if(volume > 100)
volume = 100;
theDesiredVolume = volume;
}
else if(key == "ssdir")
{
theSnapShotDir = value;
}
else if(key == "ssname")
{
theSnapShotName = value;
}
else if(key == "sssingle")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theMultipleSnapShotFlag = false;
else if(option == 0)
theMultipleSnapShotFlag = true;
}
else if(key == "sound")
{
if((value != "oss") && (value != "sdl") && (value != "alsa"))
value = "0";
theSoundDriver = value;
}
else if(key == "keymap")
{
theKeymapList = value;
}
else if(key == "joymap")
{
theJoymapList = value;
}
#ifdef DEVELOPER_SUPPORT
else if(key == "Dmerge")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theMergePropertiesFlag = true;
else if(option == 0)
theMergePropertiesFlag = false;
}
#endif
}
in.close();
}
void Settings::save()
{
if(!myConsole)
return;
ofstream out(mySettingsOutputFilename.c_str());
if(!out || !out.is_open())
return;
out << "fps = " << theDesiredFrameRate << endl
<< "paddle = " << thePaddleMode << endl
<< "owncmap = " << theUsePrivateColormapFlag << endl
<< "fullscreen = " << theUseFullScreenFlag << endl
<< "grabmouse = " << theGrabMouseFlag << endl
<< "hidecursor = " << theHideCursorFlag << endl
<< "center = " << theCenterWindowFlag << endl
<< "showinfo = " << theShowInfoFlag << endl
<< "accurate = " << theAccurateTimingFlag << endl
<< "zoom = " << theWindowSize << endl
<< "volume = " << theDesiredVolume << endl
<< "ssdir = " << theSnapShotDir << endl
<< "ssname = " << theSnapShotName << endl
<< "sssingle = " << theMultipleSnapShotFlag << endl
<< "sound = " << theSoundDriver << endl
#ifdef DEVELOPER_SUPPORT
<< "Dmerge = " << theMergePropertiesFlag << endl
#endif
<< "keymap = " << myConsole->eventHandler().getKeymap() << endl
<< "joymap = " << myConsole->eventHandler().getJoymap() << endl
<< endl;
out.close();
} }

View File

@ -13,92 +13,70 @@
// 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: Settings.hxx,v 1.2 2003-09-07 18:30:28 stephena Exp $ // $Id: Settings.hxx,v 1.3 2003-09-11 20:53:51 stephena Exp $
//============================================================================ //============================================================================
#ifndef SETTINGS_HXX #ifndef SETTINGS_HXX
#define SETTINGS_HXX #define SETTINGS_HXX
#include "bspf.hxx"
#ifdef DEVELOPER_SUPPORT #ifdef DEVELOPER_SUPPORT
#include "Props.hxx" #include "Props.hxx"
#endif #endif
#include "bspf.hxx"
class Console; class Console;
/**
This class provides an interface for accessing frontend specific settings.
@author Stephen Anthony
@version $Id: Settings.hxx,v 1.3 2003-09-11 20:53:51 stephena Exp $
*/
class Settings class Settings
{ {
public: public:
/**
Create a new settings abstract class
*/
Settings();
Settings(const string& infile, const string& outfile); Settings(const string& infile, const string& outfile);
~Settings();
bool handleCommandLineArgs(int ac, char* av[]); /**
void save(); Destructor
void setConsole(Console* console); */
virtual ~Settings();
public: public:
/**
This method should be called to display the supported settings.
@param message A short message about this version of Stella
*/
virtual void usage(string& message) = 0;
/**
This method should be called to save the current settings to an rc file.
*/
virtual void save() = 0;
/**
This method should be called when the emulation core sets
the console object.
*/
virtual void setConsole(Console* console) = 0;
public:
// The following settings are used by the emulation core and are
// common among all settings objects
// The keymap to use // The keymap to use
string theKeymapList; string theKeymapList;
// The joymap to use // The joymap to use
string theJoymapList; string theJoymapList;
// Indicates whether to use fullscreen
bool theUseFullScreenFlag;
// Indicates whether mouse can leave the game window
bool theGrabMouseFlag;
// Indicates whether to center the game window
bool theCenterWindowFlag;
// Indicates whether to show some game info on program exit
bool theShowInfoFlag;
// Indicates whether to show cursor in the game window
bool theHideCursorFlag;
// Indicates whether to allocate colors from a private color map
bool theUsePrivateColormapFlag;
// Indicates whether to generate multiple snapshots or keep
// overwriting the same file. Set to true by default.
bool theMultipleSnapShotFlag;
// Indicates whether to use more/less accurate emulation,
// resulting in more/less CPU usage.
bool theAccurateTimingFlag;
// Indicates what the desired volume is
Int32 theDesiredVolume;
// Indicates what the desired frame rate is
uInt32 theDesiredFrameRate;
// Indicate which paddle mode we're using:
// 0 - Mouse emulates paddle 0
// 1 - Mouse emulates paddle 1
// 2 - Mouse emulates paddle 2
// 3 - Mouse emulates paddle 3
// 4 - Use real Atari 2600 paddles
uInt32 thePaddleMode;
// An alternate properties file to use
string theAlternateProFile;
// The path to save snapshot files
string theSnapShotDir;
// What the snapshot should be called (romname or md5sum)
string theSnapShotName;
// Indicates which sound driver to use at run-time
string theSoundDriver;
// The size of the window/screen
uInt32 theWindowSize;
#ifdef DEVELOPER_SUPPORT #ifdef DEVELOPER_SUPPORT
// User-modified properties // User-modified properties
Properties userDefinedProperties; Properties userDefinedProperties;
@ -109,16 +87,11 @@ class Settings
#endif #endif
private: private:
void handleRCFile(); // Copy constructor isn't supported by this class so make it private
Settings(const Settings&);
// The full pathname of the settings file for input // Assignment operator isn't supported by this class so make it private
string mySettingsInputFilename; Settings& operator = (const Settings&);
// The full pathname of the settings file for output
string mySettingsOutputFilename;
// The global Console object
Console* myConsole;
}; };
#endif #endif

View File

@ -0,0 +1,398 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-1999 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SettingsUNIX.cxx,v 1.1 2003-09-11 20:53:51 stephena Exp $
//============================================================================
#include <fstream>
#include "Console.hxx"
#include "EventHandler.hxx"
#include "StellaEvent.hxx"
#ifdef DEVELOPER_SUPPORT
#include "Props.hxx"
#endif
#include "Settings.hxx"
#include "SettingsUNIX.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SettingsUNIX::SettingsUNIX(const string& infile, const string& outfile)
: mySettingsInputFilename(infile),
mySettingsOutputFilename(outfile)
{
theKeymapList = "";
theJoymapList = "";
theUseFullScreenFlag = false;
theGrabMouseFlag = false;
theCenterWindowFlag = false;
theShowInfoFlag = false;
theHideCursorFlag = false;
theUsePrivateColormapFlag = false;
theMultipleSnapShotFlag = true;
theAccurateTimingFlag = true;
theDesiredVolume = -1;
theDesiredFrameRate = 60;
thePaddleMode = 0;
theAlternateProFile = "";
theSnapShotDir = "";
theSnapShotName = "";
theSoundDriver = "oss";
theWindowSize = 1;
theLeftJoystickNumber = 0;
theRightJoystickNumber = 1;
#ifdef DEVELOPER_SUPPORT
userDefinedProperties.set("Display.Format", "-1");
userDefinedProperties.set("Display.XStart", "-1");
userDefinedProperties.set("Display.Width", "-1");
userDefinedProperties.set("Display.YStart", "-1");
userDefinedProperties.set("Display.Height", "-1");
theMergePropertiesFlag = false;
#endif
handleRCFile();
}
SettingsUNIX::~SettingsUNIX()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsUNIX::setConsole(Console* console)
{
myConsole = console;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool SettingsUNIX::handleCommandLineArgs(int argc, char* argv[])
{
// Make sure we have the correct number of command line arguments
if(argc == 1)
return false;
for(Int32 i = 1; i < (argc - 1); ++i)
{
// strip off the '-' character
string key = argv[i];
key = key.substr(1, key.length());
string value = argv[++i];
parseArg(key, value);
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsUNIX::handleRCFile()
{
string line, key, value;
uInt32 equalPos;
ifstream in(mySettingsInputFilename.c_str());
if(!in || !in.is_open())
return;
while(getline(in, line))
{
// Strip all whitespace and tabs from the line
uInt32 garbage;
while((garbage = line.find(" ")) != string::npos)
line.erase(garbage, 1);
while((garbage = line.find("\t")) != string::npos)
line.erase(garbage, 1);
// Ignore commented and empty lines
if((line.length() == 0) || (line[0] == ';'))
continue;
// Search for the equal sign and discard the line if its not found
if((equalPos = line.find("=")) == string::npos)
continue;
key = line.substr(0, equalPos);
value = line.substr(equalPos + 1, line.length() - key.length() - 1);
// Check for absent key or value
if((key.length() == 0) || (value.length() == 0))
continue;
parseArg(key, value);
}
in.close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsUNIX::parseArg(string& key, string& value)
{
// Now set up the options by key
if(key == "fps")
{
// They're setting the desired frame rate
uInt32 rate = atoi(value.c_str());
if((rate < 1) || (rate > 300))
cout << "Invalid rate " << rate << " (1-300)\n";
else
theDesiredFrameRate = rate;
}
else if(key == "paddle")
{
// They're trying to set the paddle emulation mode
uInt32 pMode;
if(value == "real")
{
thePaddleMode = 4;
}
else
{
pMode = atoi(value.c_str());
if((pMode > 0) && (pMode < 4))
thePaddleMode = pMode;
}
}
else if(key == "owncmap")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theUsePrivateColormapFlag = true;
else if(option == 0)
theUsePrivateColormapFlag = false;
}
else if(key == "fullscreen")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theUseFullScreenFlag = true;
else if(option == 0)
theUseFullScreenFlag = false;
}
else if(key == "grabmouse")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theGrabMouseFlag = true;
else if(option == 0)
theGrabMouseFlag = false;
}
else if(key == "hidecursor")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theHideCursorFlag = true;
else if(option == 0)
theHideCursorFlag = false;
}
else if(key == "center")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theCenterWindowFlag = true;
else if(option == 0)
theCenterWindowFlag = false;
}
else if(key == "showinfo")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theShowInfoFlag = true;
else if(option == 0)
theShowInfoFlag = false;
}
else if(key == "accurate")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theAccurateTimingFlag = true;
else if(option == 0)
theAccurateTimingFlag = false;
}
else if(key == "zoom")
{
// They're setting the initial window size
uInt32 size = atoi(value.c_str());
if((size < 1) || (size > 4))
cout << "Invalid zoom value " << size << " (1-4)\n";
else
theWindowSize = size;
}
else if(key == "volume")
{
// They're setting the desired volume
Int32 volume = atoi(value.c_str());
if(volume < -1)
volume = -1;
else if(volume > 100)
volume = 100;
theDesiredVolume = volume;
}
else if(key == "ssdir")
{
theSnapShotDir = value;
}
else if(key == "ssname")
{
theSnapShotName = value;
}
else if(key == "sssingle")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theMultipleSnapShotFlag = false;
else if(option == 0)
theMultipleSnapShotFlag = true;
}
else if(key == "sound")
{
if((value != "oss") && (value != "sdl") && (value != "alsa"))
value = "0";
theSoundDriver = value;
}
else if(key == "keymap")
{
theKeymapList = value;
}
else if(key == "joymap")
{
theJoymapList = value;
}
else if(key == "joyleft")
{
Int32 joynum = atoi(value.c_str());
if((joynum < 0) || (joynum >= StellaEvent::LastJSTICK))
cout << "Invalid left joystick.\n";
else
theLeftJoystickNumber = joynum;
}
else if(key == "joyright")
{
Int32 joynum = atoi(value.c_str());
if((joynum < 0) || (joynum >= StellaEvent::LastJSTICK))
cout << "Invalid right joystick.\n";
else
theRightJoystickNumber = joynum;
}
#ifdef DEVELOPER_SUPPORT
else if(key == "Dmerge")
{
uInt32 option = atoi(value.c_str());
if(option == 1)
theMergePropertiesFlag = true;
else if(option == 0)
theMergePropertiesFlag = false;
}
#endif
else
{
cout << "Undefined option " << key << endl;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsUNIX::save()
{
if(!myConsole)
return;
ofstream out(mySettingsOutputFilename.c_str());
if(!out || !out.is_open())
return;
out << "fps = " << theDesiredFrameRate << endl
<< "paddle = " << thePaddleMode << endl
<< "owncmap = " << theUsePrivateColormapFlag << endl
<< "fullscreen = " << theUseFullScreenFlag << endl
<< "grabmouse = " << theGrabMouseFlag << endl
<< "hidecursor = " << theHideCursorFlag << endl
<< "center = " << theCenterWindowFlag << endl
<< "showinfo = " << theShowInfoFlag << endl
<< "accurate = " << theAccurateTimingFlag << endl
<< "zoom = " << theWindowSize << endl
<< "volume = " << theDesiredVolume << endl
<< "ssdir = " << theSnapShotDir << endl
<< "ssname = " << theSnapShotName << endl
<< "sssingle = " << theMultipleSnapShotFlag << endl
<< "sound = " << theSoundDriver << endl
#ifdef DEVELOPER_SUPPORT
<< "Dmerge = " << theMergePropertiesFlag << endl
#endif
<< "keymap = " << myConsole->eventHandler().getKeymap() << endl
<< "joymap = " << myConsole->eventHandler().getJoymap() << endl
<< "joyleft = " << theLeftJoystickNumber << endl
<< "joyright = " << theRightJoystickNumber << endl
<< endl;
out.close();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsUNIX::usage(string& message)
{
cout << endl
<< message << endl
<< endl
<< "Valid options are:" << endl
<< endl
<< " -fps <number> Display the given number of frames per second\n"
<< " -zoom <size> Makes window be 'size' times normal\n"
<< " -owncmap <0|1> Install a private colormap\n"
<< " -fullscreen <0|1> Play the game in fullscreen mode\n"
<< " -grabmouse <0|1> Keeps the mouse in the game window\n"
<< " -hidecursor <0|1> Hides the mouse cursor in the game window\n"
<< " -center <0|1> Centers the game window onscreen\n"
<< " -volume <number> Set the volume (0 - 100)\n"
#ifdef HAVE_JOYSTICK
<< " -paddle <0|1|2|3|real> Indicates which paddle the mouse should emulate\n"
<< " or that real Atari 2600 paddles are being used\n"
<< " -joyleft <number> The joystick number representing the left controller\n"
<< " -joyright <number> The joystick number representing the right controller\n"
#else
<< " -paddle <0|1|2|3> Indicates which paddle the mouse should emulate\n"
#endif
<< " -pro <props file> Use the given properties file instead of stella.pro\n"
<< " -showinfo <0|1> Shows some game info\n"
<< " -accurate <0|1> Accurate game timing (uses more CPU)\n"
#ifdef HAVE_PNG
<< " -ssdir <path> The directory to save snapshot files to\n"
<< " -ssname <name> How to name the snapshot (romname or md5sum)\n"
<< " -sssingle <0|1> Generate single snapshot instead of many\n"
#endif
<< endl
<< " -sound <type> Type is one of the following:\n"
<< " 0 Disables all sound generation\n"
#ifdef SOUND_ALSA
<< " alsa ALSA version 0.9 driver\n"
#endif
#ifdef SOUND_OSS
<< " oss Open Sound System driver\n"
#endif
<< endl
#ifdef DEVELOPER_SUPPORT
<< " DEVELOPER options (see Stella manual for details)\n"
<< " -Dformat Sets \"Display.Format\"\n"
<< " -Dxstart Sets \"Display.XStart\"\n"
<< " -Dwidth Sets \"Display.Width\"\n"
<< " -Dystart Sets \"Display.YStart\"\n"
<< " -Dheight Sets \"Display.Height\"\n"
<< " -Dmerge <0|1> Merge changed properties into properties file,\n"
<< " or save into a separate file\n"
#endif
<< endl;
}

View File

@ -0,0 +1,146 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-1999 by Bradford W. Mott
//
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: SettingsUNIX.hxx,v 1.1 2003-09-11 20:53:51 stephena Exp $
//============================================================================
#ifndef SETTINGS_UNIX_HXX
#define SETTINGS_UNIX_HXX
#include "bspf.hxx"
class Console;
/**
This class defines UNIX-like OS's (Linux) system specific settings.
@author Stephen Anthony
@version $Id: SettingsUNIX.hxx,v 1.1 2003-09-11 20:53:51 stephena Exp $
*/
class SettingsUNIX : public Settings
{
public:
/**
Create a new UNIX settings object
*/
SettingsUNIX(const string& infile, const string& outfile);
/**
Destructor
*/
virtual ~SettingsUNIX();
public:
/**
Display the commandline settings for this UNIX version of Stella.
@param message A short message about this version of Stella
*/
virtual void usage(string& message);
/**
Save the current settings to an rc file.
*/
virtual void save();
/**
Let the frontend know about the console object.
*/
virtual void setConsole(Console* console);
public:
/**
Handle UNIX commandline arguments
*/
bool handleCommandLineArgs(Int32 ac, char** av);
public:
// Indicates whether to use fullscreen
bool theUseFullScreenFlag;
// Indicates whether mouse can leave the game window
bool theGrabMouseFlag;
// Indicates whether to center the game window
bool theCenterWindowFlag;
// Indicates whether to show some game info on program exit
bool theShowInfoFlag;
// Indicates whether to show cursor in the game window
bool theHideCursorFlag;
// Indicates whether to allocate colors from a private color map
bool theUsePrivateColormapFlag;
// Indicates whether to generate multiple snapshots or keep
// overwriting the same file. Set to true by default.
bool theMultipleSnapShotFlag;
// Indicates whether to use more/less accurate emulation,
// resulting in more/less CPU usage.
bool theAccurateTimingFlag;
// Indicates what the desired volume is
Int32 theDesiredVolume;
// Indicates what the desired frame rate is
uInt32 theDesiredFrameRate;
// Indicate which paddle mode we're using:
// 0 - Mouse emulates paddle 0
// 1 - Mouse emulates paddle 1
// 2 - Mouse emulates paddle 2
// 3 - Mouse emulates paddle 3
// 4 - Use real Atari 2600 paddles
uInt32 thePaddleMode;
// An alternate properties file to use
string theAlternateProFile;
// The path to save snapshot files
string theSnapShotDir;
// What the snapshot should be called (romname or md5sum)
string theSnapShotName;
// Indicates which sound driver to use at run-time
string theSoundDriver;
// The size of the window/screen
uInt32 theWindowSize;
// The left joystick number (0 .. StellaEvent::LastJSTICK)
Int32 theLeftJoystickNumber;
// The right joystick number (0 .. StellaEvent::LastJSTICK)
Int32 theRightJoystickNumber;
private:
void handleRCFile();
void parseArg(string& key, string& value);
// The full pathname of the settings file for input
string mySettingsInputFilename;
// The full pathname of the settings file for output
string mySettingsOutputFilename;
// The global Console object
Console* myConsole;
};
#endif

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: mainSDL.cxx,v 1.48 2003-09-11 00:13:39 stephena Exp $ // $Id: mainSDL.cxx,v 1.49 2003-09-11 20:53:51 stephena Exp $
//============================================================================ //============================================================================
#include <fstream> #include <fstream>
@ -58,9 +58,10 @@
#include "Snapshot.hxx" #include "Snapshot.hxx"
#endif #endif
//#ifdef UNIX #ifdef UNIX
#include "FrontendUNIX.hxx" #include "FrontendUNIX.hxx"
//#endif #include "SettingsUNIX.hxx"
#endif
// Hack for SDL < 1.2.0 // Hack for SDL < 1.2.0
#ifndef SDL_ENABLE #ifndef SDL_ENABLE
@ -116,20 +117,29 @@ static string theSnapShotDir, theSnapShotName;
#ifdef HAVE_JOYSTICK #ifdef HAVE_JOYSTICK
static SDL_Joystick* theLeftJoystick = (SDL_Joystick*) NULL; static SDL_Joystick* theLeftJoystick = (SDL_Joystick*) NULL;
static SDL_Joystick* theRightJoystick = (SDL_Joystick*) NULL; static SDL_Joystick* theRightJoystick = (SDL_Joystick*) NULL;
static uInt32 theLeftJoystickNumber;
static uInt32 theRightJoystickNumber;
// static uInt32 thePaddleNumber;
#endif #endif
#ifdef HAVE_PNG #ifdef HAVE_PNG
static Snapshot* snapshot; static Snapshot* theSnapshot;
#endif #endif
// Pointer to the console object or the null pointer // Pointer to the console object or the null pointer
static Console* theConsole = (Console*) NULL; static Console* theConsole = (Console*) NULL;
// Pointer to the sound object or the null pointer // Pointer to the sound object or the null pointer
static Sound* sound = (Sound*) NULL; static Sound* theSound = (Sound*) NULL;
// Pointer to the frontend object or the null pointer // Pointer to the frontend object or the null pointer
static Frontend* frontend = (Frontend*) NULL; static Frontend* theFrontend = (Frontend*) NULL;
// Pointer to the settings object or the null pointer
#ifdef UNIX
static SettingsUNIX* theSettings = (SettingsUNIX*) NULL;
#endif
// Indicates if the mouse should be grabbed // Indicates if the mouse should be grabbed
static bool theGrabMouseIndicator = false; static bool theGrabMouseIndicator = false;
@ -262,6 +272,25 @@ StellaEvent::JoyCode joyButtonList[StellaEvent::LastJCODE] = {
}; };
/**
Returns number of ticks in microseconds
*/
#ifdef HAVE_GETTIMEOFDAY
inline uInt32 getTicks()
{
timeval now;
gettimeofday(&now, 0);
return (uInt32) (now.tv_sec * 1000000 + now.tv_usec);
}
#else
inline uInt32 getTicks()
{
return (uInt32) SDL_GetTicks() * 1000;
}
#endif
/** /**
This routine should be called once the console is created to setup This routine should be called once the console is created to setup
the SDL window for us to use. Return false if any operation fails, the SDL window for us to use. Return false if any operation fails,
@ -269,7 +298,7 @@ StellaEvent::JoyCode joyButtonList[StellaEvent::LastJCODE] = {
*/ */
bool setupDisplay() bool setupDisplay()
{ {
Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_TIMER; Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER;
if(SDL_Init(initflags) < 0) if(SDL_Init(initflags) < 0)
return false; return false;
@ -281,8 +310,8 @@ bool setupDisplay()
x11Available = true; x11Available = true;
sdlflags = SDL_SWSURFACE; sdlflags = SDL_SWSURFACE;
sdlflags |= theConsole->settings().theUseFullScreenFlag ? SDL_FULLSCREEN : 0; sdlflags |= theSettings->theUseFullScreenFlag ? SDL_FULLSCREEN : 0;
sdlflags |= theConsole->settings().theUsePrivateColormapFlag ? SDL_HWPALETTE : 0; sdlflags |= theSettings->theUsePrivateColormapFlag ? SDL_HWPALETTE : 0;
// Get the desired width and height of the display // Get the desired width and height of the display
theWidth = theConsole->mediaSource().width(); theWidth = theConsole->mediaSource().width();
@ -291,43 +320,13 @@ bool setupDisplay()
// Get the maximum size of a window for THIS screen // Get the maximum size of a window for THIS screen
// Must be called after display and screen are known, as well as // Must be called after display and screen are known, as well as
// theWidth and theHeight // theWidth and theHeight
// Defaults to 3 on systems without X11, maximum of 4 on any system.
theMaxWindowSize = maxWindowSizeForScreen(); theMaxWindowSize = maxWindowSizeForScreen();
// If theWindowSize is not 0, then it must have been set on the commandline // Check to see if window size will fit in the screen
// Now we check to see if it is within bounds if(theSettings->theWindowSize > theMaxWindowSize)
if(theConsole->settings().theWindowSize != 0) theWindowSize = theMaxWindowSize;
{
if(theConsole->settings().theWindowSize < 1)
theWindowSize = 1;
else if(theConsole->settings().theWindowSize > theMaxWindowSize)
theWindowSize = theMaxWindowSize;
else
theWindowSize = theConsole->settings().theWindowSize;
}
else // theWindowSize hasn't been set so we do the default
{
if(theMaxWindowSize < 2)
theWindowSize = 1;
else
theWindowSize = 2;
}
#if 0
//#ifdef HAVE_PNG
// Take care of the snapshot stuff.
snapshot = new Snapshot();
if(theConsole->settings().theSnapShotDir == "")
theSnapShotDir = homeDir;
else else
theSnapShotDir = theConsole->settings().theSnapShotDir; theWindowSize = theSettings->theWindowSize;
if(theConsole->settings().theSnapShotName == "")
theSnapShotName = "romname";
else
theSnapShotName = theConsole->settings().theSnapShotName;
#endif
// Set up the rectangle list to be used in updateDisplay // Set up the rectangle list to be used in updateDisplay
rectList = new RectList(); rectList = new RectList();
@ -348,9 +347,9 @@ bool setupDisplay()
setupPalette(); setupPalette();
// Make sure that theUseFullScreenFlag sets up fullscreen mode correctly // Make sure that theUseFullScreenFlag sets up fullscreen mode correctly
theGrabMouseIndicator = theConsole->settings().theGrabMouseFlag; theGrabMouseIndicator = theSettings->theGrabMouseFlag;
theHideCursorIndicator = theConsole->settings().theHideCursorFlag; theHideCursorIndicator = theSettings->theHideCursorFlag;
if(theConsole->settings().theUseFullScreenFlag) if(theSettings->theUseFullScreenFlag)
{ {
grabMouse(true); grabMouse(true);
showCursor(false); showCursor(false);
@ -366,7 +365,7 @@ bool setupDisplay()
} }
// Center the window if centering is selected and not fullscreen // Center the window if centering is selected and not fullscreen
if(theConsole->settings().theCenterWindowFlag && !theConsole->settings().theUseFullScreenFlag) if(theSettings->theCenterWindowFlag && !theSettings->theUseFullScreenFlag)
centerWindow(); centerWindow();
return true; return true;
@ -380,35 +379,38 @@ bool setupDisplay()
bool setupJoystick() bool setupJoystick()
{ {
#ifdef HAVE_JOYSTICK #ifdef HAVE_JOYSTICK
if(SDL_NumJoysticks() <= 0) // Initialize the joystick subsystem
if((SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) || (SDL_NumJoysticks() <= 0))
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "No joysticks present, use the keyboard.\n"; cout << "No joysticks present, use the keyboard.\n";
theLeftJoystick = theRightJoystick = 0; theLeftJoystick = theRightJoystick = 0;
return true; return true;
} }
if((theLeftJoystick = SDL_JoystickOpen(0)) != NULL) if((theLeftJoystick = SDL_JoystickOpen(theSettings->theLeftJoystickNumber)) != NULL)
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Left joystick is a " << SDL_JoystickName(0) << cout << "Left joystick is a "
" with " << SDL_JoystickNumButtons(theLeftJoystick) << " buttons.\n"; << SDL_JoystickName(theSettings->theLeftJoystickNumber)
<< " with " << SDL_JoystickNumButtons(theLeftJoystick) << " buttons.\n";
} }
else else
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Left joystick not present, use keyboard instead.\n"; cout << "Left joystick not present, use keyboard instead.\n";
} }
if((theRightJoystick = SDL_JoystickOpen(1)) != NULL) if((theRightJoystick = SDL_JoystickOpen(theSettings->theRightJoystickNumber)) != NULL)
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Right joystick is a " << SDL_JoystickName(1) << cout << "Right joystick is a "
" with " << SDL_JoystickNumButtons(theRightJoystick) << " buttons.\n"; << SDL_JoystickName(theSettings->theRightJoystickNumber)
<< " with " << SDL_JoystickNumButtons(theRightJoystick) << " buttons.\n";
} }
else else
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Right joystick not present, use keyboard instead.\n"; cout << "Right joystick not present, use keyboard instead.\n";
} }
#endif #endif
@ -500,7 +502,7 @@ void setupPalette()
// Make the palette be 75% as bright if pause is selected // Make the palette be 75% as bright if pause is selected
float shade = 1.0; float shade = 1.0;
if(frontend->pause()) if(theFrontend->pause())
shade = 0.75; shade = 0.75;
const uInt32* gamePalette = theConsole->mediaSource().palette(); const uInt32* gamePalette = theConsole->mediaSource().palette();
@ -549,7 +551,6 @@ void resizeWindow(int mode)
{ {
theWidth = theConsole->mediaSource().width(); theWidth = theConsole->mediaSource().width();
theHeight = theConsole->mediaSource().height(); theHeight = theConsole->mediaSource().height();
theMaxWindowSize = maxWindowSizeForScreen();
} }
else if(mode == 1) // increase size else if(mode == 1) // increase size
{ {
@ -578,7 +579,7 @@ void resizeWindow(int mode)
// A resize may mean that the window is no longer centered // A resize may mean that the window is no longer centered
isCentered = false; isCentered = false;
if(theConsole->settings().theCenterWindowFlag) if(theSettings->theCenterWindowFlag)
centerWindow(); centerWindow();
} }
@ -644,7 +645,7 @@ void toggleFullscreen()
grabMouse(theGrabMouseIndicator); grabMouse(theGrabMouseIndicator);
showCursor(!theHideCursorIndicator); showCursor(!theHideCursorIndicator);
if(theConsole->settings().theCenterWindowFlag) if(theSettings->theCenterWindowFlag)
centerWindow(); centerWindow();
} }
} }
@ -941,7 +942,7 @@ void handleEvents()
} }
else if((mod & KMOD_ALT) && key == SDLK_s) // Alt-s saves properties to a file else if((mod & KMOD_ALT) && key == SDLK_s) // Alt-s saves properties to a file
{ {
if(theConsole->settings().theMergePropertiesFlag) // Attempt to merge with propertiesSet if(theSettings->theMergePropertiesFlag) // Attempt to merge with propertiesSet
{ {
theConsole->saveProperties(theConsole->frontend().userPropertiesFilename(), true); theConsole->saveProperties(theConsole->frontend().userPropertiesFilename(), true);
} }
@ -1003,13 +1004,13 @@ void handleEvents()
resistance = (Int32)((fudgeFactor * x) / width); resistance = (Int32)((fudgeFactor * x) / width);
// Now, set the event of the correct paddle to the calculated resistance // Now, set the event of the correct paddle to the calculated resistance
if(theConsole->settings().thePaddleMode == 0) if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroResistance; type = Event::PaddleZeroResistance;
else if(theConsole->settings().thePaddleMode == 1) else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneResistance; type = Event::PaddleOneResistance;
else if(theConsole->settings().thePaddleMode == 2) else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoResistance; type = Event::PaddleTwoResistance;
else if(theConsole->settings().thePaddleMode == 3) else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeResistance; type = Event::PaddleThreeResistance;
theConsole->eventHandler().sendEvent(type, resistance); theConsole->eventHandler().sendEvent(type, resistance);
@ -1024,13 +1025,13 @@ void handleEvents()
else else
value = 0; value = 0;
if(theConsole->settings().thePaddleMode == 0) if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroFire; type = Event::PaddleZeroFire;
else if(theConsole->settings().thePaddleMode == 1) else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneFire; type = Event::PaddleOneFire;
else if(theConsole->settings().thePaddleMode == 2) else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoFire; type = Event::PaddleTwoFire;
else if(theConsole->settings().thePaddleMode == 3) else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeFire; type = Event::PaddleThreeFire;
theConsole->eventHandler().sendEvent(type, value); theConsole->eventHandler().sendEvent(type, value);
@ -1039,7 +1040,7 @@ void handleEvents()
{ {
if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0)) if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0))
{ {
if(!frontend->pause()) if(!theFrontend->pause())
{ {
theConsole->eventHandler().sendEvent(Event::Pause, 1); theConsole->eventHandler().sendEvent(Event::Pause, 1);
} }
@ -1074,42 +1075,23 @@ void handleEvents()
} }
else if(event.type == SDL_JOYAXISMOTION) else if(event.type == SDL_JOYAXISMOTION)
{ {
code = StellaEvent::LastJCODE;
state = 1;
axis = event.jaxis.axis; axis = event.jaxis.axis;
value = event.jaxis.value; value = event.jaxis.value;
if(axis == 0) // x-axis if(axis == 0) // x-axis
{ {
if(value < -16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT,
code = StellaEvent::JAXIS_LEFT; (value < -16384) ? 1 : 0);
else if(value > 16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT,
code = StellaEvent::JAXIS_RIGHT; (value > 16384) ? 1 : 0);
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT, 0);
return;
}
} }
else if(axis == 1) // y-axis else if(axis == 1) // y-axis
{ {
if(value < -16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP,
code = StellaEvent::JAXIS_UP; (value < -16384) ? 1 : 0);
else if(value > 16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN,
code = StellaEvent::JAXIS_DOWN; (value > 16384) ? 1 : 0);
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN, 0);
return;
}
} }
theConsole->eventHandler().sendJoyEvent(stick, code, state);
} }
#endif #endif
} }
@ -1131,7 +1113,7 @@ void takeSnapshot()
#ifdef HAVE_PNG #ifdef HAVE_PNG
string message; string message;
if(!snapshot) if(!theSnapshot)
{ {
message = "Snapshots disabled"; message = "Snapshots disabled";
theConsole->mediaSource().showMessage(message, 120); theConsole->mediaSource().showMessage(message, 120);
@ -1157,7 +1139,7 @@ void takeSnapshot()
replace(path.begin(), path.end(), ' ', '_'); replace(path.begin(), path.end(), ' ', '_');
// Check whether we want multiple snapshots created // Check whether we want multiple snapshots created
if(theConsole->settings().theMultipleSnapShotFlag) if(theSettings->theMultipleSnapShotFlag)
{ {
// Determine if the file already exists, checking each successive filename // Determine if the file already exists, checking each successive filename
// until one doesn't exist // until one doesn't exist
@ -1179,7 +1161,7 @@ void takeSnapshot()
filename = path + ".png"; filename = path + ".png";
// Now save the snapshot file // Now save the snapshot file
snapshot->savePNG(filename, theConsole->mediaSource(), theWindowSize); theSnapshot->savePNG(filename, theConsole->mediaSource(), theWindowSize);
if(access(filename.c_str(), F_OK) == 0) if(access(filename.c_str(), F_OK) == 0)
{ {
@ -1241,75 +1223,6 @@ uInt32 maxWindowSizeForScreen()
} }
/**
Display a usage message and exit the program
*/
void usage()
{
static const char* message[] = {
"",
"SDL Stella version 1.4pre",
"",
"Usage: stella.sdl [option ...] file",
"",
"Valid options are:",
"",
" -fps <number> Display the given number of frames per second",
" -owncmap <0|1> Install a private colormap",
" -zoom <size> Makes window be 'size' times normal (1 - 4)",
" -fullscreen <0|1> Play the game in fullscreen mode",
" -grabmouse <0|1> Keeps the mouse in the game window",
" -hidecursor <0|1> Hides the mouse cursor in the game window",
" -center <0|1> Centers the game window onscreen",
" -volume <number> Set the volume (0 - 100)",
#ifdef HAVE_JOYSTICK
" -paddle <0|1|2|3|real> Indicates which paddle the mouse should emulate",
" or that real Atari 2600 paddles are being used",
#else
" -paddle <0|1|2|3> Indicates which paddle the mouse should emulate",
#endif
" -showinfo <0|1> Shows some game info",
#ifdef HAVE_PNG
" -ssdir <path> The directory to save snapshot files to",
" -ssname <name> How to name the snapshot (romname or md5sum)",
" -sssingle <0|1> Generate single snapshot instead of many",
#endif
" -pro <props file> Use the given properties file instead of stella.pro",
" -accurate <0|1> Accurate game timing (uses more CPU)",
"",
" -sound <type> Type is one of the following:",
" 0 Disables all sound generation",
#ifdef SOUND_ALSA
" alsa ALSA version 0.9 driver",
#endif
#ifdef SOUND_OSS
" oss Open Sound System driver",
#endif
#ifdef SOUND_SDL
" sdl Native SDL driver",
#endif
"",
#ifdef DEVELOPER_SUPPORT
" DEVELOPER options (see Stella manual for details)",
" -Dformat Sets \"Display.Format\"",
" -Dxstart Sets \"Display.XStart\"",
" -Dwidth Sets \"Display.Width\"",
" -Dystart Sets \"Display.YStart\"",
" -Dheight Sets \"Display.Height\"",
" -Dmerge <0|1> Merge changed properties into properties file,",
" or save into a separate file",
#endif
0
};
for(uInt32 i = 0; message[i] != 0; ++i)
{
cout << message[i] << endl;
}
exit(1);
}
/** /**
Setup the properties set by first checking for a user file Setup the properties set by first checking for a user file
"$HOME/.stella/stella.pro", then a system-wide file "/etc/stella.pro". "$HOME/.stella/stella.pro", then a system-wide file "/etc/stella.pro".
@ -1317,7 +1230,7 @@ void usage()
@param set The properties set to setup @param set The properties set to setup
*/ */
bool setupProperties(PropertiesSet& set, Settings& settings) bool setupProperties(PropertiesSet& set)
{ {
bool useMemList = false; bool useMemList = false;
@ -1325,25 +1238,25 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
// If the user wishes to merge any property modifications to the // If the user wishes to merge any property modifications to the
// PropertiesSet file, then the PropertiesSet file MUST be loaded // PropertiesSet file, then the PropertiesSet file MUST be loaded
// into memory. // into memory.
useMemList = settings.theMergePropertiesFlag; useMemList = theSettings->theMergePropertiesFlag;
#endif #endif
// Check to see if the user has specified an alternate .pro file. // Check to see if the user has specified an alternate .pro file.
if(settings.theAlternateProFile != "") if(theSettings->theAlternateProFile != "")
{ {
set.load(settings.theAlternateProFile, &Console::defaultProperties(), useMemList); set.load(theSettings->theAlternateProFile, &Console::defaultProperties(), useMemList);
return true; return true;
} }
if(frontend->userPropertiesFilename() != "") if(theFrontend->userPropertiesFilename() != "")
{ {
set.load(frontend->userPropertiesFilename(), set.load(theFrontend->userPropertiesFilename(),
&Console::defaultProperties(), useMemList); &Console::defaultProperties(), useMemList);
return true; return true;
} }
else if(frontend->systemPropertiesFilename() != "") else if(theFrontend->systemPropertiesFilename() != "")
{ {
set.load(frontend->systemPropertiesFilename(), set.load(theFrontend->systemPropertiesFilename(),
&Console::defaultProperties(), useMemList); &Console::defaultProperties(), useMemList);
return true; return true;
} }
@ -1360,24 +1273,24 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
*/ */
void cleanup() void cleanup()
{ {
if(frontend) if(theSettings)
delete frontend; delete theSettings;
if(theFrontend)
delete theFrontend;
if(theConsole) if(theConsole)
delete theConsole; delete theConsole;
#ifdef HAVE_PNG #ifdef HAVE_PNG
if(snapshot) if(theSnapshot)
delete snapshot; delete theSnapshot;
#endif #endif
if(rectList) if(theSound)
delete rectList;
if(sound)
{ {
sound->closeDevice(); theSound->closeDevice();
delete sound; delete theSound;
} }
if(SDL_WasInit(SDL_INIT_EVERYTHING)) if(SDL_WasInit(SDL_INIT_EVERYTHING))
@ -1398,10 +1311,10 @@ void cleanup()
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
// First set up the frontend to communicate with the emulation core // First set up the frontend to communicate with the emulation core
//#ifdef UNIX #ifdef UNIX
frontend = new FrontendUNIX(); theFrontend = new FrontendUNIX();
//#endif #endif
if(!frontend) if(!theFrontend)
{ {
cerr << "ERROR: Couldn't set up the frontend.\n"; cerr << "ERROR: Couldn't set up the frontend.\n";
cleanup(); cleanup();
@ -1410,22 +1323,45 @@ int main(int argc, char* argv[])
// Create some settings for the emulator // Create some settings for the emulator
string infile = ""; string infile = "";
string outfile = frontend->userConfigFilename(); string outfile = theFrontend->userConfigFilename();
if(frontend->userConfigFilename() != "") if(theFrontend->userConfigFilename() != "")
infile = frontend->userConfigFilename(); infile = theFrontend->userConfigFilename();
else if(frontend->systemConfigFilename() != "") else if(theFrontend->systemConfigFilename() != "")
infile = frontend->systemConfigFilename(); infile = theFrontend->systemConfigFilename();
Settings settings(infile, outfile); #ifdef UNIX
theSettings = new SettingsUNIX(infile, outfile);
// Handle the command line arguments #endif
if(!settings.handleCommandLineArgs(argc, argv)) if(!theSettings)
{ {
usage();
cleanup(); cleanup();
return 0; return 0;
} }
// Take care of commandline arguments
if(!theSettings->handleCommandLineArgs(argc, argv))
{
string message = "Stella for SDL version 1.4\n\nUsage: stella.sdl [option ...] file";
theSettings->usage(message);
cleanup();
return 0;
}
#ifdef HAVE_PNG
// Take care of the snapshot stuff.
theSnapshot = new Snapshot();
if(theSettings->theSnapShotDir == "")
theSnapShotDir = theFrontend->userHomeDir();
else
theSnapShotDir = theSettings->theSnapShotDir;
if(theSettings->theSnapShotName == "")
theSnapShotName = "romname";
else
theSnapShotName = theSettings->theSnapShotName;
#endif
// Get a pointer to the file which contains the cartridge ROM // Get a pointer to the file which contains the cartridge ROM
const char* file = argv[argc - 1]; const char* file = argv[argc - 1];
@ -1445,7 +1381,7 @@ int main(int argc, char* argv[])
// Create a properties set for us to use and set it up // Create a properties set for us to use and set it up
PropertiesSet propertiesSet; PropertiesSet propertiesSet;
if(!setupProperties(propertiesSet, settings)) if(!setupProperties(propertiesSet))
{ {
delete[] image; delete[] image;
cleanup(); cleanup();
@ -1453,52 +1389,52 @@ int main(int argc, char* argv[])
} }
// Create a sound object for playing audio // Create a sound object for playing audio
if(settings.theSoundDriver == "0") if(theSettings->theSoundDriver == "0")
{ {
// even if sound has been disabled, we still need a sound object // even if sound has been disabled, we still need a sound object
sound = new Sound(); theSound = new Sound();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Sound disabled.\n"; cout << "Sound disabled.\n";
} }
#ifdef SOUND_ALSA #ifdef SOUND_ALSA
else if(settings.theSoundDriver == "alsa") else if(theSettings->theSoundDriver == "alsa")
{ {
sound = new SoundALSA(); theSound = new SoundALSA();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Using ALSA for sound.\n"; cout << "Using ALSA for sound.\n";
} }
#endif #endif
#ifdef SOUND_OSS #ifdef SOUND_OSS
else if(settings.theSoundDriver == "oss") else if(theSettings->theSoundDriver == "oss")
{ {
sound = new SoundOSS(); theSound = new SoundOSS();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Using OSS for sound.\n"; cout << "Using OSS for sound.\n";
} }
#endif #endif
#ifdef SOUND_SDL #ifdef SOUND_SDL
else if(settings.theSoundDriver == "sdl") else if(theSettings->theSoundDriver == "sdl")
{ {
sound = new SoundSDL(); theSound = new SoundSDL();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Using SDL for sound.\n"; cout << "Using SDL for sound.\n";
} }
#endif #endif
else // a driver that doesn't exist was requested, so disable sound else // a driver that doesn't exist was requested, so disable sound
{ {
cerr << "ERROR: Sound support for " cerr << "ERROR: Sound support for "
<< settings.theSoundDriver << " not available.\n"; << theSettings->theSoundDriver << " not available.\n";
sound = new Sound(); theSound = new Sound();
} }
sound->setSoundVolume(settings.theDesiredVolume); theSound->setSoundVolume(theSettings->theDesiredVolume);
// Get just the filename of the file containing the ROM image // Get just the filename of the file containing the ROM image
const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1; const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1;
// Create the 2600 game console // Create the 2600 game console
theConsole = new Console(image, size, filename, settings, propertiesSet, theConsole = new Console(image, size, filename, *theSettings, propertiesSet,
*frontend, sound->getSampleRate()); *theFrontend, theSound->getSampleRate());
// Free the image since we don't need it any longer // Free the image since we don't need it any longer
delete[] image; delete[] image;
@ -1521,11 +1457,11 @@ int main(int argc, char* argv[])
// and are needed to calculate the overall frames per second. // and are needed to calculate the overall frames per second.
uInt32 frameTime = 0, numberOfFrames = 0; uInt32 frameTime = 0, numberOfFrames = 0;
if(settings.theAccurateTimingFlag) // normal, CPU-intensive timing if(theSettings->theAccurateTimingFlag) // normal, CPU-intensive timing
{ {
// Set up accurate timing stuff // Set up accurate timing stuff
uInt32 startTime, delta; uInt32 startTime, delta;
uInt32 timePerFrame = (uInt32)(1000000.0 / (double)settings.theDesiredFrameRate); uInt32 timePerFrame = (uInt32)(1000000.0 / (double)theSettings->theDesiredFrameRate);
// Set the base for the timers // Set the base for the timers
frameTime = 0; frameTime = 0;
@ -1534,7 +1470,7 @@ int main(int argc, char* argv[])
for(;;) for(;;)
{ {
// Exit if the user wants to quit // Exit if the user wants to quit
if(frontend->quit()) if(theFrontend->quit())
{ {
break; break;
} }
@ -1542,7 +1478,7 @@ int main(int argc, char* argv[])
// Call handleEvents here to see if user pressed pause // Call handleEvents here to see if user pressed pause
startTime = getTicks(); startTime = getTicks();
handleEvents(); handleEvents();
if(frontend->pause()) if(theFrontend->pause())
{ {
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
SDL_Delay(10); SDL_Delay(10);
@ -1551,7 +1487,7 @@ int main(int argc, char* argv[])
theConsole->mediaSource().update(); theConsole->mediaSource().update();
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
sound->updateSound(theConsole->mediaSource()); theSound->updateSound(theConsole->mediaSource());
// Now, waste time if we need to so that we are at the desired frame rate // Now, waste time if we need to so that we are at the desired frame rate
for(;;) for(;;)
@ -1570,7 +1506,7 @@ int main(int argc, char* argv[])
{ {
// Set up less accurate timing stuff // Set up less accurate timing stuff
uInt32 startTime, virtualTime, currentTime; uInt32 startTime, virtualTime, currentTime;
uInt32 timePerFrame = (uInt32)(1000000.0 / (double)theConsole->settings().theDesiredFrameRate); uInt32 timePerFrame = (uInt32)(1000000.0 / (double)theSettings->theDesiredFrameRate);
// Set the base for the timers // Set the base for the timers
virtualTime = getTicks(); virtualTime = getTicks();
@ -1580,17 +1516,17 @@ int main(int argc, char* argv[])
for(;;) for(;;)
{ {
// Exit if the user wants to quit // Exit if the user wants to quit
if(frontend->quit()) if(theFrontend->quit())
{ {
break; break;
} }
startTime = getTicks(); startTime = getTicks();
handleEvents(); handleEvents();
if(!frontend->pause()) if(!theFrontend->pause())
{ {
theConsole->mediaSource().update(); theConsole->mediaSource().update();
sound->updateSound(theConsole->mediaSource()); theSound->updateSound(theConsole->mediaSource());
} }
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
@ -1607,7 +1543,7 @@ int main(int argc, char* argv[])
} }
} }
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
{ {
double executionTime = (double) frameTime / 1000000.0; double executionTime = (double) frameTime / 1000000.0;
double framesPerSecond = (double) numberOfFrames / executionTime; double framesPerSecond = (double) numberOfFrames / executionTime;
@ -1626,22 +1562,3 @@ int main(int argc, char* argv[])
cleanup(); cleanup();
return 0; return 0;
} }
/**
Returns number of ticks in microseconds
*/
#ifdef HAVE_GETTIMEOFDAY
inline uInt32 getTicks()
{
timeval now;
gettimeofday(&now, 0);
return (uInt32) (now.tv_sec * 1000000 + now.tv_usec);
}
#else
inline uInt32 getTicks()
{
return (uInt32) SDL_GetTicks() * 1000;
}
#endif

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: mainX11.cxx,v 1.39 2003-09-11 00:13:39 stephena Exp $ // $Id: mainX11.cxx,v 1.40 2003-09-11 20:53:51 stephena Exp $
//============================================================================ //============================================================================
#include <fstream> #include <fstream>
@ -22,11 +22,12 @@
#include <string> #include <string>
#include <algorithm> #include <algorithm>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h>
#include <sys/stat.h> #ifdef HAVE_GETTIMEOFDAY
#include <sys/types.h> #include <time.h>
#include <sys/time.h>
#endif
#include <X11/Xos.h> #include <X11/Xos.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -59,14 +60,16 @@
#endif #endif
#ifdef HAVE_JOYSTICK #ifdef HAVE_JOYSTICK
#include <unistd.h> #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/joystick.h> #include <linux/joystick.h>
#endif #endif
//#ifdef UNIX #ifdef UNIX
#include "FrontendUNIX.hxx" #include "FrontendUNIX.hxx"
//#endif #include "SettingsUNIX.hxx"
#endif
// function prototypes // function prototypes
// FIXME the following will be placed in a Display class eventually ... // FIXME the following will be placed in a Display class eventually ...
@ -115,23 +118,31 @@ static void changeState(int direction);
static string theSnapShotDir, theSnapShotName; static string theSnapShotDir, theSnapShotName;
#ifdef HAVE_PNG #ifdef HAVE_PNG
static Snapshot* snapshot; static Snapshot* theSnapshot;
#endif #endif
#ifdef HAVE_JOYSTICK #ifdef HAVE_JOYSTICK
// File descriptors for the joystick devices // File descriptors for the joystick devices
static int theLeftJoystickFd; static int theLeftJoystickFd;
static int theRightJoystickFd; static int theRightJoystickFd;
static uInt32 theLeftJoystickNumber;
static uInt32 theRightJoystickNumber;
// static uInt32 thePaddleNumber;
#endif #endif
// Pointer to the console object or the null pointer // Pointer to the console object or the null pointer
static Console* theConsole = (Console*) NULL; static Console* theConsole = (Console*) NULL;
// Pointer to the sound object or the null pointer // Pointer to the sound object or the null pointer
static Sound* sound = (Sound*) NULL; static Sound* theSound = (Sound*) NULL;
// Pointer to the frontend object or the null pointer // Pointer to the frontend object or the null pointer
static Frontend* frontend = (Frontend*) NULL; static Frontend* theFrontend = (Frontend*) NULL;
// Pointer to the settings object or the null pointer
#ifdef UNIX
static SettingsUNIX* theSettings = (SettingsUNIX*) NULL;
#endif
// Indicates if the mouse should be grabbed // Indicates if the mouse should be grabbed
static bool theGrabMouseIndicator = false; static bool theGrabMouseIndicator = false;
@ -315,26 +326,11 @@ bool setupDisplay()
// theWidth and theHeight // theWidth and theHeight
theMaxWindowSize = maxWindowSizeForScreen(); theMaxWindowSize = maxWindowSizeForScreen();
// FIXME - add this error checking to the Settings class // Check to see if window size will fit in the screen
// If theWindowSize is not 0, then it must have been set on the commandline if(theSettings->theWindowSize > theMaxWindowSize)
// Now we check to see if it is within bounds theWindowSize = theMaxWindowSize;
if(theConsole->settings().theWindowSize != 0) else
{ theWindowSize = theSettings->theWindowSize;
if(theConsole->settings().theWindowSize < 1)
theWindowSize = 1;
else if(theConsole->settings().theWindowSize > theMaxWindowSize)
theWindowSize = theMaxWindowSize;
else
theWindowSize = theConsole->settings().theWindowSize;
}
else // theWindowSize hasn't been set so we do the default
{
if(theMaxWindowSize < 2)
theWindowSize = 1;
else
theWindowSize = 2;
}
///////////////////////////////
// Figure out the desired size of the window // Figure out the desired size of the window
int width = theWidth * theWindowSize * 2; int width = theWidth * theWindowSize * 2;
@ -373,7 +369,7 @@ bool setupDisplay()
XSetWMProtocols(theDisplay, theWindow, &wm_delete_window, 1); XSetWMProtocols(theDisplay, theWindow, &wm_delete_window, 1);
// If requested install a private colormap for the window // If requested install a private colormap for the window
if(theConsole->settings().theUsePrivateColormapFlag) if(theSettings->theUsePrivateColormapFlag)
{ {
XSetWindowColormap(theDisplay, theWindow, thePrivateColormap); XSetWindowColormap(theDisplay, theWindow, thePrivateColormap);
} }
@ -382,7 +378,7 @@ bool setupDisplay()
XMapWindow(theDisplay, theWindow); XMapWindow(theDisplay, theWindow);
// Center the window if centering is selected and not fullscreen // Center the window if centering is selected and not fullscreen
if(theConsole->settings().theCenterWindowFlag)// && !theUseFullScreenFlag) if(theSettings->theCenterWindowFlag)// && !theUseFullScreenFlag)
centerWindow(); centerWindow();
XEvent event; XEvent event;
@ -397,63 +393,59 @@ bool setupDisplay()
// If we're using the mouse for paddle emulation then enable mouse events // If we're using the mouse for paddle emulation then enable mouse events
if(((theConsole->properties().get("Controller.Left") == "Paddles") || if(((theConsole->properties().get("Controller.Left") == "Paddles") ||
(theConsole->properties().get("Controller.Right") == "Paddles")) (theConsole->properties().get("Controller.Right") == "Paddles"))
&& (theConsole->settings().thePaddleMode != 4)) && (theSettings->thePaddleMode != 4))
{ {
eventMask |= (PointerMotionMask | ButtonPressMask | ButtonReleaseMask); eventMask |= (PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
} }
theGrabMouseIndicator = theSettings->theGrabMouseFlag;
theHideCursorIndicator = theSettings->theHideCursorFlag;
// Keep mouse in game window if grabmouse is selected // Keep mouse in game window if grabmouse is selected
grabMouse(theGrabMouseIndicator); grabMouse(theGrabMouseIndicator);
// Show or hide the cursor depending on the 'hidecursor' argument // Show or hide the cursor depending on the 'hidecursor' argument
showCursor(!theHideCursorIndicator); showCursor(!theHideCursorIndicator);
XSelectInput(theDisplay, theWindow, eventMask); XSelectInput(theDisplay, theWindow, eventMask);
#ifdef HAVE_PNG
// Take care of the snapshot stuff.
snapshot = new Snapshot();
if(theConsole->settings().theSnapShotDir == "")
theSnapShotDir = homeDir;
else
theSnapShotDir = theConsole->settings().theSnapShotDir;
if(theConsole->settings().theSnapShotName == "")
theSnapShotName = "romname";
else
theSnapShotName = theConsole->settings().theSnapShotName;
#endif
return true; return true;
} }
/** /**
This routine should be called once setupDisplay is called This routine should be called once the display is created
to create the joystick stuff to create the joystick stuff
*/ */
bool setupJoystick() bool setupJoystick()
{ {
#ifdef HAVE_JOYSTICK #ifdef HAVE_JOYSTICK
if((theLeftJoystickFd = open("/dev/js0", O_RDONLY | O_NONBLOCK)) >= 0) ostringstream joyname;
theLeftJoystickNumber = theSettings->theLeftJoystickNumber;
theRightJoystickNumber = theSettings->theRightJoystickNumber;
joyname.str("");
joyname << "/dev/js" << theLeftJoystickNumber;
if((theLeftJoystickFd = open(joyname.str().c_str(), O_RDONLY | O_NONBLOCK)) >= 0)
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Left joystick found.\n"; cout << "Left joystick set to " << joyname.str() << "." << endl;
} }
else else
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Left joystick not present, use keyboard instead.\n"; cout << "Left joystick not present, use keyboard instead.\n";
} }
if((theRightJoystickFd = open("/dev/js1", O_RDONLY | O_NONBLOCK)) >= 0) joyname.str("");
joyname << "/dev/js" << theRightJoystickNumber;
if((theRightJoystickFd = open(joyname.str().c_str(), O_RDONLY | O_NONBLOCK)) >= 0)
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Right joystick found.\n"; cout << "Right joystick set to " << joyname.str() << "." << endl;
} }
else else
{ {
if(theConsole->settings().theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Right joystick not present, use keyboard instead.\n"; cout << "Right joystick not present, use keyboard instead.\n";
} }
#endif #endif
@ -467,7 +459,7 @@ bool setupJoystick()
void setupPalette() void setupPalette()
{ {
// If we're using a private colormap then let's free it to be safe // If we're using a private colormap then let's free it to be safe
if(theConsole->settings().theUsePrivateColormapFlag && theDisplay) if(theSettings->theUsePrivateColormapFlag && theDisplay)
{ {
if(thePrivateColormap) if(thePrivateColormap)
XFreeColormap(theDisplay, thePrivateColormap); XFreeColormap(theDisplay, thePrivateColormap);
@ -478,7 +470,7 @@ void setupPalette()
// Make the palette be 75% as bright if pause is selected // Make the palette be 75% as bright if pause is selected
float shade = 1.0; float shade = 1.0;
if(frontend->pause()) if(theFrontend->pause())
shade = 0.75; shade = 0.75;
// Allocate colors in the default colormap // Allocate colors in the default colormap
@ -492,7 +484,7 @@ void setupPalette()
color.blue = (short unsigned int)(((palette[t] & 0x000000ff) << 8) * shade); color.blue = (short unsigned int)(((palette[t] & 0x000000ff) << 8) * shade);
color.flags = DoRed | DoGreen | DoBlue; color.flags = DoRed | DoGreen | DoBlue;
if(theConsole->settings().theUsePrivateColormapFlag) if(theSettings->theUsePrivateColormapFlag)
XAllocColor(theDisplay, thePrivateColormap, &color); XAllocColor(theDisplay, thePrivateColormap, &color);
else else
XAllocColor(theDisplay, DefaultColormap(theDisplay, theScreen), &color); XAllocColor(theDisplay, DefaultColormap(theDisplay, theScreen), &color);
@ -759,7 +751,7 @@ void handleEvents()
{ {
if(event.xkey.state & Mod1Mask) if(event.xkey.state & Mod1Mask)
{ {
if(theConsole->settings().theMergePropertiesFlag) // Attempt to merge with propertiesSet if(theSettings->theMergePropertiesFlag) // Attempt to merge with propertiesSet
{ {
theConsole->saveProperties(theConsole->frontend().userPropertiesFilename(), true); theConsole->saveProperties(theConsole->frontend().userPropertiesFilename(), true);
} }
@ -793,13 +785,13 @@ void handleEvents()
resistance = (Int32)((1000000.0 * x) / width); resistance = (Int32)((1000000.0 * x) / width);
// Now, set the event of the correct paddle to the calculated resistance // Now, set the event of the correct paddle to the calculated resistance
if(theConsole->settings().thePaddleMode == 0) if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroResistance; type = Event::PaddleZeroResistance;
else if(theConsole->settings().thePaddleMode == 1) else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneResistance; type = Event::PaddleOneResistance;
else if(theConsole->settings().thePaddleMode == 2) else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoResistance; type = Event::PaddleTwoResistance;
else if(theConsole->settings().thePaddleMode == 3) else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeResistance; type = Event::PaddleThreeResistance;
theConsole->eventHandler().sendEvent(type, resistance); theConsole->eventHandler().sendEvent(type, resistance);
@ -811,13 +803,13 @@ void handleEvents()
value = (event.type == ButtonPress) ? 1 : 0; value = (event.type == ButtonPress) ? 1 : 0;
if(theConsole->settings().thePaddleMode == 0) if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroFire; type = Event::PaddleZeroFire;
else if(theConsole->settings().thePaddleMode == 1) else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneFire; type = Event::PaddleOneFire;
else if(theConsole->settings().thePaddleMode == 2) else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoFire; type = Event::PaddleTwoFire;
else if(theConsole->settings().thePaddleMode == 3) else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeFire; type = Event::PaddleThreeFire;
theConsole->eventHandler().sendEvent(type, value); theConsole->eventHandler().sendEvent(type, value);
@ -828,7 +820,7 @@ void handleEvents()
} }
else if(event.type == UnmapNotify) else if(event.type == UnmapNotify)
{ {
if(!frontend->pause()) if(!theFrontend->pause())
{ {
theConsole->eventHandler().sendEvent(Event::Pause, 1); theConsole->eventHandler().sendEvent(Event::Pause, 1);
} }
@ -846,7 +838,7 @@ void handleEvents()
if(theLeftJoystickFd >= 0) if(theLeftJoystickFd >= 0)
{ {
struct js_event event; struct js_event event;
stick = joyList[0]; stick = joyList[theLeftJoystickNumber];
// Process each joystick event that's queued-up // Process each joystick event that's queued-up
while(read(theLeftJoystickFd, &event, sizeof(struct js_event)) > 0) while(read(theLeftJoystickFd, &event, sizeof(struct js_event)) > 0)
@ -863,104 +855,22 @@ void handleEvents()
} }
else if((event.type & ~JS_EVENT_INIT) == JS_EVENT_AXIS) else if((event.type & ~JS_EVENT_INIT) == JS_EVENT_AXIS)
{ {
code = StellaEvent::LastJCODE;
state = 1;
axis = event.number; axis = event.number;
value = event.value; value = event.value;
if(axis == 0) // x-axis if(axis == 0) // x-axis
{ {
if(value < -16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT,
code = StellaEvent::JAXIS_LEFT; (value < -16384) ? 1 : 0);
else if(value > 16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT,
code = StellaEvent::JAXIS_RIGHT; (value > 16384) ? 1 : 0);
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT, 0);
return;
}
} }
else if(axis == 1) // y-axis else if(axis == 1) // y-axis
{ {
if(value < -16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP,
code = StellaEvent::JAXIS_UP; (value < -16384) ? 1 : 0);
else if(value > 16384) theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN,
code = StellaEvent::JAXIS_DOWN; (value > 16384) ? 1 : 0);
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN, 0);
return;
}
}
theConsole->eventHandler().sendJoyEvent(stick, code, state);
}
}
}
/* // Read joystick events and modify event states
if(theLeftJoystickFd >= 0)
{
struct js_event event;
// Process each joystick event that's queued-up
while(read(theLeftJoystickFd, &event, sizeof(struct js_event)) > 0)
{
if((event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON)
{
if(event.number == 0)
{
theEvent.set(Event::JoystickZeroFire, event.value ?
1 : keyboardEvent.get(Event::JoystickZeroFire));
// If we're using real paddles then set paddle event as well
if(settings->thePaddleMode == 4)
theEvent.set(Event::PaddleZeroFire, event.value);
}
else if(event.number == 1)
{
theEvent.set(Event::BoosterGripZeroTrigger, event.value ?
1 : keyboardEvent.get(Event::BoosterGripZeroTrigger));
// If we're using real paddles then set paddle event as well
if(settings->thePaddleMode == 4)
theEvent.set(Event::PaddleOneFire, event.value);
}
}
else if((event.type & ~JS_EVENT_INIT) == JS_EVENT_AXIS)
{
if(event.number == 0)
{
theEvent.set(Event::JoystickZeroLeft, (event.value < -16384) ?
1 : keyboardEvent.get(Event::JoystickZeroLeft));
theEvent.set(Event::JoystickZeroRight, (event.value > 16384) ?
1 : keyboardEvent.get(Event::JoystickZeroRight));
// If we're using real paddles then set paddle events as well
if(settings->thePaddleMode == 4)
{
uInt32 r = (uInt32)((1.0E6L * (event.value + 32767L)) / 65536);
theEvent.set(Event::PaddleZeroResistance, r);
}
}
else if(event.number == 1)
{
theEvent.set(Event::JoystickZeroUp, (event.value < -16384) ?
1 : keyboardEvent.get(Event::JoystickZeroUp));
theEvent.set(Event::JoystickZeroDown, (event.value > 16384) ?
1 : keyboardEvent.get(Event::JoystickZeroDown));
// If we're using real paddles then set paddle events as well
if(settings->thePaddleMode == 4)
{
uInt32 r = (uInt32)((1.0E6L * (event.value + 32767L)) / 65536);
theEvent.set(Event::PaddleOneResistance, r);
}
} }
} }
} }
@ -969,64 +879,43 @@ void handleEvents()
if(theRightJoystickFd >= 0) if(theRightJoystickFd >= 0)
{ {
struct js_event event; struct js_event event;
stick = joyList[theRightJoystickNumber];
// Process each joystick event that's queued-up // Process each joystick event that's queued-up
while(read(theRightJoystickFd, &event, sizeof(struct js_event)) > 0) while(read(theRightJoystickFd, &event, sizeof(struct js_event)) > 0)
{ {
if((event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON) if((event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON)
{ {
if(event.number == 0) if(event.number >= StellaEvent::LastJCODE)
{ return;
theEvent.set(Event::JoystickOneFire, event.value ?
1 : keyboardEvent.get(Event::JoystickOneFire));
// If we're using real paddles then set paddle event as well code = joyButtonList[event.number];
if(settings->thePaddleMode == 4) state = event.value;
theEvent.set(Event::PaddleTwoFire, event.value);
}
else if(event.number == 1)
{
theEvent.set(Event::BoosterGripOneTrigger, event.value ?
1 : keyboardEvent.get(Event::BoosterGripOneTrigger));
// If we're using real paddles then set paddle event as well theConsole->eventHandler().sendJoyEvent(stick, code, state);
if(settings->thePaddleMode == 4)
theEvent.set(Event::PaddleThreeFire, event.value);
}
} }
else if((event.type & ~JS_EVENT_INIT) == JS_EVENT_AXIS) else if((event.type & ~JS_EVENT_INIT) == JS_EVENT_AXIS)
{ {
if(event.number == 0) axis = event.number;
{ value = event.value;
theEvent.set(Event::JoystickOneLeft, (event.value < -16384) ?
1 : keyboardEvent.get(Event::JoystickOneLeft));
theEvent.set(Event::JoystickOneRight, (event.value > 16384) ?
1 : keyboardEvent.get(Event::JoystickOneRight));
// If we're using real paddles then set paddle events as well if(axis == 0) // x-axis
if(settings->thePaddleMode == 4) {
{ theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT,
uInt32 r = (uInt32)((1.0E6L * (event.value + 32767L)) / 65536); (value < -16384) ? 1 : 0);
theEvent.set(Event::PaddleTwoResistance, r); theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT,
} (value > 16384) ? 1 : 0);
} }
else if(event.number == 1) else if(axis == 1) // y-axis
{ {
theEvent.set(Event::JoystickOneUp, (event.value < -16384) ? theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP,
1 : keyboardEvent.get(Event::JoystickOneUp)); (value < -16384) ? 1 : 0);
theEvent.set(Event::JoystickOneDown, (event.value > 16384) ? theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN,
1 : keyboardEvent.get(Event::JoystickOneDown)); (value > 16384) ? 1 : 0);
// If we're using real paddles then set paddle events as well
if(settings->thePaddleMode == 4)
{
uInt32 r = (uInt32)((1.0E6L * (event.value + 32767L)) / 65536);
theEvent.set(Event::PaddleThreeResistance, r);
}
} }
} }
} }
}*/ }
#endif #endif
} }
@ -1089,7 +978,7 @@ void resizeWindow(int mode)
// A resize probably means that the window is no longer centered // A resize probably means that the window is no longer centered
isCentered = false; isCentered = false;
if(theConsole->settings().theCenterWindowFlag) if(theSettings->theCenterWindowFlag)
centerWindow(); centerWindow();
} }
@ -1217,7 +1106,7 @@ void takeSnapshot()
#ifdef HAVE_PNG #ifdef HAVE_PNG
string message; string message;
if(!snapshot) if(!theSnapshot)
{ {
message = "Snapshots disabled"; message = "Snapshots disabled";
theConsole->mediaSource().showMessage(message, 120); theConsole->mediaSource().showMessage(message, 120);
@ -1225,16 +1114,16 @@ void takeSnapshot()
} }
// Now find the correct name for the snapshot // Now find the correct name for the snapshot
string path = settings->theSnapShotDir; string path = theSettings->theSnapShotDir;
string filename; string filename;
if(settings->theSnapShotName == "romname") if(theSettings->theSnapShotName == "romname")
path = path + "/" + theConsole->properties().get("Cartridge.Name"); path = path + "/" + theConsole->properties().get("Cartridge.Name");
else if(settings->theSnapShotName == "md5sum") else if(theSettings->theSnapShotName == "md5sum")
path = path + "/" + theConsole->properties().get("Cartridge.MD5"); path = path + "/" + theConsole->properties().get("Cartridge.MD5");
else else
{ {
cerr << "ERROR: unknown name " << settings->theSnapShotName cerr << "ERROR: unknown name " << theSettings->theSnapShotName
<< " for snapshot type" << endl; << " for snapshot type" << endl;
return; return;
} }
@ -1243,7 +1132,7 @@ void takeSnapshot()
replace(path.begin(), path.end(), ' ', '_'); replace(path.begin(), path.end(), ' ', '_');
// Check whether we want multiple snapshots created // Check whether we want multiple snapshots created
if(settings->theMultipleSnapShotFlag) if(theSettings->theMultipleSnapShotFlag)
{ {
// Determine if the file already exists, checking each successive filename // Determine if the file already exists, checking each successive filename
// until one doesn't exist // until one doesn't exist
@ -1265,7 +1154,7 @@ void takeSnapshot()
filename = path + ".png"; filename = path + ".png";
// Now save the snapshot file // Now save the snapshot file
snapshot->savePNG(filename, theConsole->mediaSource(), settings->theWindowSize); theSnapshot->savePNG(filename, theConsole->mediaSource(), theSettings->theWindowSize);
if(access(filename.c_str(), F_OK) == 0) if(access(filename.c_str(), F_OK) == 0)
{ {
@ -1312,70 +1201,6 @@ uInt32 maxWindowSizeForScreen()
return 1; return 1;
} }
/**
Display a usage message and exit the program
*/
void usage()
{
static const char* message[] = {
"",
"X Stella version 1.4pre",
"",
"Usage: stella.x11 [option ...] file",
"",
"Valid options are:",
"",
" -fps <number> Display the given number of frames per second",
" -owncmap <0|1> Install a private colormap",
" -zoom <size> Makes window be 'size' times normal (1 - 4)",
// " -fullscreen <0|1> Play the game in fullscreen mode",
" -grabmouse <0|1> Keeps the mouse in the game window",
" -hidecursor <0|1> Hides the mouse cursor in the game window",
" -center <0|1> Centers the game window onscreen",
" -volume <number> Set the volume (0 - 100)",
#ifdef HAVE_JOYSTICK
" -paddle <0|1|2|3|real> Indicates which paddle the mouse should emulate",
" or that real Atari 2600 paddles are being used",
#else
" -paddle <0|1|2|3> Indicates which paddle the mouse should emulate",
#endif
" -showinfo <0|1> Shows some game info",
#ifdef HAVE_PNG
" -ssdir <path> The directory to save snapshot files to",
" -ssname <name> How to name the snapshot (romname or md5sum)",
" -sssingle <0|1> Generate single snapshot instead of many",
#endif
" -pro <props file> Use the given properties file instead of stella.pro",
" -accurate <0|1> Accurate game timing (uses more CPU)",
"",
" -sound <type> Type is one of the following:",
" 0 Disables all sound generation",
#ifdef SOUND_ALSA
" alsa ALSA version 0.9 driver",
#endif
#ifdef SOUND_OSS
" oss Open Sound System driver",
#endif
"",
#ifdef DEVELOPER_SUPPORT
" DEVELOPER options (see Stella manual for details)",
" -Dformat Sets \"Display.Format\"",
" -Dxstart Sets \"Display.XStart\"",
" -Dwidth Sets \"Display.Width\"",
" -Dystart Sets \"Display.YStart\"",
" -Dheight Sets \"Display.Height\"",
" -Dmerge <0|1> Merge changed properties into properties file,",
" or save into a separate file",
#endif
0
};
for(uInt32 i = 0; message[i] != 0; ++i)
{
cout << message[i] << endl;
}
exit(1);
}
/** /**
Setup the properties set by first checking for a user file Setup the properties set by first checking for a user file
@ -1384,7 +1209,7 @@ void usage()
@param set The properties set to setup @param set The properties set to setup
*/ */
bool setupProperties(PropertiesSet& set, Settings& settings) bool setupProperties(PropertiesSet& set)
{ {
bool useMemList = false; bool useMemList = false;
@ -1392,25 +1217,25 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
// If the user wishes to merge any property modifications to the // If the user wishes to merge any property modifications to the
// PropertiesSet file, then the PropertiesSet file MUST be loaded // PropertiesSet file, then the PropertiesSet file MUST be loaded
// into memory. // into memory.
useMemList = settings.theMergePropertiesFlag; useMemList = theSettings->theMergePropertiesFlag;
#endif #endif
// Check to see if the user has specified an alternate .pro file. // Check to see if the user has specified an alternate .pro file.
if(settings.theAlternateProFile != "") if(theSettings->theAlternateProFile != "")
{ {
set.load(settings.theAlternateProFile, &Console::defaultProperties(), useMemList); set.load(theSettings->theAlternateProFile, &Console::defaultProperties(), useMemList);
return true; return true;
} }
if(frontend->userPropertiesFilename() != "") if(theFrontend->userPropertiesFilename() != "")
{ {
set.load(frontend->userPropertiesFilename(), set.load(theFrontend->userPropertiesFilename(),
&Console::defaultProperties(), useMemList); &Console::defaultProperties(), useMemList);
return true; return true;
} }
else if(frontend->systemPropertiesFilename() != "") else if(theFrontend->systemPropertiesFilename() != "")
{ {
set.load(frontend->systemPropertiesFilename(), set.load(theFrontend->systemPropertiesFilename(),
&Console::defaultProperties(), useMemList); &Console::defaultProperties(), useMemList);
return true; return true;
} }
@ -1427,21 +1252,24 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
*/ */
void cleanup() void cleanup()
{ {
if(frontend) if(theSettings)
delete frontend; delete theSettings;
if(theFrontend)
delete theFrontend;
if(theConsole) if(theConsole)
delete theConsole; delete theConsole;
#ifdef HAVE_PNG #ifdef HAVE_PNG
if(snapshot) if(theSnapshot)
delete snapshot; delete theSnapshot;
#endif #endif
if(sound) if(theSound)
{ {
sound->closeDevice(); theSound->closeDevice();
delete sound; delete theSound;
} }
if(normalCursor) if(normalCursor)
@ -1450,7 +1278,7 @@ void cleanup()
XFreeCursor(theDisplay, blankCursor); XFreeCursor(theDisplay, blankCursor);
// If we're using a private colormap then let's free it to be safe // If we're using a private colormap then let's free it to be safe
if(theConsole->settings().theUsePrivateColormapFlag && theDisplay) if(theSettings->theUsePrivateColormapFlag && theDisplay)
{ {
XFreeColormap(theDisplay, thePrivateColormap); XFreeColormap(theDisplay, thePrivateColormap);
} }
@ -1469,10 +1297,10 @@ void cleanup()
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
// First set up the frontend to communicate with the emulation core // First set up the frontend to communicate with the emulation core
//#ifdef UNIX #ifdef UNIX
frontend = new FrontendUNIX(); theFrontend = new FrontendUNIX();
//#endif #endif
if(!frontend) if(!theFrontend)
{ {
cerr << "ERROR: Couldn't set up the frontend.\n"; cerr << "ERROR: Couldn't set up the frontend.\n";
cleanup(); cleanup();
@ -1481,22 +1309,45 @@ int main(int argc, char* argv[])
// Create some settings for the emulator // Create some settings for the emulator
string infile = ""; string infile = "";
string outfile = frontend->userConfigFilename(); string outfile = theFrontend->userConfigFilename();
if(frontend->userConfigFilename() != "") if(theFrontend->userConfigFilename() != "")
infile = frontend->userConfigFilename(); infile = theFrontend->userConfigFilename();
else if(frontend->systemConfigFilename() != "") else if(theFrontend->systemConfigFilename() != "")
infile = frontend->systemConfigFilename(); infile = theFrontend->systemConfigFilename();
Settings settings(infile, outfile); #ifdef UNIX
theSettings = new SettingsUNIX(infile, outfile);
// Handle the command line arguments #endif
if(!settings.handleCommandLineArgs(argc, argv)) if(!theSettings)
{ {
usage();
cleanup(); cleanup();
return 0; return 0;
} }
// Take care of commandline arguments
if(!theSettings->handleCommandLineArgs(argc, argv))
{
string message = "Stella for X11 version 1.4\n\nUsage: stella.x11 [option ...] file";
theSettings->usage(message);
cleanup();
return 0;
}
#ifdef HAVE_PNG
// Take care of the snapshot stuff.
theSnapshot = new Snapshot();
if(theSettings->theSnapShotDir == "")
theSnapShotDir = theFrontend->userHomeDir();
else
theSnapShotDir = theSettings->theSnapShotDir;
if(theSettings->theSnapShotName == "")
theSnapShotName = "romname";
else
theSnapShotName = theSettings->theSnapShotName;
#endif
// Get a pointer to the file which contains the cartridge ROM // Get a pointer to the file which contains the cartridge ROM
const char* file = argv[argc - 1]; const char* file = argv[argc - 1];
@ -1516,7 +1367,7 @@ int main(int argc, char* argv[])
// Create a properties set for us to use and set it up // Create a properties set for us to use and set it up
PropertiesSet propertiesSet; PropertiesSet propertiesSet;
if(!setupProperties(propertiesSet, settings)) if(!setupProperties(propertiesSet))
{ {
delete[] image; delete[] image;
cleanup(); cleanup();
@ -1524,44 +1375,44 @@ int main(int argc, char* argv[])
} }
// Create a sound object for playing audio // Create a sound object for playing audio
if(settings.theSoundDriver == "0") if(theSettings->theSoundDriver == "0")
{ {
// if sound has been disabled, we still need a sound object // if sound has been disabled, we still need a sound object
sound = new Sound(); theSound = new Sound();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Sound disabled.\n"; cout << "Sound disabled.\n";
} }
#ifdef SOUND_ALSA #ifdef SOUND_ALSA
else if(settings.theSoundDriver == "alsa") else if(theSettings->theSoundDriver == "alsa")
{ {
sound = new SoundALSA(); theSound = new SoundALSA();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Using ALSA for sound.\n"; cout << "Using ALSA for sound.\n";
} }
#endif #endif
#ifdef SOUND_OSS #ifdef SOUND_OSS
else if(settings.theSoundDriver == "oss") else if(theSettings->theSoundDriver == "oss")
{ {
sound = new SoundOSS(); theSound = new SoundOSS();
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
cout << "Using OSS for sound.\n"; cout << "Using OSS for sound.\n";
} }
#endif #endif
else // a driver that doesn't exist was requested, so disable sound else // a driver that doesn't exist was requested, so disable sound
{ {
cerr << "ERROR: Sound support for " cerr << "ERROR: Sound support for "
<< settings.theSoundDriver << " not available.\n"; << theSettings->theSoundDriver << " not available.\n";
sound = new Sound(); theSound = new Sound();
} }
sound->setSoundVolume(settings.theDesiredVolume); theSound->setSoundVolume(theSettings->theDesiredVolume);
// Get just the filename of the file containing the ROM image // Get just the filename of the file containing the ROM image
const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1; const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1;
// Create the 2600 game console // Create the 2600 game console
theConsole = new Console(image, size, filename, settings, propertiesSet, theConsole = new Console(image, size, filename, *theSettings, propertiesSet,
*frontend, sound->getSampleRate()); *theFrontend, theSound->getSampleRate());
// Free the image since we don't need it any longer // Free the image since we don't need it any longer
delete[] image; delete[] image;
@ -1584,12 +1435,12 @@ int main(int argc, char* argv[])
// and are needed to calculate the overall frames per second. // and are needed to calculate the overall frames per second.
uInt32 frameTime = 0, numberOfFrames = 0; uInt32 frameTime = 0, numberOfFrames = 0;
if(theConsole->settings().theAccurateTimingFlag) // normal, CPU-intensive timing if(theSettings->theAccurateTimingFlag) // normal, CPU-intensive timing
{ {
// Set up timing stuff // Set up timing stuff
uInt32 startTime, delta; uInt32 startTime, delta;
uInt32 timePerFrame = uInt32 timePerFrame =
(uInt32)(1000000.0 / (double)theConsole->settings().theDesiredFrameRate); (uInt32)(1000000.0 / (double)theSettings->theDesiredFrameRate);
// Set the base for the timers // Set the base for the timers
frameTime = 0; frameTime = 0;
@ -1598,7 +1449,7 @@ int main(int argc, char* argv[])
for(;;) for(;;)
{ {
// Exit if the user wants to quit // Exit if the user wants to quit
if(frontend->quit()) if(theFrontend->quit())
{ {
break; break;
} }
@ -1606,7 +1457,7 @@ int main(int argc, char* argv[])
// Call handleEvents here to see if user pressed pause // Call handleEvents here to see if user pressed pause
startTime = getTicks(); startTime = getTicks();
handleEvents(); handleEvents();
if(frontend->pause()) if(theFrontend->pause())
{ {
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
usleep(10000); usleep(10000);
@ -1614,7 +1465,7 @@ int main(int argc, char* argv[])
} }
theConsole->mediaSource().update(); theConsole->mediaSource().update();
sound->updateSound(theConsole->mediaSource()); theSound->updateSound(theConsole->mediaSource());
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
// Now, waste time if we need to so that we are at the desired frame rate // Now, waste time if we need to so that we are at the desired frame rate
@ -1635,7 +1486,7 @@ int main(int argc, char* argv[])
// Set up timing stuff // Set up timing stuff
uInt32 startTime, virtualTime, currentTime; uInt32 startTime, virtualTime, currentTime;
uInt32 timePerFrame = uInt32 timePerFrame =
(uInt32)(1000000.0 / (double)settings.theDesiredFrameRate); (uInt32)(1000000.0 / (double)theSettings->theDesiredFrameRate);
// Set the base for the timers // Set the base for the timers
virtualTime = getTicks(); virtualTime = getTicks();
@ -1645,17 +1496,17 @@ int main(int argc, char* argv[])
for(;;) for(;;)
{ {
// Exit if the user wants to quit // Exit if the user wants to quit
if(frontend->quit()) if(theFrontend->quit())
{ {
break; break;
} }
startTime = getTicks(); startTime = getTicks();
handleEvents(); handleEvents();
if(!frontend->pause()) if(!theFrontend->pause())
{ {
theConsole->mediaSource().update(); theConsole->mediaSource().update();
sound->updateSound(theConsole->mediaSource()); theSound->updateSound(theConsole->mediaSource());
} }
updateDisplay(theConsole->mediaSource()); updateDisplay(theConsole->mediaSource());
@ -1672,7 +1523,7 @@ int main(int argc, char* argv[])
} }
} }
if(settings.theShowInfoFlag) if(theSettings->theShowInfoFlag)
{ {
double executionTime = (double) frameTime / 1000000.0; double executionTime = (double) frameTime / 1000000.0;
double framesPerSecond = (double) numberOfFrames / executionTime; double framesPerSecond = (double) numberOfFrames / executionTime;