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
## 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
###
SOUND_ALSA = 1
#SOUND_OSS = 1
#SOUND_SDL = 1
SOUND_OSS = 1
SOUND_SDL = 1
### if your C++ compiler doesn't support the bool type
# BSPF_BOOL = 1
@ -49,7 +49,7 @@ SOUND_ALSA = 1
### to include support for saving snapshots in png format
### (requires PNG library)
### Only X11 and SDL ports supported for now
# SNAPSHOT_SUPPORT = 1
SNAPSHOT_SUPPORT = 1
### comment this out if your system doesn't
### have the gettimeofday function
@ -73,7 +73,7 @@ LD = g++
LDFLAGS =
LDLIBS =
OBJS.X11 =
OBJS.X11 =
OPTS.X11 =
LIBS.X11 =
CFLAGS.X11 =
@ -83,7 +83,7 @@ OPTS.SDL =
LIBS.SDL = `sdl-config --libs`
CFLAGS.SDL = `sdl-config --cflags`
OPTS.DOS =
OPTS.DOS = -DDOS=1
SRC = ..
CORE = $(SRC)/emucore
@ -193,65 +193,65 @@ unix-x:
make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \
OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o"
OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o"
OBJS+="$(OBJS.X11)"
linux-x:
make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \
OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o" \
OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o" \
OBJS+="$(OBJS.X11)"
linux-sdl:
make stella.sdl \
INCLUDES="$(INCLUDES) -I$(UI)/sdl -I$(UI)/sound" \
SYS_INCLUDES="" \
OPTIONS="-DBSPF_UNIX=1" \
OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.SDL)" \
LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.SDL)" \
LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.SDL)" \
OBJS="mainSDL.o RectList.o FrontendUNIX.o" \
OBJS="mainSDL.o RectList.o FrontendUNIX.o SettingsUNIX.o" \
OBJS+="$(OBJS.SDL)"
bsdi-x:
make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="-I/usr/X11R6/include" \
OPTIONS="-DBSPF_UNIX=1" \
OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/X11R6/lib" \
LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o"
OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o"
OBJS+="$(OBJS.X11)"
solaris-x:
make stella.x11 \
INCLUDES="$(INCLUDES) -I$(UI)/x11 -I$(UI)/sound" \
SYS_INCLUDES="-I/usr/openwin/include" \
OPTIONS="-DBSPF_UNIX=1" \
OPTIONS="-DBSPF_UNIX=1 -DUNIX=1" \
OPTIONS+="$(OPTS.X11)" \
LDFLAGS="-L/usr/openwin/lib" \
LDFLAGS+="$(CFLAGS.X11)" \
LDLIBS="-lX11 -lXext" \
LDLIBS+="$(LIBS.X11)" \
OBJS="mainX11.o FrontendUNIX.o"
OBJS="mainX11.o FrontendUNIX.o SettingsUNIX.o"
OBJS+="$(OBJS.X11)"
###############################################################################
@ -430,6 +430,9 @@ Deserializer.o: $(CORE)/Deserializer.cxx $(CORE)/Deserializer.hxx
Settings.o: $(CORE)/Settings.cxx $(CORE)/Settings.hxx
$(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
$(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
// 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
@ -27,7 +27,7 @@ class Console;
This class provides an interface for accessing frontend specific data.
@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
{
@ -47,7 +47,7 @@ class Frontend
This method should be called when the emulation core sets
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

View File

@ -13,463 +13,36 @@
// See the file "license" for information on usage and redistribution of
// 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 "Console.hxx"
#include "EventHandler.hxx"
#ifdef DEVELOPER_SUPPORT
#include "Props.hxx"
#endif
#include "bspf.hxx"
#include "Settings.hxx"
Settings::Settings(const string& infile, const string& outfile)
: mySettingsInputFilename(infile),
mySettingsOutputFilename(outfile)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Settings::Settings()
{
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()
{
}
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
if(argc == 1)
return false;
assert(false);
for(Int32 i = 1; i < (argc - 1); ++i)
{
// 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();
return *this;
}

View File

@ -13,92 +13,70 @@
// See the file "license" for information on usage and redistribution of
// 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
#define SETTINGS_HXX
#include "bspf.hxx"
#ifdef DEVELOPER_SUPPORT
#include "Props.hxx"
#endif
#include "bspf.hxx"
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
{
public:
/**
Create a new settings abstract class
*/
Settings();
Settings(const string& infile, const string& outfile);
~Settings();
bool handleCommandLineArgs(int ac, char* av[]);
void save();
void setConsole(Console* console);
/**
Destructor
*/
virtual ~Settings();
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
string theKeymapList;
// The joymap to use
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
// User-modified properties
Properties userDefinedProperties;
@ -109,16 +87,11 @@ class Settings
#endif
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
string mySettingsInputFilename;
// The full pathname of the settings file for output
string mySettingsOutputFilename;
// The global Console object
Console* myConsole;
// Assignment operator isn't supported by this class so make it private
Settings& operator = (const Settings&);
};
#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
// 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>
@ -58,9 +58,10 @@
#include "Snapshot.hxx"
#endif
//#ifdef UNIX
#ifdef UNIX
#include "FrontendUNIX.hxx"
//#endif
#include "SettingsUNIX.hxx"
#endif
// Hack for SDL < 1.2.0
#ifndef SDL_ENABLE
@ -116,20 +117,29 @@ static string theSnapShotDir, theSnapShotName;
#ifdef HAVE_JOYSTICK
static SDL_Joystick* theLeftJoystick = (SDL_Joystick*) NULL;
static SDL_Joystick* theRightJoystick = (SDL_Joystick*) NULL;
static uInt32 theLeftJoystickNumber;
static uInt32 theRightJoystickNumber;
// static uInt32 thePaddleNumber;
#endif
#ifdef HAVE_PNG
static Snapshot* snapshot;
static Snapshot* theSnapshot;
#endif
// Pointer to the console object or the null pointer
static Console* theConsole = (Console*) NULL;
// 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
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
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
the SDL window for us to use. Return false if any operation fails,
@ -269,7 +298,7 @@ StellaEvent::JoyCode joyButtonList[StellaEvent::LastJCODE] = {
*/
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)
return false;
@ -281,8 +310,8 @@ bool setupDisplay()
x11Available = true;
sdlflags = SDL_SWSURFACE;
sdlflags |= theConsole->settings().theUseFullScreenFlag ? SDL_FULLSCREEN : 0;
sdlflags |= theConsole->settings().theUsePrivateColormapFlag ? SDL_HWPALETTE : 0;
sdlflags |= theSettings->theUseFullScreenFlag ? SDL_FULLSCREEN : 0;
sdlflags |= theSettings->theUsePrivateColormapFlag ? SDL_HWPALETTE : 0;
// Get the desired width and height of the display
theWidth = theConsole->mediaSource().width();
@ -291,43 +320,13 @@ bool setupDisplay()
// Get the maximum size of a window for THIS screen
// Must be called after display and screen are known, as well as
// theWidth and theHeight
// Defaults to 3 on systems without X11, maximum of 4 on any system.
theMaxWindowSize = maxWindowSizeForScreen();
// If theWindowSize is not 0, then it must have been set on the commandline
// Now we check to see if it is within bounds
if(theConsole->settings().theWindowSize != 0)
{
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;
// Check to see if window size will fit in the screen
if(theSettings->theWindowSize > theMaxWindowSize)
theWindowSize = theMaxWindowSize;
else
theSnapShotDir = theConsole->settings().theSnapShotDir;
if(theConsole->settings().theSnapShotName == "")
theSnapShotName = "romname";
else
theSnapShotName = theConsole->settings().theSnapShotName;
#endif
theWindowSize = theSettings->theWindowSize;
// Set up the rectangle list to be used in updateDisplay
rectList = new RectList();
@ -348,9 +347,9 @@ bool setupDisplay()
setupPalette();
// Make sure that theUseFullScreenFlag sets up fullscreen mode correctly
theGrabMouseIndicator = theConsole->settings().theGrabMouseFlag;
theHideCursorIndicator = theConsole->settings().theHideCursorFlag;
if(theConsole->settings().theUseFullScreenFlag)
theGrabMouseIndicator = theSettings->theGrabMouseFlag;
theHideCursorIndicator = theSettings->theHideCursorFlag;
if(theSettings->theUseFullScreenFlag)
{
grabMouse(true);
showCursor(false);
@ -366,7 +365,7 @@ bool setupDisplay()
}
// Center the window if centering is selected and not fullscreen
if(theConsole->settings().theCenterWindowFlag && !theConsole->settings().theUseFullScreenFlag)
if(theSettings->theCenterWindowFlag && !theSettings->theUseFullScreenFlag)
centerWindow();
return true;
@ -380,35 +379,38 @@ bool setupDisplay()
bool setupJoystick()
{
#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";
theLeftJoystick = theRightJoystick = 0;
return true;
}
if((theLeftJoystick = SDL_JoystickOpen(0)) != NULL)
if((theLeftJoystick = SDL_JoystickOpen(theSettings->theLeftJoystickNumber)) != NULL)
{
if(theConsole->settings().theShowInfoFlag)
cout << "Left joystick is a " << SDL_JoystickName(0) <<
" with " << SDL_JoystickNumButtons(theLeftJoystick) << " buttons.\n";
if(theSettings->theShowInfoFlag)
cout << "Left joystick is a "
<< SDL_JoystickName(theSettings->theLeftJoystickNumber)
<< " with " << SDL_JoystickNumButtons(theLeftJoystick) << " buttons.\n";
}
else
{
if(theConsole->settings().theShowInfoFlag)
if(theSettings->theShowInfoFlag)
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)
cout << "Right joystick is a " << SDL_JoystickName(1) <<
" with " << SDL_JoystickNumButtons(theRightJoystick) << " buttons.\n";
if(theSettings->theShowInfoFlag)
cout << "Right joystick is a "
<< SDL_JoystickName(theSettings->theRightJoystickNumber)
<< " with " << SDL_JoystickNumButtons(theRightJoystick) << " buttons.\n";
}
else
{
if(theConsole->settings().theShowInfoFlag)
if(theSettings->theShowInfoFlag)
cout << "Right joystick not present, use keyboard instead.\n";
}
#endif
@ -500,7 +502,7 @@ void setupPalette()
// Make the palette be 75% as bright if pause is selected
float shade = 1.0;
if(frontend->pause())
if(theFrontend->pause())
shade = 0.75;
const uInt32* gamePalette = theConsole->mediaSource().palette();
@ -549,7 +551,6 @@ void resizeWindow(int mode)
{
theWidth = theConsole->mediaSource().width();
theHeight = theConsole->mediaSource().height();
theMaxWindowSize = maxWindowSizeForScreen();
}
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
isCentered = false;
if(theConsole->settings().theCenterWindowFlag)
if(theSettings->theCenterWindowFlag)
centerWindow();
}
@ -644,7 +645,7 @@ void toggleFullscreen()
grabMouse(theGrabMouseIndicator);
showCursor(!theHideCursorIndicator);
if(theConsole->settings().theCenterWindowFlag)
if(theSettings->theCenterWindowFlag)
centerWindow();
}
}
@ -941,7 +942,7 @@ void handleEvents()
}
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);
}
@ -1003,13 +1004,13 @@ void handleEvents()
resistance = (Int32)((fudgeFactor * x) / width);
// Now, set the event of the correct paddle to the calculated resistance
if(theConsole->settings().thePaddleMode == 0)
if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroResistance;
else if(theConsole->settings().thePaddleMode == 1)
else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneResistance;
else if(theConsole->settings().thePaddleMode == 2)
else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoResistance;
else if(theConsole->settings().thePaddleMode == 3)
else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeResistance;
theConsole->eventHandler().sendEvent(type, resistance);
@ -1024,13 +1025,13 @@ void handleEvents()
else
value = 0;
if(theConsole->settings().thePaddleMode == 0)
if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroFire;
else if(theConsole->settings().thePaddleMode == 1)
else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneFire;
else if(theConsole->settings().thePaddleMode == 2)
else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoFire;
else if(theConsole->settings().thePaddleMode == 3)
else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeFire;
theConsole->eventHandler().sendEvent(type, value);
@ -1039,7 +1040,7 @@ void handleEvents()
{
if((event.active.state & SDL_APPACTIVE) && (event.active.gain == 0))
{
if(!frontend->pause())
if(!theFrontend->pause())
{
theConsole->eventHandler().sendEvent(Event::Pause, 1);
}
@ -1074,42 +1075,23 @@ void handleEvents()
}
else if(event.type == SDL_JOYAXISMOTION)
{
code = StellaEvent::LastJCODE;
state = 1;
axis = event.jaxis.axis;
value = event.jaxis.value;
if(axis == 0) // x-axis
{
if(value < -16384)
code = StellaEvent::JAXIS_LEFT;
else if(value > 16384)
code = StellaEvent::JAXIS_RIGHT;
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT, 0);
return;
}
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT,
(value < -16384) ? 1 : 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT,
(value > 16384) ? 1 : 0);
}
else if(axis == 1) // y-axis
{
if(value < -16384)
code = StellaEvent::JAXIS_UP;
else if(value > 16384)
code = StellaEvent::JAXIS_DOWN;
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN, 0);
return;
}
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP,
(value < -16384) ? 1 : 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN,
(value > 16384) ? 1 : 0);
}
theConsole->eventHandler().sendJoyEvent(stick, code, state);
}
#endif
}
@ -1131,7 +1113,7 @@ void takeSnapshot()
#ifdef HAVE_PNG
string message;
if(!snapshot)
if(!theSnapshot)
{
message = "Snapshots disabled";
theConsole->mediaSource().showMessage(message, 120);
@ -1157,7 +1139,7 @@ void takeSnapshot()
replace(path.begin(), path.end(), ' ', '_');
// Check whether we want multiple snapshots created
if(theConsole->settings().theMultipleSnapShotFlag)
if(theSettings->theMultipleSnapShotFlag)
{
// Determine if the file already exists, checking each successive filename
// until one doesn't exist
@ -1179,7 +1161,7 @@ void takeSnapshot()
filename = path + ".png";
// 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)
{
@ -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
"$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
*/
bool setupProperties(PropertiesSet& set, Settings& settings)
bool setupProperties(PropertiesSet& set)
{
bool useMemList = false;
@ -1325,25 +1238,25 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
// If the user wishes to merge any property modifications to the
// PropertiesSet file, then the PropertiesSet file MUST be loaded
// into memory.
useMemList = settings.theMergePropertiesFlag;
useMemList = theSettings->theMergePropertiesFlag;
#endif
// 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;
}
if(frontend->userPropertiesFilename() != "")
if(theFrontend->userPropertiesFilename() != "")
{
set.load(frontend->userPropertiesFilename(),
set.load(theFrontend->userPropertiesFilename(),
&Console::defaultProperties(), useMemList);
return true;
}
else if(frontend->systemPropertiesFilename() != "")
else if(theFrontend->systemPropertiesFilename() != "")
{
set.load(frontend->systemPropertiesFilename(),
set.load(theFrontend->systemPropertiesFilename(),
&Console::defaultProperties(), useMemList);
return true;
}
@ -1360,24 +1273,24 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
*/
void cleanup()
{
if(frontend)
delete frontend;
if(theSettings)
delete theSettings;
if(theFrontend)
delete theFrontend;
if(theConsole)
delete theConsole;
#ifdef HAVE_PNG
if(snapshot)
delete snapshot;
if(theSnapshot)
delete theSnapshot;
#endif
if(rectList)
delete rectList;
if(sound)
if(theSound)
{
sound->closeDevice();
delete sound;
theSound->closeDevice();
delete theSound;
}
if(SDL_WasInit(SDL_INIT_EVERYTHING))
@ -1398,10 +1311,10 @@ void cleanup()
int main(int argc, char* argv[])
{
// First set up the frontend to communicate with the emulation core
//#ifdef UNIX
frontend = new FrontendUNIX();
//#endif
if(!frontend)
#ifdef UNIX
theFrontend = new FrontendUNIX();
#endif
if(!theFrontend)
{
cerr << "ERROR: Couldn't set up the frontend.\n";
cleanup();
@ -1410,22 +1323,45 @@ int main(int argc, char* argv[])
// Create some settings for the emulator
string infile = "";
string outfile = frontend->userConfigFilename();
if(frontend->userConfigFilename() != "")
infile = frontend->userConfigFilename();
else if(frontend->systemConfigFilename() != "")
infile = frontend->systemConfigFilename();
string outfile = theFrontend->userConfigFilename();
if(theFrontend->userConfigFilename() != "")
infile = theFrontend->userConfigFilename();
else if(theFrontend->systemConfigFilename() != "")
infile = theFrontend->systemConfigFilename();
Settings settings(infile, outfile);
// Handle the command line arguments
if(!settings.handleCommandLineArgs(argc, argv))
#ifdef UNIX
theSettings = new SettingsUNIX(infile, outfile);
#endif
if(!theSettings)
{
usage();
cleanup();
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
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
PropertiesSet propertiesSet;
if(!setupProperties(propertiesSet, settings))
if(!setupProperties(propertiesSet))
{
delete[] image;
cleanup();
@ -1453,52 +1389,52 @@ int main(int argc, char* argv[])
}
// 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
sound = new Sound();
if(settings.theShowInfoFlag)
theSound = new Sound();
if(theSettings->theShowInfoFlag)
cout << "Sound disabled.\n";
}
#ifdef SOUND_ALSA
else if(settings.theSoundDriver == "alsa")
else if(theSettings->theSoundDriver == "alsa")
{
sound = new SoundALSA();
if(settings.theShowInfoFlag)
theSound = new SoundALSA();
if(theSettings->theShowInfoFlag)
cout << "Using ALSA for sound.\n";
}
#endif
#ifdef SOUND_OSS
else if(settings.theSoundDriver == "oss")
else if(theSettings->theSoundDriver == "oss")
{
sound = new SoundOSS();
if(settings.theShowInfoFlag)
theSound = new SoundOSS();
if(theSettings->theShowInfoFlag)
cout << "Using OSS for sound.\n";
}
#endif
#ifdef SOUND_SDL
else if(settings.theSoundDriver == "sdl")
else if(theSettings->theSoundDriver == "sdl")
{
sound = new SoundSDL();
if(settings.theShowInfoFlag)
theSound = new SoundSDL();
if(theSettings->theShowInfoFlag)
cout << "Using SDL for sound.\n";
}
#endif
else // a driver that doesn't exist was requested, so disable sound
{
cerr << "ERROR: Sound support for "
<< settings.theSoundDriver << " not available.\n";
sound = new Sound();
<< theSettings->theSoundDriver << " not available.\n";
theSound = new Sound();
}
sound->setSoundVolume(settings.theDesiredVolume);
theSound->setSoundVolume(theSettings->theDesiredVolume);
// Get just the filename of the file containing the ROM image
const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1;
// Create the 2600 game console
theConsole = new Console(image, size, filename, settings, propertiesSet,
*frontend, sound->getSampleRate());
theConsole = new Console(image, size, filename, *theSettings, propertiesSet,
*theFrontend, theSound->getSampleRate());
// Free the image since we don't need it any longer
delete[] image;
@ -1521,11 +1457,11 @@ int main(int argc, char* argv[])
// and are needed to calculate the overall frames per second.
uInt32 frameTime = 0, numberOfFrames = 0;
if(settings.theAccurateTimingFlag) // normal, CPU-intensive timing
if(theSettings->theAccurateTimingFlag) // normal, CPU-intensive timing
{
// Set up accurate timing stuff
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
frameTime = 0;
@ -1534,7 +1470,7 @@ int main(int argc, char* argv[])
for(;;)
{
// Exit if the user wants to quit
if(frontend->quit())
if(theFrontend->quit())
{
break;
}
@ -1542,7 +1478,7 @@ int main(int argc, char* argv[])
// Call handleEvents here to see if user pressed pause
startTime = getTicks();
handleEvents();
if(frontend->pause())
if(theFrontend->pause())
{
updateDisplay(theConsole->mediaSource());
SDL_Delay(10);
@ -1551,7 +1487,7 @@ int main(int argc, char* argv[])
theConsole->mediaSource().update();
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
for(;;)
@ -1570,7 +1506,7 @@ int main(int argc, char* argv[])
{
// Set up less accurate timing stuff
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
virtualTime = getTicks();
@ -1580,17 +1516,17 @@ int main(int argc, char* argv[])
for(;;)
{
// Exit if the user wants to quit
if(frontend->quit())
if(theFrontend->quit())
{
break;
}
startTime = getTicks();
handleEvents();
if(!frontend->pause())
if(!theFrontend->pause())
{
theConsole->mediaSource().update();
sound->updateSound(theConsole->mediaSource());
theSound->updateSound(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 framesPerSecond = (double) numberOfFrames / executionTime;
@ -1626,22 +1562,3 @@ int main(int argc, char* argv[])
cleanup();
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
// 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>
@ -22,11 +22,12 @@
#include <string>
#include <algorithm>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef HAVE_GETTIMEOFDAY
#include <time.h>
#include <sys/time.h>
#endif
#include <X11/Xos.h>
#include <X11/Xlib.h>
@ -59,14 +60,16 @@
#endif
#ifdef HAVE_JOYSTICK
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/joystick.h>
#endif
//#ifdef UNIX
#ifdef UNIX
#include "FrontendUNIX.hxx"
//#endif
#include "SettingsUNIX.hxx"
#endif
// function prototypes
// FIXME the following will be placed in a Display class eventually ...
@ -115,23 +118,31 @@ static void changeState(int direction);
static string theSnapShotDir, theSnapShotName;
#ifdef HAVE_PNG
static Snapshot* snapshot;
static Snapshot* theSnapshot;
#endif
#ifdef HAVE_JOYSTICK
// File descriptors for the joystick devices
static int theLeftJoystickFd;
static int theRightJoystickFd;
static uInt32 theLeftJoystickNumber;
static uInt32 theRightJoystickNumber;
// static uInt32 thePaddleNumber;
#endif
// Pointer to the console object or the null pointer
static Console* theConsole = (Console*) NULL;
// 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
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
static bool theGrabMouseIndicator = false;
@ -315,26 +326,11 @@ bool setupDisplay()
// theWidth and theHeight
theMaxWindowSize = maxWindowSizeForScreen();
// FIXME - add this error checking to the Settings class
// If theWindowSize is not 0, then it must have been set on the commandline
// Now we check to see if it is within bounds
if(theConsole->settings().theWindowSize != 0)
{
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;
}
///////////////////////////////
// Check to see if window size will fit in the screen
if(theSettings->theWindowSize > theMaxWindowSize)
theWindowSize = theMaxWindowSize;
else
theWindowSize = theSettings->theWindowSize;
// Figure out the desired size of the window
int width = theWidth * theWindowSize * 2;
@ -373,7 +369,7 @@ bool setupDisplay()
XSetWMProtocols(theDisplay, theWindow, &wm_delete_window, 1);
// If requested install a private colormap for the window
if(theConsole->settings().theUsePrivateColormapFlag)
if(theSettings->theUsePrivateColormapFlag)
{
XSetWindowColormap(theDisplay, theWindow, thePrivateColormap);
}
@ -382,7 +378,7 @@ bool setupDisplay()
XMapWindow(theDisplay, theWindow);
// Center the window if centering is selected and not fullscreen
if(theConsole->settings().theCenterWindowFlag)// && !theUseFullScreenFlag)
if(theSettings->theCenterWindowFlag)// && !theUseFullScreenFlag)
centerWindow();
XEvent event;
@ -397,63 +393,59 @@ bool setupDisplay()
// If we're using the mouse for paddle emulation then enable mouse events
if(((theConsole->properties().get("Controller.Left") == "Paddles") ||
(theConsole->properties().get("Controller.Right") == "Paddles"))
&& (theConsole->settings().thePaddleMode != 4))
&& (theSettings->thePaddleMode != 4))
{
eventMask |= (PointerMotionMask | ButtonPressMask | ButtonReleaseMask);
}
theGrabMouseIndicator = theSettings->theGrabMouseFlag;
theHideCursorIndicator = theSettings->theHideCursorFlag;
// Keep mouse in game window if grabmouse is selected
grabMouse(theGrabMouseIndicator);
// Show or hide the cursor depending on the 'hidecursor' argument
showCursor(!theHideCursorIndicator);
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;
}
/**
This routine should be called once setupDisplay is called
This routine should be called once the display is created
to create the joystick stuff
*/
bool setupJoystick()
{
#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)
cout << "Left joystick found.\n";
if(theSettings->theShowInfoFlag)
cout << "Left joystick set to " << joyname.str() << "." << endl;
}
else
{
if(theConsole->settings().theShowInfoFlag)
if(theSettings->theShowInfoFlag)
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)
cout << "Right joystick found.\n";
if(theSettings->theShowInfoFlag)
cout << "Right joystick set to " << joyname.str() << "." << endl;
}
else
{
if(theConsole->settings().theShowInfoFlag)
if(theSettings->theShowInfoFlag)
cout << "Right joystick not present, use keyboard instead.\n";
}
#endif
@ -467,7 +459,7 @@ bool setupJoystick()
void setupPalette()
{
// 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)
XFreeColormap(theDisplay, thePrivateColormap);
@ -478,7 +470,7 @@ void setupPalette()
// Make the palette be 75% as bright if pause is selected
float shade = 1.0;
if(frontend->pause())
if(theFrontend->pause())
shade = 0.75;
// Allocate colors in the default colormap
@ -492,7 +484,7 @@ void setupPalette()
color.blue = (short unsigned int)(((palette[t] & 0x000000ff) << 8) * shade);
color.flags = DoRed | DoGreen | DoBlue;
if(theConsole->settings().theUsePrivateColormapFlag)
if(theSettings->theUsePrivateColormapFlag)
XAllocColor(theDisplay, thePrivateColormap, &color);
else
XAllocColor(theDisplay, DefaultColormap(theDisplay, theScreen), &color);
@ -759,7 +751,7 @@ void handleEvents()
{
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);
}
@ -793,13 +785,13 @@ void handleEvents()
resistance = (Int32)((1000000.0 * x) / width);
// Now, set the event of the correct paddle to the calculated resistance
if(theConsole->settings().thePaddleMode == 0)
if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroResistance;
else if(theConsole->settings().thePaddleMode == 1)
else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneResistance;
else if(theConsole->settings().thePaddleMode == 2)
else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoResistance;
else if(theConsole->settings().thePaddleMode == 3)
else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeResistance;
theConsole->eventHandler().sendEvent(type, resistance);
@ -811,13 +803,13 @@ void handleEvents()
value = (event.type == ButtonPress) ? 1 : 0;
if(theConsole->settings().thePaddleMode == 0)
if(theSettings->thePaddleMode == 0)
type = Event::PaddleZeroFire;
else if(theConsole->settings().thePaddleMode == 1)
else if(theSettings->thePaddleMode == 1)
type = Event::PaddleOneFire;
else if(theConsole->settings().thePaddleMode == 2)
else if(theSettings->thePaddleMode == 2)
type = Event::PaddleTwoFire;
else if(theConsole->settings().thePaddleMode == 3)
else if(theSettings->thePaddleMode == 3)
type = Event::PaddleThreeFire;
theConsole->eventHandler().sendEvent(type, value);
@ -828,7 +820,7 @@ void handleEvents()
}
else if(event.type == UnmapNotify)
{
if(!frontend->pause())
if(!theFrontend->pause())
{
theConsole->eventHandler().sendEvent(Event::Pause, 1);
}
@ -846,7 +838,7 @@ void handleEvents()
if(theLeftJoystickFd >= 0)
{
struct js_event event;
stick = joyList[0];
stick = joyList[theLeftJoystickNumber];
// Process each joystick event that's queued-up
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)
{
code = StellaEvent::LastJCODE;
state = 1;
axis = event.number;
value = event.value;
if(axis == 0) // x-axis
{
if(value < -16384)
code = StellaEvent::JAXIS_LEFT;
else if(value > 16384)
code = StellaEvent::JAXIS_RIGHT;
else
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT, 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT, 0);
return;
}
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT,
(value < -16384) ? 1 : 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT,
(value > 16384) ? 1 : 0);
}
else if(axis == 1) // y-axis
{
if(value < -16384)
code = StellaEvent::JAXIS_UP;
else if(value > 16384)
code = StellaEvent::JAXIS_DOWN;
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);
}
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP,
(value < -16384) ? 1 : 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN,
(value > 16384) ? 1 : 0);
}
}
}
@ -969,64 +879,43 @@ void handleEvents()
if(theRightJoystickFd >= 0)
{
struct js_event event;
stick = joyList[theRightJoystickNumber];
// Process each joystick event that's queued-up
while(read(theRightJoystickFd, &event, sizeof(struct js_event)) > 0)
{
if((event.type & ~JS_EVENT_INIT) == JS_EVENT_BUTTON)
{
if(event.number == 0)
{
theEvent.set(Event::JoystickOneFire, event.value ?
1 : keyboardEvent.get(Event::JoystickOneFire));
if(event.number >= StellaEvent::LastJCODE)
return;
// If we're using real paddles then set paddle event as well
if(settings->thePaddleMode == 4)
theEvent.set(Event::PaddleTwoFire, event.value);
}
else if(event.number == 1)
{
theEvent.set(Event::BoosterGripOneTrigger, event.value ?
1 : keyboardEvent.get(Event::BoosterGripOneTrigger));
code = joyButtonList[event.number];
state = event.value;
// If we're using real paddles then set paddle event as well
if(settings->thePaddleMode == 4)
theEvent.set(Event::PaddleThreeFire, event.value);
}
theConsole->eventHandler().sendJoyEvent(stick, code, state);
}
else if((event.type & ~JS_EVENT_INIT) == JS_EVENT_AXIS)
{
if(event.number == 0)
{
theEvent.set(Event::JoystickOneLeft, (event.value < -16384) ?
1 : keyboardEvent.get(Event::JoystickOneLeft));
theEvent.set(Event::JoystickOneRight, (event.value > 16384) ?
1 : keyboardEvent.get(Event::JoystickOneRight));
axis = event.number;
value = event.value;
// 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::PaddleTwoResistance, r);
}
if(axis == 0) // x-axis
{
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT,
(value < -16384) ? 1 : 0);
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) ?
1 : keyboardEvent.get(Event::JoystickOneUp));
theEvent.set(Event::JoystickOneDown, (event.value > 16384) ?
1 : keyboardEvent.get(Event::JoystickOneDown));
// 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);
}
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP,
(value < -16384) ? 1 : 0);
theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN,
(value > 16384) ? 1 : 0);
}
}
}
}*/
}
#endif
}
@ -1089,7 +978,7 @@ void resizeWindow(int mode)
// A resize probably means that the window is no longer centered
isCentered = false;
if(theConsole->settings().theCenterWindowFlag)
if(theSettings->theCenterWindowFlag)
centerWindow();
}
@ -1217,7 +1106,7 @@ void takeSnapshot()
#ifdef HAVE_PNG
string message;
if(!snapshot)
if(!theSnapshot)
{
message = "Snapshots disabled";
theConsole->mediaSource().showMessage(message, 120);
@ -1225,16 +1114,16 @@ void takeSnapshot()
}
// Now find the correct name for the snapshot
string path = settings->theSnapShotDir;
string path = theSettings->theSnapShotDir;
string filename;
if(settings->theSnapShotName == "romname")
if(theSettings->theSnapShotName == "romname")
path = path + "/" + theConsole->properties().get("Cartridge.Name");
else if(settings->theSnapShotName == "md5sum")
else if(theSettings->theSnapShotName == "md5sum")
path = path + "/" + theConsole->properties().get("Cartridge.MD5");
else
{
cerr << "ERROR: unknown name " << settings->theSnapShotName
cerr << "ERROR: unknown name " << theSettings->theSnapShotName
<< " for snapshot type" << endl;
return;
}
@ -1243,7 +1132,7 @@ void takeSnapshot()
replace(path.begin(), path.end(), ' ', '_');
// Check whether we want multiple snapshots created
if(settings->theMultipleSnapShotFlag)
if(theSettings->theMultipleSnapShotFlag)
{
// Determine if the file already exists, checking each successive filename
// until one doesn't exist
@ -1265,7 +1154,7 @@ void takeSnapshot()
filename = path + ".png";
// 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)
{
@ -1312,70 +1201,6 @@ uInt32 maxWindowSizeForScreen()
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
@ -1384,7 +1209,7 @@ void usage()
@param set The properties set to setup
*/
bool setupProperties(PropertiesSet& set, Settings& settings)
bool setupProperties(PropertiesSet& set)
{
bool useMemList = false;
@ -1392,25 +1217,25 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
// If the user wishes to merge any property modifications to the
// PropertiesSet file, then the PropertiesSet file MUST be loaded
// into memory.
useMemList = settings.theMergePropertiesFlag;
useMemList = theSettings->theMergePropertiesFlag;
#endif
// 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;
}
if(frontend->userPropertiesFilename() != "")
if(theFrontend->userPropertiesFilename() != "")
{
set.load(frontend->userPropertiesFilename(),
set.load(theFrontend->userPropertiesFilename(),
&Console::defaultProperties(), useMemList);
return true;
}
else if(frontend->systemPropertiesFilename() != "")
else if(theFrontend->systemPropertiesFilename() != "")
{
set.load(frontend->systemPropertiesFilename(),
set.load(theFrontend->systemPropertiesFilename(),
&Console::defaultProperties(), useMemList);
return true;
}
@ -1427,21 +1252,24 @@ bool setupProperties(PropertiesSet& set, Settings& settings)
*/
void cleanup()
{
if(frontend)
delete frontend;
if(theSettings)
delete theSettings;
if(theFrontend)
delete theFrontend;
if(theConsole)
delete theConsole;
#ifdef HAVE_PNG
if(snapshot)
delete snapshot;
if(theSnapshot)
delete theSnapshot;
#endif
if(sound)
if(theSound)
{
sound->closeDevice();
delete sound;
theSound->closeDevice();
delete theSound;
}
if(normalCursor)
@ -1450,7 +1278,7 @@ void cleanup()
XFreeCursor(theDisplay, blankCursor);
// 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);
}
@ -1469,10 +1297,10 @@ void cleanup()
int main(int argc, char* argv[])
{
// First set up the frontend to communicate with the emulation core
//#ifdef UNIX
frontend = new FrontendUNIX();
//#endif
if(!frontend)
#ifdef UNIX
theFrontend = new FrontendUNIX();
#endif
if(!theFrontend)
{
cerr << "ERROR: Couldn't set up the frontend.\n";
cleanup();
@ -1481,22 +1309,45 @@ int main(int argc, char* argv[])
// Create some settings for the emulator
string infile = "";
string outfile = frontend->userConfigFilename();
if(frontend->userConfigFilename() != "")
infile = frontend->userConfigFilename();
else if(frontend->systemConfigFilename() != "")
infile = frontend->systemConfigFilename();
string outfile = theFrontend->userConfigFilename();
if(theFrontend->userConfigFilename() != "")
infile = theFrontend->userConfigFilename();
else if(theFrontend->systemConfigFilename() != "")
infile = theFrontend->systemConfigFilename();
Settings settings(infile, outfile);
// Handle the command line arguments
if(!settings.handleCommandLineArgs(argc, argv))
#ifdef UNIX
theSettings = new SettingsUNIX(infile, outfile);
#endif
if(!theSettings)
{
usage();
cleanup();
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
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
PropertiesSet propertiesSet;
if(!setupProperties(propertiesSet, settings))
if(!setupProperties(propertiesSet))
{
delete[] image;
cleanup();
@ -1524,44 +1375,44 @@ int main(int argc, char* argv[])
}
// 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
sound = new Sound();
if(settings.theShowInfoFlag)
theSound = new Sound();
if(theSettings->theShowInfoFlag)
cout << "Sound disabled.\n";
}
#ifdef SOUND_ALSA
else if(settings.theSoundDriver == "alsa")
else if(theSettings->theSoundDriver == "alsa")
{
sound = new SoundALSA();
if(settings.theShowInfoFlag)
theSound = new SoundALSA();
if(theSettings->theShowInfoFlag)
cout << "Using ALSA for sound.\n";
}
#endif
#ifdef SOUND_OSS
else if(settings.theSoundDriver == "oss")
else if(theSettings->theSoundDriver == "oss")
{
sound = new SoundOSS();
if(settings.theShowInfoFlag)
theSound = new SoundOSS();
if(theSettings->theShowInfoFlag)
cout << "Using OSS for sound.\n";
}
#endif
else // a driver that doesn't exist was requested, so disable sound
{
cerr << "ERROR: Sound support for "
<< settings.theSoundDriver << " not available.\n";
sound = new Sound();
<< theSettings->theSoundDriver << " not available.\n";
theSound = new Sound();
}
sound->setSoundVolume(settings.theDesiredVolume);
theSound->setSoundVolume(theSettings->theDesiredVolume);
// Get just the filename of the file containing the ROM image
const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1;
// Create the 2600 game console
theConsole = new Console(image, size, filename, settings, propertiesSet,
*frontend, sound->getSampleRate());
theConsole = new Console(image, size, filename, *theSettings, propertiesSet,
*theFrontend, theSound->getSampleRate());
// Free the image since we don't need it any longer
delete[] image;
@ -1584,12 +1435,12 @@ int main(int argc, char* argv[])
// and are needed to calculate the overall frames per second.
uInt32 frameTime = 0, numberOfFrames = 0;
if(theConsole->settings().theAccurateTimingFlag) // normal, CPU-intensive timing
if(theSettings->theAccurateTimingFlag) // normal, CPU-intensive timing
{
// Set up timing stuff
uInt32 startTime, delta;
uInt32 timePerFrame =
(uInt32)(1000000.0 / (double)theConsole->settings().theDesiredFrameRate);
(uInt32)(1000000.0 / (double)theSettings->theDesiredFrameRate);
// Set the base for the timers
frameTime = 0;
@ -1598,7 +1449,7 @@ int main(int argc, char* argv[])
for(;;)
{
// Exit if the user wants to quit
if(frontend->quit())
if(theFrontend->quit())
{
break;
}
@ -1606,7 +1457,7 @@ int main(int argc, char* argv[])
// Call handleEvents here to see if user pressed pause
startTime = getTicks();
handleEvents();
if(frontend->pause())
if(theFrontend->pause())
{
updateDisplay(theConsole->mediaSource());
usleep(10000);
@ -1614,7 +1465,7 @@ int main(int argc, char* argv[])
}
theConsole->mediaSource().update();
sound->updateSound(theConsole->mediaSource());
theSound->updateSound(theConsole->mediaSource());
updateDisplay(theConsole->mediaSource());
// 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
uInt32 startTime, virtualTime, currentTime;
uInt32 timePerFrame =
(uInt32)(1000000.0 / (double)settings.theDesiredFrameRate);
(uInt32)(1000000.0 / (double)theSettings->theDesiredFrameRate);
// Set the base for the timers
virtualTime = getTicks();
@ -1645,17 +1496,17 @@ int main(int argc, char* argv[])
for(;;)
{
// Exit if the user wants to quit
if(frontend->quit())
if(theFrontend->quit())
{
break;
}
startTime = getTicks();
handleEvents();
if(!frontend->pause())
if(!theFrontend->pause())
{
theConsole->mediaSource().update();
sound->updateSound(theConsole->mediaSource());
theSound->updateSound(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 framesPerSecond = (double) numberOfFrames / executionTime;