mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2024-11-23 07:49:48 +00:00
Support command line arguments.
git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@44 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
parent
7409939b67
commit
64f1ba20b9
@ -1,4 +1,4 @@
|
||||
env = Environment(CPPPATH = ['.', '../libgambatte/include'],
|
||||
env = Environment(CPPPATH = ['src', '../libgambatte/include'],
|
||||
LIBS = ['gambatte'],
|
||||
LIBPATH = '../libgambatte',
|
||||
CPPFLAGS = ARGUMENTS.get('CPPFLAGS', '-Wall -O2 -fno-exceptions -fno-rtti -fomit-frame-pointer'))
|
||||
@ -6,7 +6,9 @@ env = Environment(CPPPATH = ['.', '../libgambatte/include'],
|
||||
env.ParseConfig('sdl-config --cflags --libs')
|
||||
|
||||
sourceFiles = Split('''
|
||||
gambatte_sdl.cpp
|
||||
src/gambatte_sdl.cpp
|
||||
src/parser.cpp
|
||||
src/syncfunc.cpp
|
||||
''')
|
||||
|
||||
env.Program(sourceFiles)
|
||||
env.Program('gambatte_sdl', sourceFiles)
|
||||
|
@ -18,84 +18,27 @@
|
||||
***************************************************************************/
|
||||
#include <gambatte.h>
|
||||
#include <SDL/SDL.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace {
|
||||
struct timeval {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
};
|
||||
|
||||
void gettimeofday(timeval *const t, void *) {
|
||||
const unsigned long tv_msec = SDL_GetTicks();
|
||||
|
||||
t->tv_sec = tv_msec / 1000;
|
||||
t->tv_usec = (tv_msec % 1000) * 1000;
|
||||
}
|
||||
|
||||
void syncFunc() {
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
static timeval time = t;
|
||||
static long late = 0;
|
||||
static unsigned noSleep = 60;
|
||||
|
||||
if (time.tv_sec > t.tv_sec || (time.tv_sec == t.tv_sec && time.tv_usec > t.tv_usec)) {
|
||||
timeval tmp;
|
||||
tmp.tv_sec = 0;
|
||||
tmp.tv_usec = time.tv_usec - t.tv_usec;
|
||||
if (time.tv_sec != t.tv_sec)
|
||||
tmp.tv_usec += 1000000;
|
||||
|
||||
if (tmp.tv_usec > late) {
|
||||
tmp.tv_usec -= late;
|
||||
|
||||
if (tmp.tv_usec >= 1000000) {
|
||||
tmp.tv_usec -= 1000000;
|
||||
++tmp.tv_sec;
|
||||
}
|
||||
|
||||
SDL_Delay(tmp.tv_sec * 1000 + (tmp.tv_usec + 500) / 1000);
|
||||
|
||||
gettimeofday(&t, NULL);
|
||||
late -= (time.tv_sec - t.tv_sec) * 1000000 + time.tv_usec - t.tv_usec >> 1;
|
||||
// printf("late: %d\n", late);
|
||||
|
||||
if (late < 0)
|
||||
late = 0;
|
||||
|
||||
noSleep = 60;
|
||||
} else if (noSleep-- == 0) {
|
||||
noSleep = 60;
|
||||
late = 0;
|
||||
}
|
||||
|
||||
while (time.tv_sec > t.tv_sec || (time.tv_sec == t.tv_sec && time.tv_usec > t.tv_usec)) {
|
||||
gettimeofday(&t, NULL);
|
||||
}
|
||||
|
||||
} else
|
||||
time = t;
|
||||
|
||||
time.tv_usec += 16743;
|
||||
|
||||
if (time.tv_usec >= 1000000) {
|
||||
time.tv_usec -= 1000000;
|
||||
++time.tv_sec;
|
||||
}
|
||||
}
|
||||
}
|
||||
#include "syncfunc.h"
|
||||
#include "parser.h"
|
||||
|
||||
class SdlBlitter : public VideoBlitter {
|
||||
SDL_Surface *screen;
|
||||
unsigned startFlags;
|
||||
|
||||
public:
|
||||
SdlBlitter() : screen(NULL), startFlags(SDL_SWSURFACE) {}
|
||||
void setBufferDimensions(unsigned int width, unsigned int height);
|
||||
const PixelBuffer inBuffer();
|
||||
void blit();
|
||||
void toggleFullScreen();
|
||||
void setStartFull() { startFlags |= SDL_FULLSCREEN; }
|
||||
};
|
||||
|
||||
void SdlBlitter::setBufferDimensions(const unsigned int width, const unsigned int height) {
|
||||
screen = SDL_SetVideoMode(width, height, SDL_GetVideoInfo()->vfmt->BitsPerPixel == 16 ? 16 : 32, SDL_SWSURFACE/*|SDL_FULLSCREEN*/);
|
||||
screen = SDL_SetVideoMode(width, height, SDL_GetVideoInfo()->vfmt->BitsPerPixel == 16 ? 16 : 32, startFlags);
|
||||
}
|
||||
|
||||
const PixelBuffer SdlBlitter::inBuffer() {
|
||||
@ -118,6 +61,86 @@ static Gambatte gambatte;
|
||||
static SdlBlitter blitter;
|
||||
static InputState is;
|
||||
|
||||
struct FatOption {
|
||||
virtual Parser::Option* getShort() { return NULL; };
|
||||
virtual Parser::Option* getLong() = 0;
|
||||
virtual const char* getDesc() const = 0;
|
||||
virtual ~FatOption() {}
|
||||
};
|
||||
|
||||
class FsOption : public FatOption {
|
||||
class Main : public Parser::Option {
|
||||
protected:
|
||||
Main(const char *const s) : Option(s) {}
|
||||
public:
|
||||
void exec(const char *const */*argv*/, int /*index*/) {
|
||||
blitter.setStartFull();
|
||||
}
|
||||
};
|
||||
|
||||
struct Short : Main {
|
||||
Short() : Main("-f") {}
|
||||
};
|
||||
|
||||
struct Long : Main {
|
||||
Long() : Main("--full-screen") {}
|
||||
};
|
||||
|
||||
Short sOpt;
|
||||
Long lOpt;
|
||||
static const char *const desc;
|
||||
|
||||
public:
|
||||
Parser::Option* getShort() { return &sOpt; }
|
||||
Parser::Option* getLong() { return &lOpt; }
|
||||
const char* getDesc() const { return desc; }
|
||||
};
|
||||
|
||||
const char *const FsOption::desc = "\t\tStart in full screen mode\n";
|
||||
|
||||
class VfOption : public FatOption {
|
||||
class Main : public Parser::Option {
|
||||
protected:
|
||||
Main(const char *const s) : Option(s, 1) {}
|
||||
public:
|
||||
void exec(const char *const *argv, int index) {
|
||||
gambatte.setVideoFilter(atoi(argv[index + 1]));
|
||||
}
|
||||
};
|
||||
|
||||
struct Short : Main {
|
||||
Short() : Main("-v") {}
|
||||
};
|
||||
|
||||
struct Long : Main {
|
||||
Long() : Main("--video-filter") {}
|
||||
};
|
||||
|
||||
Short sOpt;
|
||||
Long lOpt;
|
||||
std::string s;
|
||||
|
||||
public:
|
||||
VfOption();
|
||||
Parser::Option* getShort() { return &sOpt; }
|
||||
Parser::Option* getLong() { return &lOpt; }
|
||||
const char* getDesc() const { return s.c_str(); }
|
||||
};
|
||||
|
||||
VfOption::VfOption() {
|
||||
const std::vector<const FilterInfo*> &finfo = gambatte.filterInfo();
|
||||
std::stringstream ss;
|
||||
ss << " N\t\tUse video filter number N\n";
|
||||
|
||||
for (std::size_t i = 0; i < finfo.size(); ++i) {
|
||||
ss << "\t\t\t\t " << i << " = " << finfo[i]->handle << "\n";
|
||||
}
|
||||
|
||||
s = ss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void fill_buffer(void *buffer, Uint8 *stream, int len);
|
||||
|
||||
// static unsigned bufPos = 0;
|
||||
@ -137,17 +160,55 @@ static InputGetter inputGetter;
|
||||
|
||||
static const unsigned SND_BUF_SZ = 4096;
|
||||
|
||||
static const char *const usage = "Usage: gambatte_sdl romfile\n";
|
||||
|
||||
static void printUsage(std::vector<FatOption*> &v) {
|
||||
printf("Usage: gambatte_sdl [OPTION]... romfile\n\n");
|
||||
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
printf(" %s, %s%s\n", v[i]->getShort()->getStr(), v[i]->getLong()->getStr(), v[i]->getDesc());
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
printf("Gambatte SDL svn\n");
|
||||
|
||||
if (argc < 2) {
|
||||
printf("Usage: gambatte_sdl romfile\n");
|
||||
return 1;
|
||||
}
|
||||
Parser parser;
|
||||
|
||||
if (gambatte.load(argv[1])) {
|
||||
printf("failed to load rom %s\n", argv[1]);
|
||||
return 1;
|
||||
{
|
||||
static std::vector<FatOption*> v;
|
||||
static FsOption fsOption;
|
||||
v.push_back(&fsOption);
|
||||
static VfOption vfOption;
|
||||
v.push_back(&vfOption);
|
||||
|
||||
for (unsigned i = 0; i < v.size(); ++i) {
|
||||
parser.add(v[i]->getShort());
|
||||
parser.add(v[i]->getLong());
|
||||
}
|
||||
|
||||
unsigned loadIndex = 0;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (argv[i][0] == '-') {
|
||||
if (!(i = parser.parse(argc, argv, i))) {
|
||||
printUsage(v);
|
||||
return 1;
|
||||
}
|
||||
} else if (!loadIndex) {
|
||||
loadIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadIndex) {
|
||||
printUsage(v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gambatte.load(argv[loadIndex])) {
|
||||
printf("failed to load ROM %s\n", argv[loadIndex]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
gambatte.setInputStateGetter(&inputGetter);
|
||||
@ -165,6 +226,7 @@ int main(int argc, char **argv) {
|
||||
SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO);
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
SDL_WM_SetCaption("Gambatte SDL", NULL);
|
||||
|
||||
SDL_OpenAudio(&spec, NULL);
|
||||
SDL_PauseAudio(0);
|
||||
@ -174,7 +236,6 @@ int main(int argc, char **argv) {
|
||||
|
||||
Uint8 *keys = SDL_GetKeyState(NULL);
|
||||
|
||||
// gambatte.setVideoFilter(4);
|
||||
gambatte.setVideoBlitter(&blitter);
|
||||
|
||||
for (;;) {
|
115
gambatte_sdl/src/parser.cpp
Normal file
115
gambatte_sdl/src/parser.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "parser.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
struct OptionLess {
|
||||
bool operator()(const Parser::Option *const l, const Parser::Option *const r) const {
|
||||
return l->getHash() < r->getHash();
|
||||
}
|
||||
};
|
||||
|
||||
static unsigned computeHash(const char *s) {
|
||||
unsigned hash = 0;
|
||||
|
||||
while (*s) {
|
||||
hash += *s++;
|
||||
hash += hash << 10;
|
||||
hash ^= hash >> 6;
|
||||
}
|
||||
|
||||
hash += hash << 3;
|
||||
hash ^= hash >> 11;
|
||||
hash += hash << 15;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
Parser::Option::Option(const char *const s, int nArgs) : s(s), hash(computeHash(s)), nArgs(nArgs) {}
|
||||
|
||||
Parser::Parser() : sorted(false) {
|
||||
memset(t, 0, sizeof(t));
|
||||
}
|
||||
|
||||
void Parser::addLong(Option *const o) {
|
||||
v.push_back(o);
|
||||
sorted = false;
|
||||
}
|
||||
|
||||
int Parser::parseLong(const int argc, const char *const *const argv, const int index) {
|
||||
if (!sorted)
|
||||
std::sort(v.begin(), v.end(), OptionLess());
|
||||
|
||||
sorted = true;
|
||||
|
||||
Option o(argv[index]);
|
||||
std::vector<Option*>::iterator it = lower_bound(v.begin(), v.end(), &o, OptionLess());
|
||||
|
||||
while (it != v.end() && (*it)->getHash() == o.getHash()) {
|
||||
if (!strcmp((*it)->getStr(), o.getStr())) {
|
||||
if ((*it)->neededArgs() >= argc - index)
|
||||
return 0;
|
||||
|
||||
(*it)->exec(argv, index);
|
||||
return index + (*it)->neededArgs();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Parser::addShort(Option *const o) {
|
||||
t[static_cast<unsigned char>(o->getStr()[1])] = o;
|
||||
}
|
||||
|
||||
int Parser::parseShort(const int argc, const char *const *const argv, const int index) {
|
||||
const char *s = argv[index];
|
||||
++s;
|
||||
|
||||
if (!(*s))
|
||||
return 0;
|
||||
|
||||
do {
|
||||
Option *const o = t[static_cast<unsigned char>(*s)];
|
||||
|
||||
if (!o)
|
||||
return 0;
|
||||
|
||||
if (o->neededArgs()) {
|
||||
if (s[1] || o->neededArgs() >= argc - index)
|
||||
return 0;
|
||||
|
||||
o->exec(argv, index);
|
||||
return index + o->neededArgs();
|
||||
}
|
||||
|
||||
o->exec(argv, index);
|
||||
} while (*++s);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void Parser::add(Option *const o) {
|
||||
(o->getStr()[1] == '-') ? addLong(o) : addShort(o);
|
||||
}
|
||||
|
||||
int Parser::parse(const int argc, const char *const *const argv, const int index) {
|
||||
return (argv[index][1] == '-') ? parseLong(argc, argv, index) : parseShort(argc, argv, index);
|
||||
}
|
56
gambatte_sdl/src/parser.h
Normal file
56
gambatte_sdl/src/parser.h
Normal file
@ -0,0 +1,56 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Parser {
|
||||
public:
|
||||
class Option {
|
||||
const char *const s;
|
||||
const unsigned hash;
|
||||
const int nArgs;
|
||||
|
||||
public:
|
||||
Option(const char *s, int nArgs = 0);
|
||||
virtual ~Option() {}
|
||||
unsigned getHash() const { return hash; }
|
||||
const char* getStr() const { return s; }
|
||||
int neededArgs() const { return nArgs; }
|
||||
virtual void exec(const char *const */*argv*/, int /*index*/) {}
|
||||
};
|
||||
|
||||
private:
|
||||
Option *t[256];
|
||||
std::vector<Option*> v;
|
||||
bool sorted;
|
||||
|
||||
void addLong(Option *o);
|
||||
void addShort(Option *o);
|
||||
int parseLong(int argc, const char *const *argv, int index);
|
||||
int parseShort(int argc, const char *const *argv, int index);
|
||||
|
||||
public:
|
||||
Parser();
|
||||
void add(Option *o);
|
||||
int parse(int argc,const char *const *argv, int index);
|
||||
};
|
||||
|
||||
#endif
|
90
gambatte_sdl/src/syncfunc.cpp
Normal file
90
gambatte_sdl/src/syncfunc.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include "syncfunc.h"
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
namespace SyncFunc {
|
||||
struct timeval {
|
||||
long tv_sec;
|
||||
long tv_usec;
|
||||
};
|
||||
|
||||
void gettimeofday(timeval *const t, void *) {
|
||||
const unsigned long tv_msec = SDL_GetTicks();
|
||||
|
||||
t->tv_sec = tv_msec / 1000;
|
||||
t->tv_usec = (tv_msec % 1000) * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
void syncFunc() {
|
||||
using SyncFunc::timeval;
|
||||
using SyncFunc::gettimeofday;
|
||||
|
||||
timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
static timeval time = t;
|
||||
static long late = 0;
|
||||
static unsigned noSleep = 60;
|
||||
|
||||
if (time.tv_sec > t.tv_sec || (time.tv_sec == t.tv_sec && time.tv_usec > t.tv_usec)) {
|
||||
timeval tmp;
|
||||
tmp.tv_sec = 0;
|
||||
tmp.tv_usec = time.tv_usec - t.tv_usec;
|
||||
if (time.tv_sec != t.tv_sec)
|
||||
tmp.tv_usec += 1000000;
|
||||
|
||||
if (tmp.tv_usec > late) {
|
||||
tmp.tv_usec -= late;
|
||||
|
||||
if (tmp.tv_usec >= 1000000) {
|
||||
tmp.tv_usec -= 1000000;
|
||||
++tmp.tv_sec;
|
||||
}
|
||||
|
||||
SDL_Delay(tmp.tv_sec * 1000 + (tmp.tv_usec + 500) / 1000);
|
||||
|
||||
gettimeofday(&t, NULL);
|
||||
late -= (time.tv_sec - t.tv_sec) * 1000000 + time.tv_usec - t.tv_usec >> 1;
|
||||
// printf("late: %d\n", late);
|
||||
|
||||
if (late < 0)
|
||||
late = 0;
|
||||
|
||||
noSleep = 60;
|
||||
} else if (noSleep-- == 0) {
|
||||
noSleep = 60;
|
||||
late = 0;
|
||||
}
|
||||
|
||||
while (time.tv_sec > t.tv_sec || (time.tv_sec == t.tv_sec && time.tv_usec > t.tv_usec)) {
|
||||
gettimeofday(&t, NULL);
|
||||
}
|
||||
|
||||
} else
|
||||
time = t;
|
||||
|
||||
time.tv_usec += 16743;
|
||||
|
||||
if (time.tv_usec >= 1000000) {
|
||||
time.tv_usec -= 1000000;
|
||||
++time.tv_sec;
|
||||
}
|
||||
}
|
24
gambatte_sdl/src/syncfunc.h
Normal file
24
gambatte_sdl/src/syncfunc.h
Normal file
@ -0,0 +1,24 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2007 by Sindre Aamås *
|
||||
* aamas@stud.ntnu.no *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License version 2 as *
|
||||
* published by the Free Software Foundation. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License version 2 for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* version 2 along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#ifndef SYNCFUNC_H
|
||||
#define SYNCFUNC_H
|
||||
|
||||
void syncFunc();
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user