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:
sinamas 2007-08-28 22:16:53 +00:00
parent 7409939b67
commit 64f1ba20b9
6 changed files with 425 additions and 77 deletions

View File

@ -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)

View File

@ -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
View 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
View 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

View 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;
}
}

View 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