aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/gp2x/gp2x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/platform/gp2x/gp2x.cpp')
-rw-r--r--backends/platform/gp2x/gp2x.cpp248
1 files changed, 209 insertions, 39 deletions
diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp
index 5701a27c35..039f72e02f 100644
--- a/backends/platform/gp2x/gp2x.cpp
+++ b/backends/platform/gp2x/gp2x.cpp
@@ -31,16 +31,20 @@
#include "backends/platform/gp2x/gp2x-common.h"
#include "backends/platform/gp2x/gp2x-hw.h"
#include "backends/platform/gp2x/gp2x-mem.h"
+#include "common/archive.h"
#include "common/config-manager.h"
+
+#include "common/events.h"
+#include "common/util.h"
+
#include "common/debug.h"
#include "common/file.h"
-#include "common/util.h"
#include "base/main.h"
-#include "backends/saves/default/default-saves.h"
+#include "backends/saves/posix/posix-saves.h"
+
#include "backends/timer/default/default-timer.h"
#include "backends/plugins/posix/posix-provider.h"
-#include "backends/fs/posix/posix-fs-factory.h" // for getFilesystemFactory()
#include "sound/mixer_intern.h"
#include <stdio.h>
@@ -49,20 +53,18 @@
#include <limits.h>
#include <errno.h>
#include <sys/stat.h>
-#include <time.h> // for getTimeAndDate()
+#include <time.h> // for getTimeAndDate()
// Disable for normal serial logging.
#define DUMP_STDOUT
-#if defined(HAVE_CONFIG_H)
-#include "config.h"
-#endif
-
#define SAMPLES_PER_SEC 11025
//#define SAMPLES_PER_SEC 22050
//#define SAMPLES_PER_SEC 44100
+#define DEFAULT_CONFIG_FILE ".scummvmrc"
+#include "backends/fs/posix/posix-fs-factory.h"
static Uint32 timer_handler(Uint32 interval, void *param) {
((DefaultTimerManager *)param)->handler();
@@ -107,8 +109,6 @@ void OSystem_GP2X::initBackend() {
error("Could not initialize SDL: %s", SDL_GetError());
}
- SDL_ShowCursor(SDL_DISABLE);
-
// Setup default save path to be workingdir/saves
#ifndef PATH_MAX
#define PATH_MAX 255
@@ -192,6 +192,10 @@ void OSystem_GP2X::initBackend() {
setbuf(stderr, NULL); /* No buffering */
#endif // DUMP_STDOUT
+ _graphicsMutex = createMutex();
+
+ SDL_ShowCursor(SDL_DISABLE);
+
// Setup other defaults.
ConfMan.registerDefault("aspect_ratio", true);
@@ -200,14 +204,15 @@ void OSystem_GP2X::initBackend() {
ConfMan.registerDefault("speech_volume", 220);
ConfMan.registerDefault("autosave_period", 3 * 60); // Trigger autosave every 3 minutes - On low batts 4 mins is about your warning time.
- _graphicsMutex = createMutex();
+ memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
+ memset(&_videoMode, 0, sizeof(_videoMode));
+ memset(&_transactionDetails, 0, sizeof(_transactionDetails));
_cksumValid = false;
- _mode = GFX_NORMAL;
- _scaleFactor = 0;
+ _videoMode.mode = GFX_NORMAL;
+ _videoMode.scaleFactor = 1;
_scalerProc = Normal1x;
- _fullscreen = true;
- _adjustAspectRatio = ConfMan.getBool("aspect_ratio");
+ _videoMode.aspectRatio = ConfMan.getBool("aspect_ratio");
_scalerType = 0;
_modeFlags = 0;
_adjustZoomOnMouse = false;
@@ -221,7 +226,7 @@ void OSystem_GP2X::initBackend() {
// Create the savefile manager, if none exists yet (we check for this to
// allow subclasses to provide their own).
if (_savefile == 0) {
- _savefile = new DefaultSaveFileManager(savePath);
+ _savefile = new POSIXSaveFileManager();
}
// Create and hook up the mixer, if none exists yet (we check for this to
@@ -230,16 +235,21 @@ void OSystem_GP2X::initBackend() {
setupMixer();
}
+ // Setup the keymapper with backend's set of keys
+ // NOTE: must be done before creating TimerManager
+ // to avoid race conditions in creating EventManager
+ setupKeymapper();
+
// Create and hook up the timer manager, if none exists yet (we check for
// this to allow subclasses to provide their own).
if (_timer == 0) {
- // TODO: We could implement a custom SDLTimerManager by using
+ // Note: We could implement a custom SDLTimerManager by using
// SDL_AddTimer. That might yield better timer resolution, but it would
// also change the semantics of a timer: Right now, ScummVM timers
// *never* run in parallel, due to the way they are implemented. If we
// switched to SDL_AddTimer, each timer might run in a separate thread.
- // Unfortunately, not all our code is prepared for that, so we can't just
- // switch. But it's a long term goal to do just that!
+ // However, not all our code is prepared for that, so we can't just
+ // switch. Still, it's a potential future change to keep in mind.
_timer = new DefaultTimerManager();
_timerID = SDL_AddTimer(10, &timer_handler, _timer);
@@ -278,8 +288,7 @@ void OSystem_GP2X::initBackend() {
OSystem_GP2X::OSystem_GP2X()
:
_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
- _hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
- _tmpscreen(0), _overlayWidth(0), _overlayHeight(0),
+ _hwscreen(0), _screen(0), _tmpscreen(0),
_overlayVisible(false),
_overlayscreen(0), _tmpscreen2(0),
_samplesPerSec(0),
@@ -289,9 +298,15 @@ OSystem_GP2X::OSystem_GP2X()
_joystick(0),
_currentShakePos(0), _newShakePos(0),
_paletteDirtyStart(0), _paletteDirtyEnd(0),
+#ifdef MIXER_DOUBLE_BUFFERING
+ _soundMutex(0), _soundCond(0), _soundThread(0),
+ _soundThreadIsRunning(false), _soundThreadShouldQuit(false),
+#endif
+ _fsFactory(0),
_savefile(0),
_mixer(0),
_timer(0),
+ _screenIsLocked(false),
_graphicsMutex(0), _transactionMode(kTransactionNone) {
// allocate palette storage
@@ -305,11 +320,12 @@ OSystem_GP2X::OSystem_GP2X()
memset(&_mouseCurState, 0, sizeof(_mouseCurState));
_inited = false;
+ _fsFactory = new POSIXFilesystemFactory();
}
OSystem_GP2X::~OSystem_GP2X() {
SDL_RemoveTimer(_timerID);
- SDL_CloseAudio();
+ closeMixer();
free(_dirtyChecksums);
free(_currentPalette);
@@ -317,12 +333,13 @@ OSystem_GP2X::~OSystem_GP2X() {
free(_mouseData);
delete _savefile;
- delete _mixer;
delete _timer;
}
uint32 OSystem_GP2X::getMillis() {
- return SDL_GetTicks();
+ uint32 millis = SDL_GetTicks();
+ getEventManager()->processMillis(millis);
+ return millis;
}
void OSystem_GP2X::delayMillis(uint msecs) {
@@ -345,12 +362,54 @@ Common::SaveFileManager *OSystem_GP2X::getSavefileManager() {
}
FilesystemFactory *OSystem_GP2X::getFilesystemFactory() {
- return &POSIXFilesystemFactory::instance();
+ assert(_fsFactory);
+ return _fsFactory;
+}
+
+void OSystem_GP2X::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+
+#ifdef DATA_PATH
+ // Add the global DATA_PATH to the directory search list
+ // FIXME: We use depth = 4 for now, to match the old code. May want to change that
+ Common::FSNode dataNode(DATA_PATH);
+ if (dataNode.exists() && dataNode.isDirectory()) {
+ s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), priority);
+ }
+#endif
+
+#if defined(MACOSX) || defined(IPHONE)
+ // Get URL of the Resource directory of the .app bundle
+ CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
+ if (fileUrl) {
+ // Try to convert the URL to an absolute path
+ UInt8 buf[MAXPATHLEN];
+ if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) {
+ // Success: Add it to the search path
+ Common::String bundlePath((const char *)buf);
+ s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority);
+ }
+ CFRelease(fileUrl);
+ }
+
+#endif
+
+}
+
+static Common::String getDefaultConfigFileName() {
+ char configFile[MAXPATHLEN];
+ strcpy(configFile, DEFAULT_CONFIG_FILE);
+ return configFile;
+}
+
+Common::SeekableReadStream *OSystem_GP2X::createConfigReadStream() {
+ Common::FSNode file(getDefaultConfigFileName());
+ return file.createReadStream();
}
-//void OSystem_GP2X::setTimerCallback(TimerProc callback, int timer) {
-// SDL_SetTimer(timer, (SDL_TimerCallback) callback);
-//}
+Common::WriteStream *OSystem_GP2X::createConfigWriteStream() {
+ Common::FSNode file(getDefaultConfigFileName());
+ return file.createWriteStream();
+}
bool OSystem_GP2X::hasFeature(Feature f) {
return
@@ -387,10 +446,8 @@ bool OSystem_GP2X::getFeatureState(Feature f) {
switch (f) {
case kFeatureFullscreenMode:
return false;
- //case kFeatureFullscreenMode:
- // return _fullscreen;
case kFeatureAspectRatioCorrection:
- return _adjustAspectRatio;
+ return _videoMode.aspectRatio;
case kFeatureAutoComputeDirtyRects:
return _modeFlags & DF_WANT_RECT_OPTIM;
default:
@@ -408,7 +465,7 @@ void OSystem_GP2X::quit() {
GP2X_device_deinit();
SDL_RemoveTimer(_timerID);
- SDL_CloseAudio();
+ closeMixer();
free(_dirtyChecksums);
free(_currentPalette);
@@ -416,9 +473,8 @@ void OSystem_GP2X::quit() {
free(_mouseData);
delete _savefile;
- delete _mixer;
delete _timer;
-
+ SDL_ShowCursor(SDL_ENABLE);
SDL_Quit();
delete getEventManager();
@@ -446,20 +502,114 @@ void OSystem_GP2X::deleteMutex(MutexRef mutex) {
#pragma mark --- Audio ---
#pragma mark -
+#ifdef MIXER_DOUBLE_BUFFERING
+
+void OSystem_GP2X::mixerProducerThread() {
+ byte nextSoundBuffer;
+
+ SDL_LockMutex(_soundMutex);
+ while (true) {
+ // Wait till we are allowed to produce data
+ SDL_CondWait(_soundCond, _soundMutex);
+
+ if (_soundThreadShouldQuit)
+ break;
+
+ // Generate samples and put them into the next buffer
+ nextSoundBuffer = _activeSoundBuf ^ 1;
+ _mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
+
+ // Swap buffers
+ _activeSoundBuf = nextSoundBuffer;
+ }
+ SDL_UnlockMutex(_soundMutex);
+}
+
+int SDLCALL OSystem_GP2X::mixerProducerThreadEntry(void *arg) {
+ OSystem_GP2X *this_ = (OSystem_GP2X *)arg;
+ assert(this_);
+ this_->mixerProducerThread();
+ return 0;
+}
+
+
+void OSystem_GP2X::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) {
+ _soundThreadIsRunning = false;
+ _soundThreadShouldQuit = false;
+
+ // Create mutex and condition variable
+ _soundMutex = SDL_CreateMutex();
+ _soundCond = SDL_CreateCond();
+
+ // Create two sound buffers
+ _activeSoundBuf = 0;
+ _soundBufSize = bufSize;
+ _soundBuffers[0] = (byte *)calloc(1, bufSize);
+ _soundBuffers[1] = (byte *)calloc(1, bufSize);
+
+ _soundThreadIsRunning = true;
+
+ // Finally start the thread
+ _soundThread = SDL_CreateThread(mixerProducerThreadEntry, this);
+}
+
+void OSystem_GP2X::deinitThreadedMixer() {
+ // Kill thread?? _soundThread
+
+ if (_soundThreadIsRunning) {
+ // Signal the producer thread to end, and wait for it to actually finish.
+ _soundThreadShouldQuit = true;
+ SDL_CondBroadcast(_soundCond);
+ SDL_WaitThread(_soundThread, NULL);
+
+ // Kill the mutex & cond variables.
+ // Attention: AT this point, the mixer callback must not be running
+ // anymore, else we will crash!
+ SDL_DestroyMutex(_soundMutex);
+ SDL_DestroyCond(_soundCond);
+
+ _soundThreadIsRunning = false;
+
+ free(_soundBuffers[0]);
+ free(_soundBuffers[1]);
+ }
+}
+
+
+void OSystem_GP2X::mixCallback(void *arg, byte *samples, int len) {
+ OSystem_GP2X *this_ = (OSystem_GP2X *)arg;
+ assert(this_);
+ assert(this_->_mixer);
+
+ assert((int)this_->_soundBufSize == len);
+
+ // Lock mutex, to ensure our data is not overwritten by the producer thread
+ SDL_LockMutex(this_->_soundMutex);
+
+ // Copy data from the current sound buffer
+ memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
+
+ // Unlock mutex and wake up the produced thread
+ SDL_UnlockMutex(this_->_soundMutex);
+ SDL_CondSignal(this_->_soundCond);
+}
+
+#else
+
void OSystem_GP2X::mixCallback(void *sys, byte *samples, int len) {
OSystem_GP2X *this_ = (OSystem_GP2X *)sys;
assert(this_);
+ assert(this_->_mixer);
- if (this_->_mixer)
- this_->_mixer->mixCallback(samples, len);
+ this_->_mixer->mixCallback(samples, len);
}
+#endif
+
void OSystem_GP2X::setupMixer() {
SDL_AudioSpec desired;
SDL_AudioSpec obtained;
- //memset(&desired, 0, sizeof(desired));
-
// Determine the desired output sampling frequency.
_samplesPerSec = 0;
if (ConfMan.hasKey("output_rate"))
@@ -467,7 +617,6 @@ void OSystem_GP2X::setupMixer() {
if (_samplesPerSec <= 0)
_samplesPerSec = SAMPLES_PER_SEC;
-
//Quick EVIL Hack - DJWillis
_samplesPerSec = 11025;
@@ -507,10 +656,31 @@ void OSystem_GP2X::setupMixer() {
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
_mixer->setReady(true);
+
+#ifdef MIXER_DOUBLE_BUFFERING
+ initThreadedMixer(_mixer, obtained.samples * 4);
+#endif
+
+ // start the sound system
SDL_PauseAudio(0);
}
}
+void OSystem_GP2X::closeMixer() {
+ if (_mixer)
+ _mixer->setReady(false);
+
+ SDL_CloseAudio();
+
+ delete _mixer;
+ _mixer = 0;
+
+#ifdef MIXER_DOUBLE_BUFFERING
+ deinitThreadedMixer();
+#endif
+
+}
+
Audio::Mixer *OSystem_GP2X::getMixer() {
assert(_mixer);
return _mixer;