- SDL now uses the new configuration system

This commit is contained in:
gimmedonutnow 2006-08-30 15:27:05 +00:00
parent 24288cd015
commit 091d0b225d
19 changed files with 1594 additions and 945 deletions

View File

@ -10,10 +10,7 @@ Doxygen integration - DONE
* website integration
Linux build - soules
* go through #def variables and figure out which we need and which we don't
- check OpenGL code
* lots of testing and code clean-up
* figure out why its running 640x480 instead of 512x448
* clean-up of input device code
Windows build - zeromus
* verify rerecording

View File

@ -52,7 +52,7 @@ void FCEUI_NetplayText(uint8 *text);
*/
void FCEUD_NetworkClose(void);
int FCEUI_BeginWaveRecord(char *fn);
int FCEUI_BeginWaveRecord(const char *fn);
int FCEUI_EndWaveRecord(void);
void FCEUI_ResetNES(void);
@ -146,7 +146,7 @@ void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
/* Sets the base directory(save states, snapshots, etc. are saved in directories
below this directory. */
void FCEUI_SetBaseDirectory(char *dir);
void FCEUI_SetBaseDirectory(const char *dir);
/* Tells FCE Ultra to copy the palette data pointed to by pal and use it.
Data pointed to by pal needs to be 64*3 bytes in length.

View File

@ -17,7 +17,8 @@ Config::_addOption(char shortArg,
int type)
{
// make sure we have a valid type
if(type != INTEGER && type != STRING) {
if(type != INTEGER && type != STRING &&
type != DOUBLE && type != FUNCTION) {
return -1;
}
@ -25,17 +26,21 @@ Config::_addOption(char shortArg,
if(_shortArgMap.find(shortArg) != _shortArgMap.end() ||
_longArgMap.find(longArg) != _longArgMap.end() ||
(type == INTEGER && _intOptMap.find(name) != _intOptMap.end()) ||
(type == STRING && _strOptMap.find(name) != _strOptMap.end())) {
(type == STRING && _strOptMap.find(name) != _strOptMap.end()) ||
(type == DOUBLE && _dblOptMap.find(name) != _dblOptMap.end())) {
return -1;
}
// add the option
switch(type) {
case(STRING):
_strOptMap[name] = "";
break;
case(INTEGER):
_intOptMap[name] = 0;
break;
case(STRING):
_strOptMap[name] = "";
case(DOUBLE):
_dblOptMap[name] = 0.0;
break;
case(FUNCTION):
_fnOptMap[name] = NULL;
@ -49,6 +54,44 @@ Config::_addOption(char shortArg,
return 0;
}
int
Config::_addOption(const std::string &longArg,
const std::string &name,
int type)
{
// make sure we have a valid type
if(type != STRING && type != INTEGER && type != DOUBLE) {
return -1;
}
// check if the option already exists
if(_longArgMap.find(longArg) != _longArgMap.end() ||
(type == STRING && _strOptMap.find(name) != _strOptMap.end()) ||
(type == INTEGER && _intOptMap.find(name) != _intOptMap.end()) ||
(type == DOUBLE && _dblOptMap.find(name) != _dblOptMap.end())) {
return -1;
}
// add the option
switch(type) {
case(STRING):
_strOptMap[name] = "";
break;
case(INTEGER):
_intOptMap[name] = 0;
break;
case(DOUBLE):
_dblOptMap[name] = 0.0;
break;
default:
break;
}
_longArgMap[longArg] = name;
return 0;
}
/**
* Add a given option and sets its default value. The option is
* specified as a short command line (-f), long command line (--foo),
@ -78,6 +121,36 @@ Config::addOption(char shortArg,
return 0;
}
/**
* Add a given option and sets its default value. The option is
* specified as a short command line (-f), long command line (--foo),
* option name (Foo), its type (integer or string), and its default
* value.
*/
int
Config::addOption(char shortArg,
const std::string &longArg,
const std::string &name,
double defaultValue)
{
int error;
// add the option to the config system
error = _addOption(shortArg, longArg, name, DOUBLE);
if(error) {
return error;
}
// set the option to the default value
error = setOption(name, defaultValue);
if(error) {
return error;
}
return 0;
}
/**
* Add a given option and sets its default value. The option is
* specified as a short command line (-f), long command line (--foo),
@ -111,7 +184,7 @@ int
Config::addOption(char shortArg,
const std::string &longArg,
const std::string &name,
void (*defaultFn)(void))
void (*defaultFn)(const std::string &))
{
int error;
@ -130,6 +203,72 @@ Config::addOption(char shortArg,
return 0;
}
int
Config::addOption(const std::string &longArg,
const std::string &name,
const std::string &defaultValue)
{
int error;
// add the option to the config system
error = _addOption(longArg, name, STRING);
if(error) {
return error;
}
// set the option to the default value
error = setOption(name, defaultValue);
if(error) {
return error;
}
return 0;
}
int
Config::addOption(const std::string &longArg,
const std::string &name,
int defaultValue)
{
int error;
// add the option to the config system
error = _addOption(longArg, name, INTEGER);
if(error) {
return error;
}
// set the option to the default value
error = setOption(name, defaultValue);
if(error) {
return error;
}
return 0;
}
int
Config::addOption(const std::string &longArg,
const std::string &name,
double defaultValue)
{
int error;
// add the option to the config system
error = _addOption(longArg, name, DOUBLE);
if(error) {
return error;
}
// set the option to the default value
error = setOption(name, defaultValue);
if(error) {
return error;
}
return 0;
}
int
Config::addOption(const std::string &name,
const std::string &defaultValue)
@ -156,6 +295,19 @@ Config::addOption(const std::string &name,
return 0;
}
int
Config::addOption(const std::string &name,
double defaultValue)
{
if(_dblOptMap.find(name) != _dblOptMap.end()) {
return -1;
}
// add the option
_dblOptMap[name] = defaultValue;
return 0;
}
/**
* Sets the specified option to the given integer value.
*/
@ -176,6 +328,26 @@ Config::setOption(const std::string &name,
return 0;
}
/**
* Sets the specified option to the given integer value.
*/
int
Config::setOption(const std::string &name,
double value)
{
std::map<std::string, double>::iterator opt_i;
// confirm that the option exists
opt_i = _dblOptMap.find(name);
if(opt_i == _dblOptMap.end()) {
return -1;
}
// set the option
opt_i->second = value;
return 0;
}
/**
* Sets the specified option to the given string value.
*/
@ -201,9 +373,9 @@ Config::setOption(const std::string &name,
*/
int
Config::setOption(const std::string &name,
void (*value)(void))
void (*value)(const std::string &))
{
std::map<std::string, void (*)(void)>::iterator opt_i;
std::map<std::string, void (*)(const std::string &)>::iterator opt_i;
// confirm that the option exists
opt_i = _fnOptMap.find(name);
@ -268,6 +440,23 @@ Config::getOption(const std::string &name,
return 0;
}
int
Config::getOption(const std::string &name,
double *value)
{
std::map<std::string, double>::iterator opt_i;
// confirm that the option exists
opt_i = _dblOptMap.find(name);
if(opt_i == _dblOptMap.end()) {
return -1;
}
// get the option
(*value) = opt_i->second;
return 0;
}
/**
* Parses the command line arguments. Short args are of the form -f
* <opt>, long args are of the form --foo <opt>. Returns < 0 on error,
@ -281,7 +470,8 @@ Config::_parseArgs(int argc,
std::map<std::string, std::string>::iterator long_i, str_i;
std::map<char, std::string>::iterator short_i;
std::map<std::string, int>::iterator int_i;
std::map<std::string, void (*)(void)>::iterator fn_i;
std::map<std::string, double>::iterator dbl_i;
std::map<std::string, void (*)(const std::string &)>::iterator fn_i;
std::string arg, opt, value;
for(int i = 1; i < argc; i++) {
@ -318,13 +508,6 @@ Config::_parseArgs(int argc,
opt = short_i->second;
}
// check if its a function, and if so, call the function
fn_i = _fnOptMap.find(opt);
if(fn_i != _fnOptMap.end()) {
(*(fn_i->second))();
continue;
}
// make sure we've got a value
if(i + 1 >= argc) {
// XXX missing value
@ -335,10 +518,16 @@ Config::_parseArgs(int argc,
// now, find the appropriate option entry, and update it
str_i = _strOptMap.find(opt);
int_i = _intOptMap.find(opt);
dbl_i = _dblOptMap.find(opt);
fn_i = _fnOptMap.find(opt);
if(str_i != _strOptMap.end()) {
str_i->second = argv[i];
} else if(int_i != _intOptMap.end()) {
int_i->second = atol(argv[i]);
} else if(dbl_i != _dblOptMap.end()) {
dbl_i->second = atof(argv[i]);
} else if(fn_i != _fnOptMap.end()) {
(*(fn_i->second))(argv[i]);
} else {
// XXX invalid option? shouldn't happen
return -1;
@ -386,6 +575,7 @@ Config::_load()
unsigned int pos, eqPos;
std::fstream config;
std::map<std::string, int>::iterator int_i;
std::map<std::string, double>::iterator dbl_i;
std::map<std::string, std::string>::iterator str_i;
std::string configFile = _dir + "/fceu.cfg";
std::string line, name, value;
@ -399,7 +589,7 @@ Config::_load()
config.open(configFile.c_str(), std::ios::in | std::ios::out);
if(!config.is_open()) {
// XXX file couldn't be opened?
return -1;
return 0;
}
while(!config.eof()) {
@ -422,11 +612,14 @@ Config::_load()
// check if the option exists, and if so, set it appropriately
str_i = _strOptMap.find(name);
dbl_i = _dblOptMap.find(name);
int_i = _intOptMap.find(name);
if(str_i != _strOptMap.end()) {
str_i->second = value;
} else if(int_i != _intOptMap.end()) {
int_i->second = atol(value.c_str());
} else if(dbl_i != _dblOptMap.end()) {
dbl_i->second = atof(value.c_str());
}
}
@ -449,6 +642,7 @@ Config::save()
int error;
std::fstream config;
std::map<std::string, int>::iterator int_i;
std::map<std::string, double>::iterator dbl_i;
std::map<std::string, std::string>::iterator str_i;
std::string configFile = _dir + "/fceu.cfg";
char buf[1024];
@ -470,6 +664,11 @@ Config::save()
int_i->first.c_str(), int_i->second);
config.write(buf, strlen(buf));
}
for(dbl_i = _dblOptMap.begin(); dbl_i != _dblOptMap.end(); int_i++) {
snprintf(buf, 1024, "%s = %f\n",
dbl_i->first.c_str(), dbl_i->second);
config.write(buf, strlen(buf));
}
for(str_i = _strOptMap.begin(); str_i != _strOptMap.end(); str_i++) {
snprintf(buf, 1024, "%s = %s\n",
str_i->first.c_str(), str_i->second.c_str());

View File

@ -10,20 +10,23 @@ private:
std::map<std::string, std::string> _strOptMap;
std::map<std::string, int> _intOptMap;
std::map<std::string, void (*)(void)> _fnOptMap;
std::map<std::string, double> _dblOptMap;
std::map<std::string, void (*)(const std::string &)> _fnOptMap;
std::map<char, std::string> _shortArgMap;
std::map<std::string, std::string> _longArgMap;
private:
int _addOption(char, const std::string &, const std::string &, int);
int _addOption(const std::string &, const std::string &, int);
int _load(void);
int _parseArgs(int, char **);
public:
const static int STRING = 1;
const static int INTEGER = 2;
const static int FUNCTION = 3;
const static int DOUBLE = 3;
const static int FUNCTION = 4;
public:
Config(std::string d) : _dir(d) { }
@ -33,25 +36,39 @@ public:
* Adds a configuration option. All options must be added before
* parse().
*/
int addOption(char, const std::string &,
const std::string &, int);
int addOption(char, const std::string &,
const std::string &, const std::string &);
int addOption(char, const std::string &,
const std::string &, void (*)(void));
const std::string &, int);
int addOption(char, const std::string &,
const std::string &, double);
int addOption(char, const std::string &,
const std::string &, void (*)(const std::string &));
int addOption(const std::string &,
const std::string &, const std::string &);
int addOption(const std::string &, const std::string &, int);
int addOption(const std::string &, const std::string &, double);
//int addOption(const std::string &,
// const std::string &, void (*)(const std::string &));
int addOption(const std::string &, const std::string &);
int addOption(const std::string &, int);
int addOption(const std::string &, double);
//int addOption(const std::string &, void (*)(const std::string &));
/**
* Sets a configuration option. Can be called at any time.
*/
int setOption(const std::string &, int);
int setOption(const std::string &, const std::string &);
int setOption(const std::string &, void (*)(void));
int setOption(const std::string &, int);
int setOption(const std::string &, double);
int setOption(const std::string &, void (*)(const std::string &));
int getOption(const std::string &, std::string *);
int getOption(const std::string &, const char **);
int getOption(const std::string &, int *);
int getOption(const std::string &, double *);
/**
* Parse the arguments. Also read in the configuration file and

View File

@ -26,218 +26,19 @@
#include <windows.h>
#endif
int frameskip;
char *cpalette;
char *soundrecfn;
int ntsccol, ntschue, ntsctint;
char *DrBaseDirectory;
static int srendlinev[2]={8,0};
static int erendlinev[2]={231,239};
static int soundvol=100;
static long soundq=0;
int _sound=1;
long soundrate=48000;
#ifdef WIN32
long soundbufsize=52;
#else
long soundbufsize=24;
#endif
DSETTINGS Settings;
CFGSTRUCT DriverConfig[]={
#ifdef OPENGL
AC(_stretchx),
AC(_stretchy),
AC(_opengl),
AC(_openglip),
#endif
AC(Settings.special),
AC(Settings.specialfs),
AC(_doublebuf),
AC(_xscale),
AC(_yscale),
AC(_xscalefs),
AC(_yscalefs),
AC(_bpp),
AC(_efx),
AC(_efxfs),
AC(_fullscreen),
AC(_xres),
AC(_yres),
ACS(netplaynick),
AC(netlocalplayers),
AC(tport),
ACS(netpassword),
ACS(netgamekey),
ENDCFGSTRUCT
};
//-fshack x Set the environment variable SDL_VIDEODRIVER to \"x\" when
// entering full screen mode and x is not \"0\".
char *DriverUsage=
"-xres x Set horizontal resolution to x for full screen mode.\n\
-yres x Set vertical resolution to x for full screen mode.\n\
-xscale(fs) x Multiply width by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\
-yscale(fs) x Multiply height by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\
-bpp(fs) x Bits per pixel for SDL surface(and video mode in fs). 8, 16, 32.\n\
-opengl x Enable OpenGL support if x is 1.\n\
-openglip x Enable OpenGL linear interpolation if x is 1.\n\
-doublebuf x \n\
-special(fs) x Specify special scaling filter.\n\
-stretch(x/y) x Stretch to fill surface on x or y axis(fullscreen, only with OpenGL).\n\
-efx(fs) x Enable special effects. Logically OR the following together:\n\
1 = scanlines(for yscale>=2).\n\
2 = TV blur(for bpp of 16 or 32).\n\
-fs x Select full screen mode if x is non zero.\n\
-connect s Connect to server 's' for TCP/IP network play.\n\
-netnick s Set the nickname to use in network play.\n\
-netgamekey s Use key 's' to create a unique session for the game loaded.\n\
-netpassword s Password to use for connecting to the server.\n\
-netlocalplayers x Set the number of local players.\n\
-netport x Use TCP/IP port x for network play.";
ARGPSTRUCT DriverArgs[]={
#ifdef OPENGL
{"-opengl",0,&_opengl,0},
{"-openglip",0,&_openglip,0},
{"-stretchx",0,&_stretchx,0},
{"-stretchy",0,&_stretchy,0},
#endif
{"-special",0,&Settings.special,0},
{"-specialfs",0,&Settings.specialfs,0},
{"-doublebuf",0,&_doublebuf,0},
{"-bpp",0,&_bpp,0},
{"-xscale",0,&_xscale,2},
{"-yscale",0,&_yscale,2},
{"-efx",0,&_efx,0},
{"-xscalefs",0,&_xscalefs,2},
{"-yscalefs",0,&_yscalefs,2},
{"-efxfs",0,&_efxfs,0},
{"-xres",0,&_xres,0},
{"-yres",0,&_yres,0},
{"-fs",0,&_fullscreen,0},
//{"-fshack",0,&_fshack,0x4001},
{"-connect",0,&netplayhost,0x4001},
{"-netport",0,&tport,0},
{"-netlocalplayers",0,&netlocalplayers,0},
{"-netnick",0,&netplaynick,0x4001},
{"-netpassword",0,&netpassword,0x4001},
{0,0,0,0}
};
#include "usage.h"
void
SetDefaults(void)
{
Settings.special=Settings.specialfs=0;
_bpp=8;
_xres=640;
_yres=480;
_fullscreen=0;
_xscale=2;
_yscale=2;
_xscalefs=_yscalefs=2;
_efx=_efxfs=0;
//_fshack=_fshacksave=0;
#ifdef OPENGL
_opengl=1;
_stretchx=1;
_stretchy=0;
_openglip=1;
#endif
}
/**
* Unimplemented.
*/
void DoDriverArgs(void)
{
}
/**
* Handles arguments passed to FCEU. Hopefully obsolete with new
* configuration system.
*/
static void
DoArgs(int argc,
char *argv[])
{
int x;
static ARGPSTRUCT FCEUArgs[]={
{"-soundbufsize",0,&soundbufsize,0},
{"-soundrate",0,&soundrate,0},
{"-soundq",0,&soundq,0},
#ifdef FRAMESKIP
{"-frameskip",0,&frameskip,0},
#endif
{"-sound",0,&_sound,0},
{"-soundvol",0,&soundvol,0},
{"-cpalette",0,&cpalette,0x4001},
{"-soundrecord",0,&soundrecfn,0x4001},
{"-ntsccol",0,&ntsccol,0},
{"-pal",0,&eoptions,0x8000|EO_PAL},
{"-lowpass",0,&eoptions,0x8000|EO_LOWPASS},
{"-gg",0,&eoptions,0x8000|EO_GAMEGENIE},
{"-no8lim",0,&eoptions,0x8001},
{"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
{"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
{"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
{"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
{"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
{"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
{0,(int *)InputArgs,0,0},
{0,(int *)DriverArgs,0,0},
{0,0,0,0}
};
ParseArguments(argc, argv, FCEUArgs);
if(cpalette) {
if(cpalette[0] == '0') {
if(cpalette[1] == 0) {
free(cpalette);
cpalette=0;
}
}
}
FCEUI_SetVidSystem((eoptions&EO_PAL)?1:0);
FCEUI_SetGameGenie((eoptions&EO_GAMEGENIE)?1:0);
FCEUI_SetLowPass((eoptions&EO_LOWPASS)?1:0);
FCEUI_DisableSpriteLimitation(eoptions&1);
FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
for(x = 0; x < 2; x++) {
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
}
FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
DoDriverArgs();
}
//#include "usage.h"
/**
* Read a custom pallete from a file and load it into the core.
*/
static void
LoadCPalette()
LoadCPalette(const std::string &file)
{
uint8 tmpp[192];
FILE *fp;
if(!(fp = FCEUD_UTF8fopen(cpalette, "rb"))) {
printf(" Error loading custom palette from file: %s\n", cpalette);
if(!(fp = FCEUD_UTF8fopen(file.c_str(), "rb"))) {
printf(" Error loading custom palette from file: %s\n", file.c_str());
return;
}
fread(tmpp, 1, 192, fp);
@ -245,76 +46,28 @@ LoadCPalette()
fclose(fp);
}
static CFGSTRUCT fceuconfig[]= {
AC(soundrate),
AC(soundq),
AC(_sound),
AC(soundvol),
AC(soundbufsize),
ACS(cpalette),
AC(ntsctint),
AC(ntschue),
AC(ntsccol),
AC(eoptions),
ACA(srendlinev),
ACA(erendlinev),
ADDCFGSTRUCT(InputConfig),
ADDCFGSTRUCT(DriverConfig),
ENDCFGSTRUCT
};
/**
* Wrapper for SaveFCEUConfig() that sets the path. Hopefully
* obsolete with new configuration system.
*/
void
SaveConfig()
{
char tdir[2048];
sprintf(tdir,"%s"PSS"fceu98.cfg", DrBaseDirectory);
FCEUI_GetNTSCTH(&ntsctint, &ntschue);
SaveFCEUConfig(tdir, fceuconfig);
}
/**
* Wrapper for LoadFCEUConfig() that sets the path. Hopefully
* obsolete with the new configuration system.
*/
static void
LoadConfig()
{
char tdir[2048];
sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
/* Get default settings for if no config file exists. */
FCEUI_GetNTSCTH(&ntsctint, &ntschue);
LoadFCEUConfig(tdir,fceuconfig);
InputUserActiveFix();
}
/**
* Creates the subdirectories used for saving snapshots, movies, game
* saves, etc. Hopefully obsolete with new configuration system.
*/
static void
CreateDirs(void)
CreateDirs(const std::string &dir)
{
char *subs[7]={"fcs","fcm","snaps","gameinfo","sav","cheats","movie"};
char tdir[2048];
std::string subdir;
int x;
#ifdef WIN32
mkdir((char *)DrBaseDirectory);
mkdir(dir.c_str());
for(x = 0; x < 6; x++) {
sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
mkdir(tdir);
subdir = dir + PSS + subs[x];
mkdir(subdir.c_str());
}
#else
mkdir((char *)DrBaseDirectory,S_IRWXU);
mkdir(dir.c_str(), S_IRWXU);
for(x = 0; x < 6; x++) {
sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
mkdir(tdir,S_IRWXU);
subdir = dir + PSS + subs[x];
mkdir(subdir.c_str(), S_IRWXU);
}
#endif
}
@ -324,58 +77,242 @@ CreateDirs(void)
* hopefully become obsolete once the new configuration system is in
* place.
*/
static uint8 *
GetBaseDirectory()
static void
GetBaseDirectory(std::string &dir)
{
uint8 *ol;
uint8 *ret;
char *home, *lastBS;
ol=(uint8 *)getenv("HOME");
if(ol) {
ret=(uint8 *)malloc(strlen((char *)ol)+1+strlen("./fceultra"));
strcpy((char *)ret,(char *)ol);
strcat((char *)ret,"/.fceultra");
home = getenv("HOME");
if(home) {
dir = std::string(home) + "/.fceultra";
} else {
#ifdef WIN32
char *sa;
home = new char[MAX_PATH + 1];
GetModuleFileName(NULL, home, MAX_PATH + 1);
ret=(uint8*)malloc(MAX_PATH+1);
GetModuleFileName(NULL,(char*)ret,MAX_PATH+1);
lastBS = strrchr(home,'\\');
if(lastBS) {
*lastBS = 0;
}
sa=strrchr((char*)ret,'\\');
if(sa)
*sa = 0;
dir = std::string(home);
delete[] home;
#else
ret=(uint8 *)malloc(sizeof(uint8));
ret[0]=0;
dir = "";
#endif
printf("%s\n",ret);
}
return(ret);
}
int
InitConfig(int argc,
char **argv)
Config *
InitConfig()
{
DrBaseDirectory = (char *)GetBaseDirectory();
FCEUI_SetBaseDirectory(DrBaseDirectory);
std::string dir, prefix;
Config *config;
CreateDirs();
GetBaseDirectory(dir);
if(argc<=1) {
ShowUsage(argv[0]);
return -1;
}
LoadConfig();
DoArgs(argc - 2, &argv[1]);
FCEUI_SetBaseDirectory(dir.c_str());
CreateDirs(dir);
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
if(cpalette) {
LoadCPalette();
config = new Config(dir);
// sound options
config->addOption('s', "sound", "SDL.Sound", 1);
config->addOption("volume", "SDL.SoundVolume", 100);
config->addOption("SDL.SoundRate", 48000);
config->addOption("SDL.SoundQuality", 0);
config->addOption("soundrecord", "SDL.SoundRecordFile", "");
#ifdef WIN32
config->addOption("SDL.SoundBufSize", 52);
#else
config->addOption("SDL.SoundBufSize", 24);
#endif
// old EOptions
config->addOption('g', "gamegenie", "SDL.GameGenie", 0);
config->addOption("lowpass", "SDL.LowPass", 0);
config->addOption("pal", "SDL.PAL", 0);
config->addOption("frameskip", "SDL.Frameskip", 0);
config->addOption("SDL.SnapName", 0);
config->addOption("SDL.ClipSides", 0);
config->addOption("SDL.NoThrottle", 0);
config->addOption("SDL.DisableSpriteLimit", 0);
// color control
config->addOption('p', "palette", "SDL.Palette", "");
config->addOption("tint", "SDL.Tint", 56);
config->addOption("hue", "SDL.Hue", 72);
config->addOption("color", "SDL.Color", 0);
// scanline settings
config->addOption("SDL.ScanLineStart", 0);
config->addOption("SDL.ScanLineEnd", 239);
// video controls
config->addOption('x', "xres", "SDL.XResolution", 512);
config->addOption('y', "yres", "SDL.YResolution", 448);
config->addOption('f', "fullscreen", "SDL.Fullscreen", 0);
config->addOption('b', "bpp", "SDL.BitsPerPixel", 32);
config->addOption("doublebuf", "SDL.DoubleBuffering", 0);
config->addOption("xscale", "SDL.XScale", 1.0);
config->addOption("yscale", "SDL.YScale", 1.0);
config->addOption("xstretch", "SDL.XStretch", 0);
config->addOption("ystretch", "SDL.YStretch", 0);
// OpenGL options
config->addOption("opengl", "SDL.OpenGL", 0);
config->addOption("SDL.OpenGLip", 0);
config->addOption("SDL.SpecialFilter", 0);
config->addOption("SDL.SpecialFX", 0);
// network play options
config->addOption('n', "net", "SDL.NetworkServer", "");
config->addOption('u', "user", "SDL.NetworkUsername", "");
config->addOption('w', "pass", "SDL.NetworkPassword", "");
config->addOption('k', "netkey", "SDL.NetworkGameKey", "");
config->addOption('p', "port", "SDL.NetworkPort", 0xFCE);
config->addOption('l', "players", "SDL.NetworkNumPlayers", 1);
// input configuration options
config->addOption("SDL.Input.0", "GamePad.0");
config->addOption("SDL.Input.1", "GamePad.1");
config->addOption("SDL.Input.2", "None");
// Allow for input configuration
config->addOption('i', "inputcfg", "SDL.InputCfg", InputCfg);
// GamePad 0 - 3
for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) {
char buf[64];
snprintf(buf, 20, "SDL.Input.GamePad.%d.", i);
prefix = buf;
config->addOption(prefix + "DeviceType", DefaultGamePadDevice[i]);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) {
config->addOption(prefix + GamePadNames[j], DefaultGamePad[i][j]);
}
}
return 0;
// PowerPad 0 - 1
for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) {
char buf[64];
snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i);
prefix = buf;
config->addOption(prefix + "DeviceType", DefaultPowerPadDevice[i]);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) {
config->addOption(prefix +PowerPadNames[j], DefaultPowerPad[i][j]);
}
}
// QuizKing
prefix = "SDL.Input.QuizKing.";
config->addOption(prefix + "DeviceType", DefaultQuizKingDevice);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) {
config->addOption(prefix + QuizKingNames[j], DefaultQuizKing[j]);
}
// HyperShot
prefix = "SDL.Input.HyperShot.";
config->addOption(prefix + "DeviceType", DefaultHyperShotDevice);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) {
config->addOption(prefix + HyperShotNames[j], DefaultHyperShot[j]);
}
// Mahjong
prefix = "SDL.Input.Mahjong.";
config->addOption(prefix + "DeviceType", DefaultMahjongDevice);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) {
config->addOption(prefix + MahjongNames[j], DefaultMahjong[j]);
}
// TopRider
prefix = "SDL.Input.TopRider.";
config->addOption(prefix + "DeviceType", DefaultTopRiderDevice);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) {
config->addOption(prefix + TopRiderNames[j], DefaultTopRider[j]);
}
// FTrainer
prefix = "SDL.Input.FTrainer.";
config->addOption(prefix + "DeviceType", DefaultFTrainerDevice);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) {
config->addOption(prefix + FTrainerNames[j], DefaultFTrainer[j]);
}
// FamilyKeyBoard
prefix = "SDL.Input.FamilyKeyBoard.";
config->addOption(prefix + "DeviceType", DefaultFamilyKeyBoardDevice);
config->addOption(prefix + "DeviceNum", 0);
for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) {
config->addOption(prefix + FamilyKeyBoardNames[j],
DefaultFamilyKeyBoard[j]);
}
// All mouse devices
config->addOption("SDL.OekaKids.0.DeviceType", "Mouse");
config->addOption("SDL.OekaKids.0.DeviceNum", 0);
config->addOption("SDL.Arkanoid.0.DeviceType", "Mouse");
config->addOption("SDL.Arkanoid.0.DeviceNum", 0);
config->addOption("SDL.Shadow.0.DeviceType", "Mouse");
config->addOption("SDL.Shadow.0.DeviceNum", 0);
config->addOption("SDL.Zapper.0.DeviceType", "Mouse");
config->addOption("SDL.Zapper.0.DeviceNum", 0);
return config;
}
void
UpdateEMUCore(Config *config)
{
int ntsccol, ntsctint, ntschue, flag, start, end;
std::string cpalette;
config->getOption("SDL.Color", &ntsccol);
config->getOption("SDL.Tint", &ntsctint);
config->getOption("SDL.Hue", &ntschue);
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
config->getOption("SDL.Palette", &cpalette);
if(cpalette.size()) {
LoadCPalette(cpalette);
}
config->getOption("SDL.PAL", &flag);
FCEUI_SetVidSystem(flag ? 1 : 0);
config->getOption("SDL.GameGenie", &flag);
FCEUI_SetGameGenie(flag ? 1 : 0);
config->getOption("SDL.LowPass", &flag);
FCEUI_SetLowPass(flag ? 1 : 0);
config->getOption("SDL.DisableSpriteLimit", &flag);
FCEUI_DisableSpriteLimitation(flag ? 1 : 0);
config->getOption("SDL.DisableSpriteLimit", &flag);
FCEUI_SetSnapName(flag ? 1 : 0);
config->getOption("SDL.ScanLineStart", &start);
config->getOption("SDL.ScanLineEnd", &end);
#if DOING_SCANLINE_CHECKS
for(int i = 0; i < 2; x++) {
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
}
#endif
FCEUI_SetRenderedLines(start + 8, end - 8, start, end);
}

View File

@ -1,9 +1,4 @@
extern int frameskip;
extern char *cpalette;
extern char *soundrecfn;
extern int ntsccol, ntschue, ntsctint;
extern char *DrBaseDirectory;
#include "../common/configSys.h"
int InitConfig(int, char **);
void SaveConfig(void);
void SetDefaults(void);
Config *InitConfig(void);
void UpdateEMUCore(Config *);

View File

@ -29,15 +29,15 @@
#include "../common/cheat.h"
#include "../../fceu.h"
/** GLOBALS **/
int NoWaiting=1;
/* UsrInputType[] is user-specified. InputType[] is current
(game loading can override user settings)
*/
static int UsrInputType[3] = {SI_GAMEPAD, SI_GAMEPAD, SIFC_NONE};
static int InputType[3] = {0, 0, 0};
static int UsrInputType[NUM_INPUT_DEVICES];
static int InputType[NUM_INPUT_DEVICES];
static int cspec = 0;
extern int gametype;
@ -990,41 +990,106 @@ ConfigButton(char *text,
/**
* Update the button configuration for a specified device.
*/
extern Config *g_config;
void
ConfigDevice(int which,
int arg)
{
uint8 buf[256];
char buf[256];
int x;
std::string prefix;
char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"};
// XXX soules - set the configuration options so that later calls
// don't override these. This is a temp hack until I
// can clean up this file.
ButtonConfigBegin();
switch(which) {
case FCFGD_QUIZKING:
prefix = "SDL.Input.QuizKing.";
for(x = 0; x < 6; x++) {
sprintf((char *)buf, "Quiz King Buzzer #%d", x+1);
ConfigButton((char *)buf, &QuizKingButtons[x]);
sprintf(buf, "Quiz King Buzzer #%d", x+1);
ConfigButton(buf, &QuizKingButtons[x]);
g_config->setOption(prefix + QuizKingNames[x],
QuizKingButtons[x].ButtonNum[0]);
}
if(QuizKingButtons[0].ButtType[0] == BUTTC_KEYBOARD) {
g_config->setOption(prefix + "DeviceType", "Keyboard");
} else if(QuizKingButtons[0].ButtType[0] == BUTTC_JOYSTICK) {
g_config->setOption(prefix + "DeviceType", "Joystick");
} else {
g_config->setOption(prefix + "DeviceType", "Unknown");
}
g_config->setOption(prefix + "DeviceNum",
QuizKingButtons[0].DeviceNum[0]);
break;
case FCFGD_HYPERSHOT:
prefix = "SDL.Input.HyperShot.";
for(x = 0; x < 4; x++) {
sprintf((char *)buf, "Hyper Shot %d: %s",
sprintf(buf, "Hyper Shot %d: %s",
((x & 2) >> 1) + 1, (x & 1) ? "JUMP" : "RUN");
ConfigButton((char *)buf, &HyperShotButtons[x]);
ConfigButton(buf, &HyperShotButtons[x]);
g_config->setOption(prefix + HyperShotNames[x],
HyperShotButtons[x].ButtonNum[0]);
}
if(HyperShotButtons[0].ButtType[0] == BUTTC_KEYBOARD) {
g_config->setOption(prefix + "DeviceType", "Keyboard");
} else if(HyperShotButtons[0].ButtType[0] == BUTTC_JOYSTICK) {
g_config->setOption(prefix + "DeviceType", "Joystick");
} else {
g_config->setOption(prefix + "DeviceType", "Unknown");
}
g_config->setOption(prefix + "DeviceNum",
HyperShotButtons[0].DeviceNum[0]);
break;
case FCFGD_POWERPAD:
snprintf(buf, 256, "SDL.Input.PowerPad.%d", (arg & 1));
prefix = buf;
for(x = 0; x < 12; x++) {
sprintf((char *)buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11);
ConfigButton((char *)buf, &powerpadsc[arg&1][x]);
sprintf(buf, "PowerPad %d: %d", (arg & 1) + 1, x + 11);
ConfigButton(buf, &powerpadsc[arg&1][x]);
g_config->setOption(prefix + PowerPadNames[x],
powerpadsc[arg & 1][x].ButtonNum[0]);
}
if(powerpadsc[arg & 1][0].ButtType[0] == BUTTC_KEYBOARD) {
g_config->setOption(prefix + "DeviceType", "Keyboard");
} else if(powerpadsc[arg & 1][0].ButtType[0] == BUTTC_JOYSTICK) {
g_config->setOption(prefix + "DeviceType", "Joystick");
} else {
g_config->setOption(prefix + "DeviceType", "Unknown");
}
g_config->setOption(prefix + "DeviceNum",
powerpadsc[arg & 1][0].DeviceNum[0]);
break;
case FCFGD_GAMEPAD:
snprintf(buf, 256, "SDL.Input.GamePad.%d", arg);
prefix = buf;
for(x = 0; x < 10; x++) {
sprintf((char *)buf, "GamePad #%d: %s", arg + 1, str[x]);
ConfigButton((char *)buf, &GamePadConfig[arg][x]);
sprintf(buf, "GamePad #%d: %s", arg + 1, str[x]);
ConfigButton(buf, &GamePadConfig[arg][x]);
g_config->setOption(prefix + GamePadNames[x],
GamePadConfig[arg][x].ButtonNum[0]);
}
if(GamePadConfig[arg][0].ButtType[0] == BUTTC_KEYBOARD) {
g_config->setOption(prefix + "DeviceType", "Keyboard");
} else if(GamePadConfig[arg][0].ButtType[0] == BUTTC_JOYSTICK) {
g_config->setOption(prefix + "DeviceType", "Joystick");
} else {
g_config->setOption(prefix + "DeviceType", "Unknown");
}
g_config->setOption(prefix + "DeviceNum",
GamePadConfig[arg][0].DeviceNum[0]);
break;
}
@ -1035,16 +1100,16 @@ ConfigDevice(int which,
/**
* Update the button configuration for a device, specified by a text string.
*/
static void
InputCfg(char *text)
void
InputCfg(const std::string &text)
{
if(!strncasecmp(text, "gamepad", strlen("gamepad"))) {
if(text.find("gamepad") != std::string::npos) {
ConfigDevice(FCFGD_GAMEPAD, (text[strlen("gamepad")] - '1') & 3);
} else if(!strncasecmp(text, "powerpad", strlen("powerpad"))) {
} else if(text.find("powerpad") != std::string::npos) {
ConfigDevice(FCFGD_POWERPAD, (text[strlen("powerpad")] - '1') & 1);
} else if(!strcasecmp(text,"hypershot")) {
} else if(text.find("hypershot") != std::string::npos) {
ConfigDevice(FCFGD_HYPERSHOT, 0);
} else if(!strcasecmp(text,"quizking")) {
} else if(text.find("quizking") != std::string::npos) {
ConfigDevice(FCFGD_QUIZKING, 0);
}
}
@ -1108,7 +1173,7 @@ Input2(char *text)
}
/** GLOBALS **/
#if 0
CFGSTRUCT InputConfig[]={
ACA(UsrInputType),
AC(powerpadsc),
@ -1128,4 +1193,238 @@ ARGPSTRUCT InputArgs[]={
{"-input2",0,(void *)Input2,0x2000},
{0,0,0,0}
};
#endif
/**
* Hack to map the new configuration onto the existing button
* configuration management. Will probably want to change this in the
* future - soules.
*/
void
UpdateInput(Config *config)
{
char buf[64];
std::string device, prefix;
for(unsigned int i = 0; i < 3; i++) {
snprintf(buf, 64, "SDL.Input.%d", i);
config->getOption(buf, &device);
if(device == "None") {
UsrInputType[i] = SI_NONE;
} else if(device.find("GamePad") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_GAMEPAD : SI_NONE;
} else if(device.find("PowerPad.0") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_POWERPADA : SI_NONE;
} else if(device.find("PowerPad.1") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_POWERPADB : SI_NONE;
} else if(device.find("QuizKing") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_QUIZKING;
} else if(device.find("HyperShot") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_HYPERSHOT;
} else if(device.find("Mahjong") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_MAHJONG;
} else if(device.find("TopRider") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_TOPRIDER;
} else if(device.find("FTrainer") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_FTRAINERA;
} else if(device.find("FamilyKeyBoard") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_FKB;
} else if(device.find("OekaKids") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_OEKAKIDS;
} else if(device.find("Arkanoid") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_ARKANOID : SIFC_ARKANOID;
} else if(device.find("Shadow") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_SHADOW;
} else if(device.find("Zapper") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_ZAPPER : SIFC_NONE;
} else if(device.find("BWorld") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_BWORLD;
} else if(device.find("4Player") != std::string::npos) {
UsrInputType[i] = (i < 2) ? SI_NONE : SIFC_4PLAYER;
} else {
// Unknown device
UsrInputType[i] = SI_NONE;
}
}
// update each of the devices' configuration structure
// XXX soules - this is temporary until this file is cleaned up to
// simplify the interface between configuration and
// structure data. This will likely include the
// removal of multiple input buttons for a single
// input device key.
int type, devnum, button;
// gamepad 0 - 3
for(unsigned int i = 0; i < GAMEPAD_NUM_DEVICES; i++) {
char buf[64];
snprintf(buf, 20, "SDL.Input.GamePad.%d.", i);
prefix = buf;
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < GAMEPAD_NUM_BUTTONS; j++) {
config->getOption(prefix + GamePadNames[j], &button);
GamePadConfig[i][j].ButtType[0] = type;
GamePadConfig[i][j].DeviceNum[0] = devnum;
GamePadConfig[i][j].ButtonNum[0] = button;
GamePadConfig[i][j].NumC = 1;
}
}
// PowerPad 0 - 1
for(unsigned int i = 0; i < POWERPAD_NUM_DEVICES; i++) {
char buf[64];
snprintf(buf, 20, "SDL.Input.PowerPad.%d.", i);
prefix = buf;
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < POWERPAD_NUM_BUTTONS; j++) {
config->getOption(prefix + PowerPadNames[j], &button);
powerpadsc[i][j].ButtType[0] = type;
powerpadsc[i][j].DeviceNum[0] = devnum;
powerpadsc[i][j].ButtonNum[0] = button;
powerpadsc[i][j].NumC = 1;
}
}
// QuizKing
prefix = "SDL.Input.QuizKing.";
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < QUIZKING_NUM_BUTTONS; j++) {
config->getOption(prefix + QuizKingNames[j], &button);
QuizKingButtons[j].ButtType[0] = type;
QuizKingButtons[j].DeviceNum[0] = devnum;
QuizKingButtons[j].ButtonNum[0] = button;
QuizKingButtons[j].NumC = 1;
}
// HyperShot
prefix = "SDL.Input.HyperShot.";
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < HYPERSHOT_NUM_BUTTONS; j++) {
config->getOption(prefix + HyperShotNames[j], &button);
HyperShotButtons[j].ButtType[0] = type;
HyperShotButtons[j].DeviceNum[0] = devnum;
HyperShotButtons[j].ButtonNum[0] = button;
HyperShotButtons[j].NumC = 1;
}
// Mahjong
prefix = "SDL.Input.Mahjong.";
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < MAHJONG_NUM_BUTTONS; j++) {
config->getOption(prefix + MahjongNames[j], &button);
MahjongButtons[j].ButtType[0] = type;
MahjongButtons[j].DeviceNum[0] = devnum;
MahjongButtons[j].ButtonNum[0] = button;
MahjongButtons[j].NumC = 1;
}
// TopRider
prefix = "SDL.Input.TopRider.";
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < TOPRIDER_NUM_BUTTONS; j++) {
config->getOption(prefix + TopRiderNames[j], &button);
TopRiderButtons[j].ButtType[0] = type;
TopRiderButtons[j].DeviceNum[0] = devnum;
TopRiderButtons[j].ButtonNum[0] = button;
TopRiderButtons[j].NumC = 1;
}
// FTrainer
prefix = "SDL.Input.FTrainer.";
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < FTRAINER_NUM_BUTTONS; j++) {
config->getOption(prefix + FTrainerNames[j], &button);
FTrainerButtons[j].ButtType[0] = type;
FTrainerButtons[j].DeviceNum[0] = devnum;
FTrainerButtons[j].ButtonNum[0] = button;
FTrainerButtons[j].NumC = 1;
}
// FamilyKeyBoard
prefix = "SDL.Input.FamilyKeyBoard.";
config->getOption(prefix + "DeviceType", &device);
if(device.find("Keyboard") != std::string::npos) {
type = BUTTC_KEYBOARD;
} else if(device.find("Joystick") != std::string::npos) {
type = BUTTC_JOYSTICK;
} else {
type = 0;
}
config->getOption(prefix + "DeviceNum", &devnum);
for(unsigned int j = 0; j < FAMILYKEYBOARD_NUM_BUTTONS; j++) {
config->getOption(prefix + FamilyKeyBoardNames[j], &button);
fkbmap[j].ButtType[0] = type;
fkbmap[j].DeviceNum[0] = devnum;
fkbmap[j].ButtonNum[0] = button;
fkbmap[j].NumC = 1;
}
}

View File

@ -1,5 +1,8 @@
#ifndef _aosdfjk02fmasf
#define _aosdfjk02fmasf
#include "../common/configSys.h"
#define MAXBUTTCONFIG 4
typedef struct {
uint8 ButtType[MAXBUTTCONFIG];
@ -37,4 +40,8 @@ void DecreaseEmulationSpeed(void);
int DTestButtonJoy(ButtConfig *bc);
void FCEUD_UpdateInput(void);
void UpdateInput(Config *config);
void InputCfg(const std::string &);
#endif

View File

@ -17,6 +17,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __FCEU_SDL_MAIN_H
#define __FCEU_SDL_MAIN_H
#include <SDL.h>
#include "../../driver.h"
#include "../common/config.h"
@ -42,3 +46,110 @@ extern long soundbufsize;
int CLImain(int argc, char *argv[]);
// Device management defaults
#define NUM_INPUT_DEVICES 3
// GamePad defaults
#define GAMEPAD_NUM_DEVICES 4
#define GAMEPAD_NUM_BUTTONS 10
static char *GamePadNames[GAMEPAD_NUM_BUTTONS] =
{"A", "B", "Select", "Start",
"Up", "Down", "Left", "Right", "TurboA", "TurboB"};
static char *DefaultGamePadDevice[GAMEPAD_NUM_DEVICES] =
{"Keyboard", "None", "None", "None"};
static int DefaultGamePad[GAMEPAD_NUM_DEVICES][GAMEPAD_NUM_BUTTONS] =
{ { SDLK_KP2, SDLK_KP3, SDLK_TAB, SDLK_RETURN,
SDLK_w, SDLK_s, SDLK_a, SDLK_d, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
// PowerPad defaults
#define POWERPAD_NUM_DEVICES 2
#define POWERPAD_NUM_BUTTONS 12
static char *PowerPadNames[POWERPAD_NUM_BUTTONS] =
{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B"};
static char *DefaultPowerPadDevice[POWERPAD_NUM_DEVICES] =
{"Keyboard", "None"};
static int DefaultPowerPad[POWERPAD_NUM_DEVICES][POWERPAD_NUM_BUTTONS] =
{ { SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET,
SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE,
SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
// QuizKing defaults
#define QUIZKING_NUM_BUTTONS 6
static char *QuizKingNames[QUIZKING_NUM_BUTTONS] =
{ "0", "1", "2", "3", "4", "5" };
static char *DefaultQuizKingDevice = "Keyboard";
static int DefaultQuizKing[QUIZKING_NUM_BUTTONS] =
{ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y };
// HyperShot defaults
#define HYPERSHOT_NUM_BUTTONS 4
static char *HyperShotNames[HYPERSHOT_NUM_BUTTONS] =
{ "0", "1", "2", "3" };
static char *DefaultHyperShotDevice = "Keyboard";
static int DefaultHyperShot[HYPERSHOT_NUM_BUTTONS] =
{ SDLK_q, SDLK_w, SDLK_e, SDLK_r };
// Mahjong defaults
#define MAHJONG_NUM_BUTTONS 21
static char *MahjongNames[MAHJONG_NUM_BUTTONS] =
{ "00", "01", "02", "03", "04", "05", "06", "07",
"08", "09", "10", "11", "12", "13", "14", "15",
"16", "17", "18", "19", "20" };
static char *DefaultMahjongDevice = "Keyboard";
static int DefaultMahjong[MAHJONG_NUM_BUTTONS] =
{ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_a, SDLK_s, SDLK_d,
SDLK_f, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, SDLK_z, SDLK_x,
SDLK_c, SDLK_v, SDLK_b, SDLK_n, SDLK_m };
// TopRider defaults
#define TOPRIDER_NUM_BUTTONS 8
static char *TopRiderNames[TOPRIDER_NUM_BUTTONS] =
{ "0", "1", "2", "3", "4", "5", "6", "7" };
static char *DefaultTopRiderDevice = "Keyboard";
static int DefaultTopRider[TOPRIDER_NUM_BUTTONS] =
{ SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i };
// FTrainer defaults
#define FTRAINER_NUM_BUTTONS 12
static char *FTrainerNames[FTRAINER_NUM_BUTTONS] =
{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B" };
static char *DefaultFTrainerDevice = "Keyboard";
static int DefaultFTrainer[FTRAINER_NUM_BUTTONS] =
{ SDLK_o, SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET,
SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE,
SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH };
// FamilyKeyBoard defaults
#define FAMILYKEYBOARD_NUM_BUTTONS 0x48
static char *FamilyKeyBoardNames[FAMILYKEYBOARD_NUM_BUTTONS] =
{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
"MINUS", "EQUAL", "BACKSLASH", "BACKSPACE",
"ESCAPE", "Q", "W", "E", "R", "T", "Y", "U", "I", "O",
"P", "GRAVE", "BRACKET_LEFT", "ENTER",
"LEFTCONTROL", "A", "S", "D", "F", "G", "H", "J", "K",
"L", "SEMICOLON", "APOSTROPHE", "BRACKET_RIGHT", "INSERT",
"LEFTSHIFT", "Z", "X", "C", "V", "B", "N", "M", "COMMA",
"PERIOD", "SLASH", "RIGHTALT", "RIGHTSHIFT", "LEFTALT", "SPACE",
"DELETE", "END", "PAGEDOWN",
"CURSORUP", "CURSORLEFT", "CURSORRIGHT", "CURSORDOWN" };
static char *DefaultFamilyKeyBoardDevice = "Keyboard";
static int DefaultFamilyKeyBoard[FAMILYKEYBOARD_NUM_BUTTONS] =
{ SDLK_F1, SDLK_F2, SDLK_F3, SDLK_F4, SDLK_F5, SDLK_F6, SDLK_F7, SDLK_F8,
SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5,
SDLK_6, SDLK_7, SDLK_8, SDLK_9, SDLK_0,
SDLK_MINUS, SDLK_EQUALS, SDLK_BACKSLASH, SDLK_BACKSPACE,
SDLK_ESCAPE, SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u,
SDLK_i, SDLK_o, SDLK_p, SDLK_BACKQUOTE, SDLK_LEFTBRACKET, SDLK_RETURN,
SDLK_LCTRL, SDLK_a, SDLK_s, SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j,
SDLK_k, SDLK_l, SDLK_SEMICOLON, SDLK_QUOTE, SDLK_RIGHTBRACKET,
SDLK_INSERT, SDLK_LSHIFT, SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_b,
SDLK_n, SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH, SDLK_RALT,
SDLK_RSHIFT, SDLK_LALT, SDLK_SPACE, SDLK_DELETE, SDLK_END, SDLK_PAGEDOWN,
SDLK_UP, SDLK_LEFT, SDLK_RIGHT, SDLK_DOWN };
#endif

View File

@ -30,7 +30,10 @@
#include "sdl.h"
#define MAX_JOYSTICKS 32
static SDL_Joystick *Joysticks[MAX_JOYSTICKS] = {NULL};
static SDL_Joystick *s_Joysticks[MAX_JOYSTICKS] = {NULL};
static int s_jinited = 0;
/**
* Tests if the given button is active on the joystick.
@ -44,7 +47,7 @@ DTestButtonJoy(ButtConfig *bc)
if(bc->ButtonNum[x] & 0x8000) {
/* Axis "button" */
int pos;
pos = SDL_JoystickGetAxis(Joysticks[bc->DeviceNum[x]],
pos = SDL_JoystickGetAxis(s_Joysticks[bc->DeviceNum[x]],
bc->ButtonNum[x] & 16383);
if ((bc->ButtonNum[x] & 0x4000) && pos <= -16383) {
return(1);
@ -53,11 +56,11 @@ DTestButtonJoy(ButtConfig *bc)
}
} else if(bc->ButtonNum[x] & 0x2000) {
/* Hat "button" */
if(SDL_JoystickGetHat(Joysticks[bc->DeviceNum[x]],
if(SDL_JoystickGetHat(s_Joysticks[bc->DeviceNum[x]],
(((bc->ButtonNum[x] >> 8) & 0x1F) &
(bc->ButtonNum[x]&0xFF)))) {
return(1);
} else if(SDL_JoystickGetButton(Joysticks[bc->DeviceNum[x]],
} else if(SDL_JoystickGetButton(s_Joysticks[bc->DeviceNum[x]],
bc->ButtonNum[x])) {
return(1);
}
@ -66,8 +69,6 @@ DTestButtonJoy(ButtConfig *bc)
return(0);
}
static int jinited = 0;
/**
* Shutdown the SDL joystick subsystem.
*/
@ -76,15 +77,15 @@ KillJoysticks()
{
int n; /* joystick index */
if(!jinited) {
if(!s_jinited) {
return(-1);
}
for(n = 0; n < MAX_JOYSTICKS; n++) {
if (Joysticks[n] != 0) {
SDL_JoystickClose(Joysticks[n]);
if (s_Joysticks[n] != 0) {
SDL_JoystickClose(s_Joysticks[n]);
}
Joysticks[n]=0;
s_Joysticks[n]=0;
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return(0);
@ -108,12 +109,12 @@ InitJoysticks()
for(n = 0; n < total; n++) {
/* Open the joystick under SDL. */
Joysticks[n] = SDL_JoystickOpen(n);
s_Joysticks[n] = SDL_JoystickOpen(n);
//printf("Could not open joystick %d: %s.\n",
//joy[n] - 1, SDL_GetError());
continue;
}
jinited = 1;
s_jinited = 1;
return(1);
}

View File

@ -74,93 +74,107 @@ glClear_Func p_glClear;
glMatrixMode_Func p_glMatrixMode;
glDisable_Func p_glDisable;
void SetOpenGLPalette(uint8 *data)
void
SetOpenGLPalette(uint8 *data)
{
if(!HiBuffer)
{
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
p_glColorTableEXT(GL_TEXTURE_2D,GL_RGB,256,GL_RGBA,GL_UNSIGNED_BYTE,data);
}
else
SetPaletteBlitToHigh((uint8*)data);
if(!HiBuffer) {
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
p_glColorTableEXT(GL_TEXTURE_2D, GL_RGB, 256,
GL_RGBA, GL_UNSIGNED_BYTE, data);
} else {
SetPaletteBlitToHigh((uint8*)data);
}
}
void BlitOpenGL(uint8 *buf)
void
BlitOpenGL(uint8 *buf)
{
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
if(HiBuffer)
{
static int xo=0;
xo=(xo+1)&3;
Blit8ToHigh(buf,(uint8*)HiBuffer,256,240,256*4,1,1);
if(!xo)
p_glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,256,256, 0, GL_RGBA,GL_UNSIGNED_BYTE,
HiBuffer);
}
else
{
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
}
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
if(HiBuffer) {
static int xo = 0;
xo = (xo + 1) & 3;
Blit8ToHigh(buf, (uint8*)HiBuffer, 256, 240, 256*4, 1, 1);
if(!xo) {
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 256, 0,
GL_RGBA, GL_UNSIGNED_BYTE, HiBuffer);
}
} else {
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
}
p_glBegin(GL_QUADS);
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
p_glBegin(GL_QUADS);
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of picture.
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256);// Bottom right of picture.
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
p_glEnd();
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
p_glEnd();
//glDisable(GL_BLEND);
if(scanlines)
{
p_glEnable(GL_BLEND);
//glDisable(GL_BLEND);
if(scanlines) {
p_glEnable(GL_BLEND);
p_glBindTexture(GL_TEXTURE_2D, textures[1]);
p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
p_glBindTexture(GL_TEXTURE_2D, textures[1]);
p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
p_glBegin(GL_QUADS);
p_glBegin(GL_QUADS);
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
p_glTexCoord2f(1.0f*left/256,
1.0f*bottom/256); // Bottom left of our picture.
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
p_glTexCoord2f(1.0f*right/256,
1.0f*bottom/256); // Bottom right of our picture.
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
p_glTexCoord2f(1.0f*right/256,
1.0f*top/256); // Top right of our picture.
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
p_glTexCoord2f(1.0f*left/256,
1.0f*top/256); // Top left of our picture.
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
p_glEnd();
p_glDisable(GL_BLEND);
}
SDL_GL_SwapBuffers();
p_glEnd();
p_glDisable(GL_BLEND);
}
SDL_GL_SwapBuffers();
}
void KillOpenGL(void)
void
KillOpenGL(void)
{
if(textures[0])
p_glDeleteTextures(2, &textures[0]);
textures[0]=0;
if(HiBuffer)
{
free(HiBuffer);
HiBuffer=0;
}
if(textures[0]) {
p_glDeleteTextures(2, &textures[0]);
}
textures[0]=0;
if(HiBuffer) {
free(HiBuffer);
HiBuffer=0;
}
}
/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */
int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
int stretchx, int stretchy, SDL_Surface *screen)
int
InitOpenGL(int l,
int r,
int t,
int b,
double xscale,
double yscale,
int efx,
int ipolate,
int stretchx,
int stretchy,
SDL_Surface *screen)
{
const char *extensions;
@ -211,8 +225,8 @@ int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx,
}
{
int rw=(r-l)*xscale;
int rh=(b-t)*yscale;
int rw=(int)((r-l)*xscale);
int rh=(int)((b-t)*yscale);
int sx=(screen->w-rw)/2; // Start x
int sy=(screen->h-rh)/2; // Start y

View File

@ -27,11 +27,17 @@
#include "sdl.h"
static volatile int *Buffer = 0;
static unsigned int BufferSize;
static unsigned int BufferRead;
static unsigned int BufferWrite;
static volatile unsigned int BufferIn;
#include "../common/configSys.h"
extern Config *g_config;
static volatile int *s_Buffer = 0;
static unsigned int s_BufferSize;
static unsigned int s_BufferRead;
static unsigned int s_BufferWrite;
static volatile unsigned int s_BufferIn;
static int s_mute = 0;
/**
* Callback from the SDL to get and play audio data.
@ -46,10 +52,10 @@ fillaudio(void *udata,
while(len) {
int16 sample = 0;
if(BufferIn) {
sample = Buffer[BufferRead];
BufferRead = (BufferRead + 1) % BufferSize;
BufferIn--;
if(s_BufferIn) {
sample = s_Buffer[s_BufferRead];
s_BufferRead = (s_BufferRead + 1) % s_BufferSize;
s_BufferIn--;
} else {
sample = 0;
}
@ -66,8 +72,13 @@ fillaudio(void *udata,
int
InitSound(FCEUGI *gi)
{
int sound, soundrate, soundbufsize, soundvolume, soundq;
SDL_AudioSpec spec;
if(!_sound) return(0);
g_config->getOption("SDL.Sound", &sound);
if(!sound) {
return 0;
}
memset(&spec, 0, sizeof(spec));
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
@ -76,6 +87,12 @@ InitSound(FCEUGI *gi)
return(0);
}
// load configuration variables
g_config->getOption("SDL.SoundRate", &soundrate);
g_config->getOption("SDL.SoundBufSize", &soundbufsize);
g_config->getOption("SDL.SoundVolume", &soundvolume);
g_config->getOption("SDL.SoundQuality", &soundq);
spec.freq = soundrate;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
@ -83,18 +100,18 @@ InitSound(FCEUGI *gi)
spec.callback = fillaudio;
spec.userdata = 0;
BufferSize = soundbufsize * soundrate / 1000;
s_BufferSize = soundbufsize * soundrate / 1000;
// XXX soules - what is this??
/* SDL uses at least double-buffering, so multiply by 2. */
BufferSize -= spec.samples * 2;
s_BufferSize -= spec.samples * 2;
if(BufferSize < spec.samples) BufferSize = spec.samples;
if(s_BufferSize < spec.samples) s_BufferSize = spec.samples;
Buffer = (int *)malloc(sizeof(int) * BufferSize);
BufferRead = BufferWrite = BufferIn = 0;
s_Buffer = (int *)malloc(sizeof(int) * s_BufferSize);
s_BufferRead = s_BufferWrite = s_BufferIn = 0;
//printf("SDL Size: %d, Internal size: %d\n",spec.samples,BufferSize);
//printf("SDL Size: %d, Internal size: %d\n",spec.samples,s_BufferSize);
if(SDL_OpenAudio(&spec, 0) < 0) {
puts(SDL_GetError());
@ -102,6 +119,9 @@ InitSound(FCEUGI *gi)
return(0);
}
SDL_PauseAudio(0);
FCEUI_SetSoundVolume(soundvolume);
FCEUI_SetSoundQuality(soundq);
FCEUI_Sound(soundrate);
return(1);
}
@ -113,7 +133,7 @@ InitSound(FCEUGI *gi)
uint32
GetMaxSound(void)
{
return(BufferSize);
return(s_BufferSize);
}
/**
@ -122,7 +142,7 @@ GetMaxSound(void)
uint32
GetWriteSound(void)
{
return(BufferSize - BufferIn);
return(s_BufferSize - s_BufferIn);
}
/**
@ -133,14 +153,14 @@ WriteSound(int32 *buf,
int Count)
{
while(Count) {
while(BufferIn == BufferSize) {
while(s_BufferIn == s_BufferSize) {
SDL_Delay(1);
}
Buffer[BufferWrite] = *buf;
s_Buffer[s_BufferWrite] = *buf;
Count--;
BufferWrite = (BufferWrite + 1) % BufferSize;
BufferIn++;
s_BufferWrite = (s_BufferWrite + 1) % s_BufferSize;
s_BufferIn++;
buf++;
}
}
@ -163,17 +183,14 @@ KillSound(void)
FCEUI_Sound(0);
SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
if(Buffer) {
free((void *)Buffer);
Buffer = 0;
if(s_Buffer) {
free((void *)s_Buffer);
s_Buffer = 0;
}
return(0);
}
static int mute=0;
static int soundvolume=100;
/**
* Adjust the volume either down (-1), up (1), or to the default (0).
* Unmutes if mute was active before.
@ -181,6 +198,9 @@ static int soundvolume=100;
void
FCEUD_SoundVolumeAdjust(int n)
{
int soundvolume;
g_config->getOption("SDL.SoundVolume", &soundvolume);
switch(n) {
case -1:
soundvolume -= 10;
@ -199,8 +219,10 @@ FCEUD_SoundVolumeAdjust(int n)
break;
}
mute = 0;
s_mute = 0;
FCEUI_SetSoundVolume(soundvolume);
g_config->setOption("SDL.SoundVolume", soundvolume);
FCEU_DispMessage("Sound volume %d.", soundvolume);
}
@ -210,12 +232,15 @@ FCEUD_SoundVolumeAdjust(int n)
void
FCEUD_SoundToggle(void)
{
if(mute) {
mute = 0;
if(s_mute) {
int soundvolume;
g_config->getOption("SDL.SoundVolume", &soundvolume);
s_mute = 0;
FCEUI_SetSoundVolume(soundvolume);
FCEU_DispMessage("Sound mute off.");
} else {
mute = 1;
s_mute = 1;
FCEUI_SetSoundVolume(0);
FCEU_DispMessage("Sound mute on.");
}

View File

@ -4,14 +4,14 @@
#include "sdl.h"
#include "throttle.h"
static uint64 tfreq;
static uint64 desiredfps;
static uint64 s_tfreq;
static uint64 s_desiredfps;
static int32 fps_scale_table[]=
static int32 s_fpsScaleTable[]=
{ 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 };
int32 fps_scale = 256;
int32 g_fpsScale = 256;
#define fps_table_size (sizeof(fps_scale_table) / sizeof(fps_scale_table[0]))
#define FPS_TABLE_SIZE (sizeof(s_fpsScaleTable) / sizeof(s_fpsScaleTable[0]))
/**
* Refreshes the FPS throttling variables.
@ -19,10 +19,10 @@ int32 fps_scale = 256;
void
RefreshThrottleFPS()
{
desiredfps = FCEUI_GetDesiredFPS() >> 8;
desiredfps = (desiredfps * fps_scale) >> 8;
tfreq = 10000000;
tfreq <<= 16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
s_desiredfps = FCEUI_GetDesiredFPS() >> 8;
s_desiredfps = (s_desiredfps * g_fpsScale) >> 8;
s_tfreq = 10000000;
s_tfreq <<= 16; /* Adjust for fps returned from FCEUI_GetDesiredFPS(). */
}
/**
@ -44,8 +44,8 @@ SpeedThrottle()
ttime = SDL_GetTicks();
ttime *= 10000;
if((ttime - ltime) < (tfreq / desiredfps)) {
int64 delay = (tfreq / desiredfps) - (ttime - ltime);
if((ttime - ltime) < (s_tfreq / s_desiredfps)) {
int64 delay = (s_tfreq / s_desiredfps) - (ttime - ltime);
if(delay > 0) {
SDL_Delay(delay / 10000);
}
@ -55,10 +55,10 @@ SpeedThrottle()
} while(doDelay);
// update the "last time" to match when we want the next tick
if((ttime - ltime) >= ((tfreq * 4) / desiredfps)) {
if((ttime - ltime) >= ((s_tfreq * 4) / s_desiredfps)) {
ltime = ttime;
} else {
ltime += tfreq / desiredfps;
ltime += s_tfreq / s_desiredfps;
}
}
@ -71,15 +71,15 @@ IncreaseEmulationSpeed()
int i = 0;
// find the next entry in the FPS rate table
while(i < (fps_table_size - 1) && fps_scale_table[i] < fps_scale) {
while(i < (FPS_TABLE_SIZE - 1) && s_fpsScaleTable[i] < g_fpsScale) {
i++;
}
fps_scale = fps_scale_table[i+1];
g_fpsScale = s_fpsScaleTable[i+1];
// refresh the FPS throttling variables
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
FCEU_DispMessage("emulation speed %d%%",(g_fpsScale*100)>>8);
}
/**
@ -91,15 +91,15 @@ DecreaseEmulationSpeed()
int i = 1;
// find the previous entry in the FPS rate table
while(i < fps_table_size && fps_scale_table[i] < fps_scale) {
while(i < FPS_TABLE_SIZE && s_fpsScaleTable[i] < g_fpsScale) {
i++;
}
fps_scale = fps_scale_table[i - 1];
g_fpsScale = s_fpsScaleTable[i - 1];
// refresh the FPS throttling variables
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
FCEU_DispMessage("emulation speed %d%%",(g_fpsScale*100)>>8);
}
/**
@ -110,19 +110,19 @@ FCEUD_SetEmulationSpeed(int cmd)
{
switch(cmd) {
case EMUSPEED_SLOWEST:
fps_scale = fps_scale_table[0];
g_fpsScale = s_fpsScaleTable[0];
break;
case EMUSPEED_SLOWER:
DecreaseEmulationSpeed();
break;
case EMUSPEED_NORMAL:
fps_scale = 256;
g_fpsScale = 256;
break;
case EMUSPEED_FASTER:
IncreaseEmulationSpeed();
break;
case EMUSPEED_FASTEST:
fps_scale = fps_scale_table[fps_table_size - 1];
g_fpsScale = s_fpsScaleTable[FPS_TABLE_SIZE - 1];
break;
default:
return;
@ -130,5 +130,5 @@ FCEUD_SetEmulationSpeed(int cmd)
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
FCEU_DispMessage("emulation speed %d%%",(g_fpsScale*100)>>8);
}

View File

@ -33,28 +33,34 @@
#include "sdl-icon.h"
#include "dface.h"
SDL_Surface *screen;
#include "../common/configSys.h"
static SDL_Surface *BlitBuf; // Buffer when using hardware-accelerated blits.
static SDL_Surface *IconSurface=NULL;
// GLOBALS
extern Config *g_config;
static int curbpp;
static int srendline,erendline;
static int tlines;
static int inited;
// STATIC GLOBALS
static SDL_Surface *s_screen;
static SDL_Surface *s_BlitBuf; // Buffer when using hardware-accelerated blits.
static SDL_Surface *s_IconSurface = NULL;
static int s_curbpp;
static int s_srendline, s_erendline;
static int s_tlines;
static int s_inited;
#ifdef OPENGL
extern int sdlhaveogl;
static int usingogl;
static int s_useOpenGL;
#endif
static double exs,eys;
static int eefx;
static double s_exs, s_eys;
static int s_eefx;
static int s_clipSides;
static int s_fullscreen;
#define NWIDTH (256 - ((eoptions & EO_CLIPSIDES) ? 16 : 0))
#define NOFFSET (eoptions & EO_CLIPSIDES ? 8 : 0)
#define NWIDTH (256 - (s_clipSides ? 16 : 0))
#define NOFFSET (s_clipSides ? 8 : 0)
static int paletterefresh;
static int s_paletterefresh;
/**
* Attempts to destroy the graphical video display. Returns 0 on
@ -64,27 +70,27 @@ int
KillVideo()
{
// if the IconSurface has been initialized, destroy it
if(IconSurface) {
SDL_FreeSurface(IconSurface);
IconSurface=0;
if(s_IconSurface) {
SDL_FreeSurface(s_IconSurface);
s_IconSurface=0;
}
// if the rest of the system has been initialized, shut it down
if(inited) {
if(s_inited) {
#ifdef OPENGL
// check for OpenGL and shut it down
if(usingogl)
if(s_useOpenGL)
KillOpenGL();
else
#endif
// shut down the system that converts from 8 to 16/32 bpp
if(curbpp > 8)
if(s_curbpp > 8)
KillBlitToHigh();
// shut down the SDL video sub-system
SDL_QuitSubSystem(SDL_INIT_VIDEO);
inited = 0;
s_inited = 0;
return 0;
}
@ -93,7 +99,7 @@ KillVideo()
return -1;
}
static int sponge;
static int s_sponge;
/**
* Attempts to initialize the graphical video display. Returns 0 on
@ -105,26 +111,33 @@ InitVideo(FCEUGI *gi)
// XXX soules - const? is this necessary?
const SDL_VideoInfo *vinf;
int error, flags = 0;
int doublebuf, xstretch, ystretch, xres, yres;
FCEUI_printf("Initializing video...");
// check the starting, ending, and total scan lines
FCEUI_GetCurrentVidSystem(&srendline, &erendline);
tlines = erendline - srendline + 1;
// load the relevant configuration variables
g_config->getOption("SDL.Fullscreen", &s_fullscreen);
g_config->getOption("SDL.DoubleBuffering", &doublebuf);
#ifdef OPENGL
g_config->getOption("SDL.OpenGL", &s_useOpenGL);
#endif
// XXX soules - what is the sponge variable?
if(_fullscreen) {
sponge = Settings.specialfs;
} else {
sponge = Settings.special;
}
g_config->getOption("SDL.SpecialFilter", &s_sponge);
g_config->getOption("SDL.XStretch", &xstretch);
g_config->getOption("SDL.YStretch", &ystretch);
g_config->getOption("SDL.XResolution", &xres);
g_config->getOption("SDL.YResolution", &yres);
g_config->getOption("SDL.ClipSides", &s_clipSides);
// check the starting, ending, and total scan lines
FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
s_tlines = s_erendline - s_srendline + 1;
// check for OpenGL and set the global flags
#ifdef OPENGL
usingogl = 0;
if(_opengl && sdlhaveogl && !sponge) {
if(s_useOpenGL && !s_sponge) {
flags = SDL_OPENGL;
usingogl = 1;
}
#endif
@ -136,19 +149,19 @@ InitVideo(FCEUGI *gi)
return -1;
}
}
inited = 1;
s_inited = 1;
// shows the cursor within the display window
SDL_ShowCursor(0);
// determine if we can allocate the display on the video card
vinf=SDL_GetVideoInfo();
vinf = SDL_GetVideoInfo();
if(vinf->hw_available) {
flags |= SDL_HWSURFACE;
}
// check if we are rendering fullscreen
if(_fullscreen) {
if(s_fullscreen) {
flags |= SDL_FULLSCREEN;
}
@ -158,122 +171,139 @@ InitVideo(FCEUGI *gi)
// enable double buffering if requested and we have hardware support
#ifdef OPENGL
if(usingogl) {
if(s_useOpenGL) {
FCEU_printf("Initializing with OpenGL (Disable with '-opengl 0').\n");
if(_doublebuf) {
if(doublebuf) {
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
}
} else
#endif
if(_doublebuf && (flags & SDL_HWSURFACE)) {
if(doublebuf && (flags & SDL_HWSURFACE)) {
flags |= SDL_DOUBLEBUF;
}
if(_fullscreen) {
int desbpp = _bpp;
if(s_fullscreen) {
int desbpp;
g_config->getOption("SDL.BitsPerPixel", &desbpp);
exs = _xscalefs;
eys = _yscalefs;
eefx = _efxfs;
g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys);
g_config->getOption("SDL.SpecialFX", &s_eefx);
#ifdef OPENGL
if(!usingogl) {exs=(int)exs;eys=(int)eys;}
else desbpp=0;
if(!s_useOpenGL) {
s_exs = (int)s_exs;
s_eys = (int)s_eys;
} else {
desbpp = 0;
}
if(sponge) {
exs = eys = 2;
if(sponge == 3 || sponge == 4) {
exs = eys = 3;
if(s_sponge) {
if(s_sponge == 3 || s_sponge == 4) {
s_exs = s_eys = 3;
} else {
s_exs = s_eys = 2;
}
eefx=0;
if(sponge == 1 || sponge == 3) {
s_eefx = 0;
if(s_sponge == 1 || s_sponge == 3) {
desbpp = 32;
}
}
if( (usingogl && !_stretchx) || !usingogl)
if((s_useOpenGL && !xstretch) || !s_useOpenGL)
#endif
if(_xres < (NWIDTH * exs) || exs <= 0.01) {
if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) {
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return -1;
}
#ifdef OPENGL
if( (usingogl && !_stretchy) || !usingogl)
if((s_useOpenGL && !ystretch) || !s_useOpenGL)
#endif
if(_yres<tlines*eys || eys <= 0.01) {
if(yres < s_tlines * s_eys || s_eys <= 0.01) {
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return -1;
}
screen = SDL_SetVideoMode(_xres, _yres, desbpp, flags);
if(!screen) {
s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags);
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
return -1;
}
} else {
int desbpp=0;
// not fullscreen
int desbpp = 0;
exs=_xscale;
eys=_yscale;
eefx=_efx;
g_config->getOption("SDL.XScale", &s_exs);
g_config->getOption("SDL.YScale", &s_eys);
g_config->getOption("SDL.SpecialFX", &s_eefx);
if(sponge) {
exs = eys = 2;
if(sponge >= 3) {
exs = eys = 3;
if(s_sponge) {
if(s_sponge >= 3) {
s_exs = s_eys = 3;
} else {
s_exs = s_eys = 2;
}
eefx = 0;
s_eefx = 0;
// XXX soules - no clue what below comment is from
// SDL's 32bpp->16bpp code is slighty faster than mine, at least :/
if(sponge == 1 || sponge == 3) {
desbpp=32;
if(s_sponge == 1 || s_sponge == 3) {
desbpp = 32;
}
}
#ifdef OPENGL
if(!usingogl) {exs=(int)exs;eys=(int)eys;}
if(exs <= 0.01)
{
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return -1;
}
if(eys <= 0.01)
{
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return -1;
}
if(!s_useOpenGL) {
s_exs = (int)s_exs;
s_eys = (int)s_eys;
}
if(s_exs <= 0.01) {
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return -1;
}
if(s_eys <= 0.01) {
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return -1;
}
#endif
screen = SDL_SetVideoMode((int)(NWIDTH*exs), (int)(tlines*eys),
s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs),
(int)(s_tlines * s_eys),
desbpp, flags);
if(!screen) {
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
return -1;
}
}
curbpp=screen->format->BitsPerPixel;
if(!screen) {
s_curbpp = s_screen->format->BitsPerPixel;
if(!s_screen) {
FCEUD_PrintError(SDL_GetError());
KillVideo();
return -1;
}
#if 0
// XXX soules - this would be creating a surface on the video
// card, but was commented out for some reason...
//BlitBuf=SDL_CreateRGBSurface(SDL_HWSURFACE,256,240,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0);
s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240,
s_screen->format->BitsPerPixel,
s_screen->format->Rmask,
s_screen->format->Gmask,
s_screen->format->Bmask, 0);
#endif
FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",
screen->w, screen->h, screen->format->BitsPerPixel,
_fullscreen ? "full screen" : "");
s_screen->w, s_screen->h, s_screen->format->BitsPerPixel,
s_fullscreen ? "full screen" : "");
if(curbpp != 8 && curbpp != 16 && curbpp != 24 && curbpp != 32) {
FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", curbpp);
if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) {
FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp);
KillVideo();
return -1;
}
@ -287,31 +317,42 @@ InitVideo(FCEUGI *gi)
// create the surface for displaying graphical messages
#ifdef LSB_FIRST
IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32*3,
0xFF, 0xFF00, 0xFF0000, 0x00);
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32 * 3,
0xFF, 0xFF00, 0xFF0000, 0x00);
#else
IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32*3,
0xFF0000, 0xFF00, 0xFF, 0x00);
s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
32, 32, 24, 32 * 3,
0xFF0000, 0xFF00, 0xFF, 0x00);
#endif
SDL_WM_SetIcon(IconSurface,0);
paletterefresh = 1;
SDL_WM_SetIcon(s_IconSurface,0);
s_paletterefresh = 1;
// XXX soules - can't SDL do this for us?
// if using more than 8bpp, initialize the conversion routines
if(curbpp > 8)
if(s_curbpp > 8)
#ifdef OPENGL
if(!usingogl)
if(!s_useOpenGL)
#endif
InitBlitToHigh(curbpp>>3,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,eefx,sponge);
InitBlitToHigh(s_curbpp >> 3,
s_screen->format->Rmask,
s_screen->format->Gmask,
s_screen->format->Bmask,
s_eefx, s_sponge);
#ifdef OPENGL
if(usingogl)
if(!InitOpenGL((eoptions&EO_CLIPSIDES)?8:0,256-((eoptions&EO_CLIPSIDES)?8:0),srendline,erendline+1,exs,eys,eefx,_openglip,_stretchx,_stretchy,screen)) {
if(s_useOpenGL) {
int openGLip;
g_config->getOption("SDL.OpenGLip", &openGLip);
if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0),
s_srendline, s_erendline + 1,
s_exs, s_eys, s_eefx,
openGLip, xstretch, ystretch, s_screen)) {
FCEUD_PrintError("Error initializing OpenGL.");
KillVideo();
return -1;
}
}
#endif
return 0;
}
@ -322,24 +363,24 @@ InitVideo(FCEUGI *gi)
void
ToggleFS()
{
int error;
int error, fullscreen = s_fullscreen;
// shut down the current video system
KillVideo();
// flip the fullscreen flag
_fullscreen = !_fullscreen;
g_config->setOption("SDL.Fullscreen", !fullscreen);
// try to initialize the video
error = InitVideo(GameInfo);
if(error) {
// if we fail, just continue with what worked before
_fullscreen = !_fullscreen;
g_config->setOption("SDL.Fullscreen", fullscreen);
InitVideo(GameInfo);
}
}
static SDL_Color psdl[256];
static SDL_Color s_psdl[256];
/**
* Sets the color for a particular index in the palette.
@ -350,11 +391,11 @@ FCEUD_SetPalette(uint8 index,
uint8 g,
uint8 b)
{
psdl[index].r = r;
psdl[index].g = g;
psdl[index].b = b;
s_psdl[index].r = r;
s_psdl[index].g = g;
s_psdl[index].b = b;
paletterefresh = 1;
s_paletterefresh = 1;
}
/**
@ -366,9 +407,9 @@ FCEUD_GetPalette(uint8 index,
uint8 *g,
uint8 *b)
{
*r = psdl[index].r;
*g = psdl[index].g;
*b = psdl[index].b;
*r = s_psdl[index].r;
*g = s_psdl[index].g;
*b = s_psdl[index].b;
}
/**
@ -378,15 +419,15 @@ static void
RedoPalette()
{
#ifdef OPENGL
if(usingogl)
SetOpenGLPalette((uint8*)psdl);
if(s_useOpenGL)
SetOpenGLPalette((uint8*)s_psdl);
else
#endif
{
if(curbpp > 8) {
SetPaletteBlitToHigh((uint8*)psdl);
if(s_curbpp > 8) {
SetPaletteBlitToHigh((uint8*)s_psdl);
} else {
SDL_SetPalette(screen, SDL_PHYSPAL, psdl, 0, 256);
SDL_SetPalette(s_screen, SDL_PHYSPAL, s_psdl, 0, 256);
}
}
}
@ -409,31 +450,31 @@ BlitScreen(uint8 *XBuf)
uint8 *dest;
int xo = 0, yo = 0;
if(!screen) {
if(!s_screen) {
return;
}
// refresh the palette if required
if(paletterefresh) {
if(s_paletterefresh) {
RedoPalette();
paletterefresh=0;
s_paletterefresh = 0;
}
#ifdef OPENGL
// OpenGL is handled separately
if(usingogl) {
if(s_useOpenGL) {
BlitOpenGL(XBuf);
return;
}
#endif
// XXX soules - not entirely sure why this is being done yet
XBuf += srendline * 256;
XBuf += s_srendline * 256;
if(BlitBuf) {
TmpScreen = BlitBuf;
if(s_BlitBuf) {
TmpScreen = s_BlitBuf;
} else {
TmpScreen = screen;
TmpScreen = s_screen;
}
// lock the display, if necessary
@ -445,32 +486,33 @@ BlitScreen(uint8 *XBuf)
dest = (uint8*)TmpScreen->pixels;
if(_fullscreen) {
xo = (int)(((TmpScreen->w - NWIDTH * exs)) / 2);
dest += xo * (curbpp >> 3);
if(TmpScreen->h > (tlines * eys)) {
yo = (int)((TmpScreen->h - tlines * eys) / 2);
if(s_fullscreen) {
xo = (int)(((TmpScreen->w - NWIDTH * s_exs)) / 2);
dest += xo * (s_curbpp >> 3);
if(TmpScreen->h > (s_tlines * s_eys)) {
yo = (int)((TmpScreen->h - s_tlines * s_eys) / 2);
dest += yo * TmpScreen->pitch;
}
}
// XXX soules - again, I'm surprised SDL can't handle this
// perform the blit, converting bpp if necessary
if(curbpp > 8) {
if(BlitBuf) {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, tlines,
if(s_curbpp > 8) {
if(s_BlitBuf) {
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, 1, 1);
} else {
Blit8ToHigh(XBuf + NOFFSET,dest, NWIDTH, tlines,
TmpScreen->pitch, (int)exs, (int)eys);
Blit8ToHigh(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, (int)s_exs, (int)s_eys);
}
} else {
if(BlitBuf) {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, tlines,
TmpScreen->pitch, 1, 1, 0, sponge);
if(s_BlitBuf) {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, 1, 1, 0, s_sponge);
} else {
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, tlines,
TmpScreen->pitch, (int)exs, (int)eys, eefx, sponge);
Blit8To8(XBuf + NOFFSET, dest, NWIDTH, s_tlines,
TmpScreen->pitch, (int)s_exs, (int)s_eys,
s_eefx, s_sponge);
}
}
@ -480,29 +522,30 @@ BlitScreen(uint8 *XBuf)
}
// if we have a hardware video buffer, do a fast video->video copy
if(BlitBuf) {
if(s_BlitBuf) {
SDL_Rect srect;
SDL_Rect drect;
srect.x = 0;
srect.y = 0;
srect.w = NWIDTH;
srect.h = tlines;
srect.h = s_tlines;
drect.x = 0;
drect.y = 0;
drect.w = (Uint16)(exs * NWIDTH);
drect.h = (Uint16)(eys * tlines);
drect.w = (Uint16)(s_exs * NWIDTH);
drect.h = (Uint16)(s_eys * s_tlines);
SDL_BlitSurface(BlitBuf, &srect, screen, &drect);
SDL_BlitSurface(s_BlitBuf, &srect, s_screen, &drect);
}
// ensure that the display is updated
SDL_UpdateRect(screen, xo, yo, (Uint32)(NWIDTH*exs), (Uint32)(tlines*eys));
SDL_UpdateRect(s_screen, xo, yo,
(Uint32)(NWIDTH * s_exs), (Uint32)(s_tlines * s_eys));
// have to flip the displayed buffer in the case of double buffering
if(screen->flags & SDL_DOUBLEBUF) {
SDL_Flip(screen);
if(s_screen->flags & SDL_DOUBLEBUF) {
SDL_Flip(s_screen);
}
}
@ -514,11 +557,11 @@ uint32
PtoV(uint16 x,
uint16 y)
{
y = (uint16)((double)y / eys);
x = (uint16)((double)x / exs);
if(eoptions & EO_CLIPSIDES) {
y = (uint16)((double)y / s_eys);
x = (uint16)((double)x / s_exs);
if(s_clipSides) {
x += 8;
}
y += srendline;
y += s_srendline;
return (x | (y << 16));
}

View File

@ -24,6 +24,8 @@
#include "sdl-video.h"
#include "unix-netplay.h"
#include "../common/configSys.h"
#ifdef WIN32
#include <windows.h>
#endif
@ -34,7 +36,7 @@ int sdlhaveogl;
#endif
extern int32 fps_scale;
extern int32 g_fpsScale;
int CloseGame(void);
@ -47,6 +49,10 @@ static void DriverKill(void);
static int DriverInitialize(FCEUGI *gi);
int gametype = 0;
// global configuration object
Config *g_config;
/**
* Prints an error string to STDOUT.
*/
@ -119,6 +125,8 @@ CloseStuff(int signum)
*/
int LoadGame(const char *path)
{
std::string filename;
CloseGame();
if(!FCEUI_LoadGame(path, 1)) {
return 0;
@ -129,10 +137,11 @@ int LoadGame(const char *path)
if(!DriverInitialize(GameInfo)) {
return(0);
}
if(soundrecfn) {
if(!FCEUI_BeginWaveRecord(soundrecfn)) {
free(soundrecfn);
soundrecfn=0;
g_config->getOption("SDL.SoundRecordFile", &filename);
if(filename.size()) {
if(!FCEUI_BeginWaveRecord(filename.c_str())) {
g_config->setOption("SDL.SoundRecordFile", "");
}
}
isloaded = 1;
@ -147,6 +156,8 @@ int LoadGame(const char *path)
int
CloseGame()
{
std::string filename;
if(!isloaded) {
return(0);
}
@ -155,7 +166,8 @@ CloseGame()
isloaded = 0;
GameInfo = 0;
if(soundrecfn) {
g_config->getOption("SDL.SoundRecordFile", &filename);
if(filename.size()) {
FCEUI_EndWaveRecord();
}
@ -165,7 +177,7 @@ CloseGame()
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
void DoFun(void)
static void DoFun(int frameskip)
{
uint8 *gfx;
int32 *sound;
@ -224,7 +236,7 @@ DriverInitialize(FCEUGI *gi)
static void
DriverKill()
{
SaveConfig();
//SaveConfig();
#ifndef WIN32
// XXX soules - capturing all these signals seems pointless
@ -253,14 +265,14 @@ FCEUD_Update(uint8 *XBuf,
int ocount = Count;
// apply frame scaling to Count
Count = (Count<<8)/fps_scale;
Count = (Count<<8) / g_fpsScale;
if(Count) {
int32 can=GetWriteSound();
static int uflow=0;
int32 tmpcan;
// don't underflow when scaling fps
if(can >= GetMaxSound() && fps_scale<=256) uflow=1; /* Go into massive underflow mode. */
if(can >= GetMaxSound() && g_fpsScale<=256) uflow=1; /* Go into massive underflow mode. */
if(can > Count) can=Count;
else uflow=0;
@ -270,7 +282,7 @@ FCEUD_Update(uint8 *XBuf,
//if(uflow) puts("Underflow");
tmpcan = GetWriteSound();
// don't underflow when scaling fps
if(fps_scale>256 || ((tmpcan < Count*0.90) && !uflow)) {
if(g_fpsScale>256 || ((tmpcan < Count*0.90) && !uflow)) {
if(XBuf && (inited&4) && !(NoWaiting & 2))
BlitScreen(XBuf);
Buffer+=can;
@ -356,6 +368,8 @@ int
main(int argc,
char *argv[])
{
int error, frameskip;
FCEUD_Message("\nStarting "FCEU_NAME_AND_VERSION"...\n");
#ifdef WIN32
@ -378,9 +392,12 @@ main(int argc,
#endif
#endif
SetDefaults();
int error;
// Initialize the configuration system
g_config = InitConfig();
if(!g_config) {
SDL_Quit();
return -1;
}
// initialize the infrastructure
error = FCEUI_Initialize();
@ -389,15 +406,22 @@ main(int argc,
return -1;
}
// XXX configuration initialization
error = InitConfig(argc, argv);
if(error) {
int romIndex = g_config->parse(argc, argv);
if(romIndex <= 0) {
FCEUD_Message("\nError parsing command line arguments\n");
SDL_Quit();
return -1;
}
// update the input devices
UpdateInput(g_config);
// update the emu core
UpdateEMUCore(g_config);
g_config->getOption("SDL.Frameskip", &frameskip);
// load the specified game
error = LoadGame(argv[argc - 1]);
error = LoadGame(argv[romIndex]);
if(error != 1) {
DriverKill();
SDL_Quit();
@ -406,12 +430,12 @@ main(int argc,
// loop playing the game
while(GameInfo) {
DoFun();
DoFun(frameskip);
}
CloseGame();
// save the configuration information
SaveConfig();
// save the configuration information?
//SaveConfig();
// exit the infrastructure
FCEUI_Kill();

View File

@ -2,47 +2,3 @@
#include "main.h"
#include "dface.h"
#include "input.h"
typedef struct {
int xres;
int yres;
double xscale,yscale;
double xscalefs,yscalefs;
int efx,efxfs;
int bpp;
int fullscreen;
int doublebuf;
char *fshack;
char *fshacksave;
#ifdef OPENGL
int opengl;
int openglip;
int stretchx,stretchy;
#endif
int special,specialfs;
} DSETTINGS;
extern DSETTINGS Settings;
#define _doublebuf Settings.doublebuf
#define _bpp Settings.bpp
#define _xres Settings.xres
#define _yres Settings.yres
#define _fullscreen Settings.fullscreen
#define _xscale Settings.xscale
#define _yscale Settings.yscale
#define _xscalefs Settings.xscalefs
#define _yscalefs Settings.yscalefs
#define _efx Settings.efx
#define _efxfs Settings.efxfs
#define _ebufsize Settings.ebufsize
#define _fshack Settings.fshack
#define _fshacksave Settings.fshacksave
#ifdef OPENGL
#define _opengl Settings.opengl
#define _openglip Settings.openglip
#define _stretchx Settings.stretchx
#define _stretchy Settings.stretchy
#endif

View File

@ -48,6 +48,11 @@
#include "../../fceu.h"
#include "../../utils/md5.h"
#include <string>
#include "../common/configSys.h"
extern Config *g_config;
#ifndef socklen_t
#define socklen_t int
#endif
@ -56,264 +61,283 @@
#define SOL_TCP IPPROTO_TCP
#endif
char *netplayhost=0;
char *netplaynick=0;
char *netgamekey = 0;
char *netpassword = 0;
int netlocalplayers = 1;
int Port=0xFCE;
int FCEUDnetplay=0;
int tport=0xFCE;
static int Socket=-1;
static int s_Socket = -1;
static void en32(uint8 *buf, uint32 morp)
static void
en32(uint8 *buf,
uint32 morp)
{
buf[0]=morp;
buf[1]=morp>>8;
buf[2]=morp>>16;
buf[3]=morp>>24;
buf[0] = morp;
buf[1] = morp >> 8;
buf[2] = morp >> 16;
buf[3] = morp >> 24;
}
/*
static uint32 de32(uint8 *morp)
{
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
}
*/
int FCEUD_NetworkConnect(void)
int
FCEUD_NetworkConnect(void)
{
struct sockaddr_in sockin; /* I want to play with fighting robots. */
struct hostent *phostentb;
unsigned long hadr;
int TSocket;
int netdivisor;
struct sockaddr_in sockin;
struct hostent *phostentb;
unsigned long hadr;
int TSocket, tcpopt, error;
int netdivisor;
if(!netplayhost) return(0);
if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==-1)
{
puts("Error creating stream socket.");
FCEUD_NetworkClose();
return(0);
}
{
int tcpopt = 1;
#ifdef BEOS
if(setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int)))
#elif WIN32
if(setsockopt(TSocket, SOL_TCP, TCP_NODELAY, (char*)&tcpopt, sizeof(int)))
#else
if(setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int)))
#endif
puts("Nodelay fail");
}
memset(&sockin,0,sizeof(sockin));
sockin.sin_family=AF_INET;
hadr=inet_addr(netplayhost);
if(hadr!=INADDR_NONE)
sockin.sin_addr.s_addr=hadr;
else
{
puts("*** Looking up host name...");
if(!(phostentb=gethostbyname((const char *)netplayhost)))
{
puts("Error getting host network information.");
close(TSocket);
FCEUD_NetworkClose();
return(0);
}
memcpy(&sockin.sin_addr,phostentb->h_addr,phostentb->h_length);
}
sockin.sin_port=htons(tport);
puts("*** Connecting to remote host...");
if(connect(TSocket,(struct sockaddr *)&sockin,sizeof(sockin))==-1)
{
puts("Error connecting to remote host.");
close(TSocket);
FCEUD_NetworkClose();
return(0);
}
Socket=TSocket;
puts("*** Sending initialization data to server...");
{
uint8 *sendbuf;
uint8 buf[5];
uint32 sblen;
sblen = 4 + 16 + 16 + 64 + 1 + (netplaynick?strlen(netplaynick):0);
sendbuf = (uint8 *)malloc(sblen);
memset(sendbuf, 0, sblen);
en32(sendbuf, sblen - 4);
if(netgamekey)
{
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, GameInfo->MD5, 16);
md5_update(&md5, (uint8 *)netgamekey, strlen(netgamekey));
md5_finish(&md5, md5out);
memcpy(sendbuf + 4, md5out, 16);
}
else
memcpy(sendbuf + 4, GameInfo->MD5, 16);
if(netpassword)
{
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, (uint8 *)netpassword, strlen(netpassword));
md5_finish(&md5, md5out);
memcpy(sendbuf + 4 + 16, md5out, 16);
}
memset(sendbuf + 4 + 16 + 16, 0, 64);
sendbuf[4 + 16 + 16 + 64] = netlocalplayers;
if(netplaynick)
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,netplaynick,strlen(netplaynick));
#ifdef WIN32
send(Socket, (char*)sendbuf, sblen, 0);
#else
send(Socket, sendbuf, sblen, 0);
#endif
free(sendbuf);
#ifdef WIN32
recv(Socket, (char*)buf, 1, 0);
#else
recv(Socket, buf, 1, MSG_WAITALL);
#endif
netdivisor = buf[0];
}
puts("*** Connection established.");
FCEUDnetplay = 1;
FCEUI_NetplayStart(netlocalplayers, netdivisor);
return(1);
}
// get any required configuration variables
int port, localPlayers;
std::string server, username, password, key;
g_config->getOption("SDL.NetworkServer", &server);
g_config->getOption("SDL.NetworkUsername", &username);
g_config->getOption("SDL.NetworkPassword", &password);
g_config->getOption("SDL.NetworkGameKey", &key);
g_config->getOption("SDL.NetworkPort", &port);
g_config->getOption("SDL.NetworkPlayers", &localPlayers);
int FCEUD_SendData(void *data, uint32 len)
{
int check;
#ifndef WIN32
if(!ioctl(fileno(stdin),FIONREAD,&check))
#endif
if(check)
{
char buf[1024];
char *f;
fgets(buf,1024,stdin);
if((f=strrchr(buf,'\n')))
*f=0;
FCEUI_NetplayText((uint8 *)buf);
}
#ifdef WIN32
send(Socket, (char*)data, len ,0);
#else
send(Socket, data, len ,0);
#endif
return(1);
}
int FCEUD_RecvData(void *data, uint32 len)
{
NoWaiting&=~2;
for(;;)
{
fd_set funfun;
struct timeval popeye;
popeye.tv_sec=0;
popeye.tv_usec=100000;
FD_ZERO(&funfun);
FD_SET(Socket,&funfun);
switch(select(Socket + 1,&funfun,0,0,&popeye))
{
case 0: continue;
case -1:return(0);
}
if(FD_ISSET(Socket,&funfun))
{
#ifdef WIN32
if(recv(Socket,(char*)data,len,0) == len)
#else
if(recv(Socket,data,len,MSG_WAITALL) == len)
#endif
{
//unsigned long beefie;
FD_ZERO(&funfun);
FD_SET(Socket, &funfun);
popeye.tv_sec = popeye.tv_usec = 0;
if(select(Socket + 1, &funfun, 0, 0, &popeye) == 1)
//if(!ioctl(Socket,FIONREAD,&beefie))
// if(beefie)
{
NoWaiting|=2;
//puts("Yaya");
// only initialize if remote server is specified
if(!server.size()) {
return 0;
}
return(1);
}
else
return(0);
}
}
return 0;
TSocket = socket(AF_INET, SOCK_STREAM, 0);
if(TSocket < 0) {
puts("Error creating stream socket.");
FCEUD_NetworkClose();
return 0;
}
// try to setup TCP_NODELAY to avoid network jitters
tcpopt = 1;
#ifdef BEOS
error = setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int));
#elif WIN32
error = setsockopt(TSocket, SOL_TCP, TCP_NODELAY,
(char*)&tcpopt, sizeof(int));
#else
error = setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int));
#endif
if(error) {
puts("Nodelay fail");
}
memset(&sockin, 0, sizeof(sockin));
sockin.sin_family = AF_INET;
hadr = inet_addr(server.c_str());
if(hadr != INADDR_NONE) {
sockin.sin_addr.s_addr = hadr;
} else {
puts("*** Looking up host name...");
phostentb = gethostbyname(server.c_str());
if(!phostentb) {
puts("Error getting host network information.");
close(TSocket);
FCEUD_NetworkClose();
return(0);
}
memcpy(&sockin.sin_addr, phostentb->h_addr, phostentb->h_length);
}
sockin.sin_port = htons(port);
puts("*** Connecting to remote host...");
error = connect(TSocket, (struct sockaddr *)&sockin, sizeof(sockin));
if(error < 0) {
puts("Error connecting to remote host.");
close(TSocket);
FCEUD_NetworkClose();
return 0;
}
s_Socket = TSocket;
puts("*** Sending initialization data to server...");
uint8 *sendbuf;
uint8 buf[5];
uint32 sblen, data;
sblen = 4 + 16 + 16 + 64 + 1 + username.size();
sendbuf = (uint8 *)malloc(sblen);
memset(sendbuf, 0, sblen);
// XXX soules - should use htons instead of en32() from above!
//data = htons(sblen - 4);
//memcpy(sendbuf, &data, sizeof(data));
en32(sendbuf, sblen - 4);
if(key.size()) {
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, GameInfo->MD5, 16);
md5_update(&md5, (uint8 *)key.c_str(), key.size());
md5_finish(&md5, md5out);
memcpy(sendbuf + 4, md5out, 16);
} else {
memcpy(sendbuf + 4, GameInfo->MD5, 16);
}
if(password.size()) {
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, (uint8 *)password.c_str(), password.size());
md5_finish(&md5, md5out);
memcpy(sendbuf + 4 + 16, md5out, 16);
}
memset(sendbuf + 4 + 16 + 16, 0, 64);
sendbuf[4 + 16 + 16 + 64] = (uint8)localPlayers;
if(username.size()) {
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,
username.c_str(), username.size());
}
#ifdef WIN32
send(s_Socket, (char*)sendbuf, sblen, 0);
#else
send(s_Socket, sendbuf, sblen, 0);
#endif
free(sendbuf);
#ifdef WIN32
recv(s_Socket, (char*)buf, 1, 0);
#else
recv(s_Socket, buf, 1, MSG_WAITALL);
#endif
netdivisor = buf[0];
puts("*** Connection established.");
FCEUDnetplay = 1;
FCEUI_NetplayStart(localPlayers, netdivisor);
return 1;
}
void FCEUD_NetworkClose(void)
int
FCEUD_SendData(void *data,
uint32 len)
{
if(Socket>0)
{
#ifdef BEOS
closesocket(Socket);
#else
close(Socket);
#endif
}
Socket=-1;
int check = 0, error = 0;
#ifndef WIN32
error = ioctl(fileno(stdin), FIONREAD, &check);
#endif
if(!error && check) {
char buf[1024];
char *f;
fgets(buf, 1024, stdin);
if((f=strrchr(buf,'\n'))) {
*f = 0;
}
FCEUI_NetplayText((uint8 *)buf);
}
if(FCEUDnetplay)
FCEUI_NetplayStop();
FCEUDnetplay = 0;
#ifdef WIN32
send(s_Socket, (char*)data, len ,0);
#else
send(s_Socket, data, len ,0);
#endif
return 1;
}
void FCEUD_NetplayText(uint8 *text)
int
FCEUD_RecvData(void *data,
uint32 len)
{
char *tot = (char *)malloc(strlen((const char *)text) + 1);
char *tmp;
strcpy(tot, (const char *)text);
tmp = tot;
int size;
NoWaiting &= ~2;
for(;;) {
fd_set funfun;
struct timeval popeye;
popeye.tv_sec=0;
popeye.tv_usec=100000;
FD_ZERO(&funfun);
FD_SET(s_Socket, &funfun);
while(*tmp)
{
if(*tmp < 0x20) *tmp = ' ';
tmp++;
}
puts(tot);
free(tot);
switch(select(s_Socket + 1,&funfun,0,0,&popeye)) {
case 0: continue;
case -1:return(0);
}
if(FD_ISSET(s_Socket,&funfun)) {
#ifdef WIN32
size = recv(s_Socket, (char*)data, len, 0);
#else
size = recv(s_Socket, data, len, MSG_WAITALL);
#endif
if(size == len) {
//unsigned long beefie;
FD_ZERO(&funfun);
FD_SET(s_Socket, &funfun);
popeye.tv_sec = popeye.tv_usec = 0;
if(select(s_Socket + 1, &funfun, 0, 0, &popeye) == 1)
//if(!ioctl(s_Socket,FIONREAD,&beefie))
// if(beefie)
{
NoWaiting|=2;
//puts("Yaya");
}
return(1);
} else {
return(0);
}
}
}
return 0;
}
void
FCEUD_NetworkClose(void)
{
if(s_Socket > 0) {
#ifdef BEOS
closesocket(s_Socket);
#else
close(s_Socket);
#endif
}
s_Socket = -1;
if(FCEUDnetplay) {
FCEUI_NetplayStop();
}
FCEUDnetplay = 0;
}
void
FCEUD_NetplayText(uint8 *text)
{
char *tot = (char *)malloc(strlen((const char *)text) + 1);
char *tmp;
strcpy(tot, (const char *)text);
tmp = tot;
while(*tmp) {
if(*tmp < 0x20) {
*tmp = ' ';
}
tmp++;
}
puts(tot);
free(tot);
}

View File

@ -588,7 +588,7 @@ static char FileExt[2048]; /* Includes the . character, as in ".nes" */
static char FileBaseDirectory[2048];
void FCEUI_SetBaseDirectory(char *dir)
void FCEUI_SetBaseDirectory(const char *dir)
{
strncpy(BaseDirectory,dir,2047);
BaseDirectory[2047]=0;

View File

@ -78,7 +78,7 @@ int FCEUI_EndWaveRecord(void)
}
int FCEUI_BeginWaveRecord(char *fn)
int FCEUI_BeginWaveRecord(const char *fn)
{
int r;