mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2024-11-27 01:40:23 +00:00
Initial commit.
git-svn-id: https://gambatte.svn.sourceforge.net/svnroot/gambatte@2 9dfb2916-2d38-0410-aef4-c5fe6c9ffc24
This commit is contained in:
parent
8a034c0ee1
commit
8700ab170f
7
gambatte_sdl/SConstruct
Normal file
7
gambatte_sdl/SConstruct
Normal file
@ -0,0 +1,7 @@
|
||||
env = Environment(CPPFLAGS = '-Wall -O2 -fno-exceptions -fno-rtti -fomit-frame-pointer')
|
||||
|
||||
sourceFiles = Split('''
|
||||
gambatte_sdl.cpp
|
||||
''')
|
||||
|
||||
env.Program(sourceFiles, CPPPATH = ['.', '../libgambatte/include'], LIBS = ['gambatte', 'SDL'], LIBPATH = '../libgambatte')
|
251
gambatte_sdl/gambatte_sdl.cpp
Normal file
251
gambatte_sdl/gambatte_sdl.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
/***************************************************************************
|
||||
* 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 <gambatte.h>
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SdlBlitter : public VideoBlitter {
|
||||
SDL_Surface *screen;
|
||||
public:
|
||||
void setBufferDimensions(const unsigned int width, const unsigned int height);
|
||||
const PixelBuffer inBuffer();
|
||||
void blit();
|
||||
void toggleFullScreen();
|
||||
};
|
||||
|
||||
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*/);
|
||||
}
|
||||
|
||||
const PixelBuffer SdlBlitter::inBuffer() {
|
||||
PixelBuffer pb;
|
||||
pb.pixels = (Uint8*)(screen->pixels) + screen->offset;
|
||||
pb.format = screen->format->BitsPerPixel == 16 ? PixelBuffer::RGB16 : PixelBuffer::RGB32;
|
||||
pb.pitch = screen->pitch / screen->format->BytesPerPixel;
|
||||
return pb;
|
||||
}
|
||||
|
||||
void SdlBlitter::blit() {
|
||||
SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
|
||||
}
|
||||
|
||||
void SdlBlitter::toggleFullScreen() {
|
||||
screen = SDL_SetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel, screen->flags ^ SDL_FULLSCREEN);
|
||||
}
|
||||
|
||||
static Gambatte gambatte;
|
||||
static SdlBlitter blitter;
|
||||
static InputState is;
|
||||
|
||||
static void fill_buffer(void *buffer, Uint8 *stream, int len);
|
||||
|
||||
// static unsigned bufPos = 0;
|
||||
// static unsigned samples = 804;
|
||||
|
||||
static unsigned rPos = 0;
|
||||
static unsigned wPos = 0;
|
||||
|
||||
class InputGetter : public InputStateGetter {
|
||||
public:
|
||||
const InputState& operator()() {
|
||||
return is;
|
||||
}
|
||||
};
|
||||
|
||||
static InputGetter inputGetter;
|
||||
|
||||
static const unsigned SND_BUF_SZ = 4096;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("No rom specified\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gambatte.load(argv[1])) {
|
||||
printf("failed to load rom %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gambatte.setInputStateGetter(&inputGetter);
|
||||
|
||||
Sint16 *const sndBuffer = new Sint16[SND_BUF_SZ];
|
||||
memset(sndBuffer, 0, SND_BUF_SZ * sizeof(Sint16));
|
||||
SDL_AudioSpec spec;
|
||||
spec.freq = 48000;
|
||||
spec.format = AUDIO_S16SYS;
|
||||
spec.channels = 2;
|
||||
spec.samples = 1024;
|
||||
spec.callback = fill_buffer;
|
||||
spec.userdata = sndBuffer;
|
||||
|
||||
SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO);
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
|
||||
SDL_OpenAudio(&spec, NULL);
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
const unsigned samples = ((spec.freq * 4389) / 262144) + 2;
|
||||
uint16_t *const tmpBuf = new uint16_t[samples * 2];
|
||||
|
||||
Uint8 *keys = SDL_GetKeyState(NULL);
|
||||
|
||||
// gambatte.setVideoFilter(4);
|
||||
gambatte.setVideoBlitter(&blitter);
|
||||
|
||||
for (;;) {
|
||||
SDL_PumpEvents();
|
||||
|
||||
if (keys[SDLK_ESCAPE])
|
||||
break;
|
||||
|
||||
if (keys[SDLK_LCTRL] | keys[SDLK_RCTRL]) {
|
||||
if (keys[SDLK_f]) {
|
||||
blitter.toggleFullScreen();
|
||||
gambatte.videoBufferChange();
|
||||
}
|
||||
|
||||
if (keys[SDLK_r]) {
|
||||
gambatte.reset();
|
||||
}
|
||||
}
|
||||
|
||||
is.startButton = keys[SDLK_RETURN];
|
||||
is.selectButton = keys[SDLK_RSHIFT];
|
||||
is.bButton = keys[SDLK_c];
|
||||
is.aButton = keys[SDLK_d];
|
||||
is.dpadDown = keys[SDLK_DOWN];
|
||||
is.dpadUp = keys[SDLK_UP];
|
||||
is.dpadLeft = keys[SDLK_LEFT];
|
||||
is.dpadRight = keys[SDLK_RIGHT];
|
||||
|
||||
gambatte.runFor(70224);
|
||||
|
||||
if (!keys[SDLK_TAB]) {
|
||||
gambatte.fill_buffer(tmpBuf, samples);
|
||||
|
||||
while (rPos - wPos + (wPos > rPos ? SND_BUF_SZ : 0) >> 1 < samples)
|
||||
SDL_Delay(1);
|
||||
|
||||
SDL_LockAudio();
|
||||
|
||||
{
|
||||
const unsigned samples1 = std::min(SND_BUF_SZ - wPos >> 1, samples);
|
||||
const unsigned samples2 = samples - samples1;
|
||||
|
||||
memcpy(sndBuffer + wPos, tmpBuf, samples1 * 4);
|
||||
|
||||
if (samples2)
|
||||
memcpy(sndBuffer, tmpBuf + samples1 * 2, samples2 * 4);
|
||||
|
||||
if ((wPos += samples * 2) >= SND_BUF_SZ)
|
||||
wPos -= SND_BUF_SZ;
|
||||
}
|
||||
|
||||
SDL_UnlockAudio();
|
||||
|
||||
syncFunc();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_PauseAudio(1);
|
||||
SDL_CloseAudio();
|
||||
SDL_Quit();
|
||||
delete []sndBuffer;
|
||||
delete []tmpBuf;
|
||||
}
|
||||
|
||||
static void fill_buffer(void *const buffer, Uint8 *const stream, const int len) {
|
||||
const unsigned bytes1 = std::min(static_cast<unsigned>(len), (SND_BUF_SZ - rPos) * 2);
|
||||
const unsigned bytes2 = len - bytes1;
|
||||
|
||||
memcpy(stream, reinterpret_cast<Sint16*>(buffer) + rPos, bytes1);
|
||||
|
||||
if (bytes2)
|
||||
memcpy(stream + bytes1, buffer, bytes2);
|
||||
|
||||
if ((rPos += len >> 1) >= SND_BUF_SZ)
|
||||
rPos -= SND_BUF_SZ;
|
||||
}
|
Loading…
Reference in New Issue
Block a user