Cleanup of the GP2X backend. It's been sat on my HDD for a while and it really should be in SVN.

svn-id: r36278
This commit is contained in:
John Willis 2009-02-12 09:52:31 +00:00
parent 5f634212aa
commit 521cc08911
7 changed files with 725 additions and 421 deletions

View File

@ -27,8 +27,7 @@ cp ../../../../README ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../COPYING ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../COPYRIGHT ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../NEWS ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../gui/themes/modern.ini ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../gui/themes/modern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../gui/themes/scummmodern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../dists/pred.dic ./scummvm-gp2x-`date '+%Y-%m-%d'`/
cp ../../../../dists/engine-data/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data

View File

@ -30,6 +30,7 @@
#include "backends/platform/gp2x/gp2x-common.h"
#include "backends/platform/gp2x/gp2x-hw.h"
#include "backends/keymapper/keymapper.h"
#include "common/util.h"
#include "common/events.h"
@ -90,9 +91,9 @@ void OSystem_GP2X::fillMouseEvent(Common::Event &event, int x, int y) {
// Adjust for the screen scaling
if (!_overlayVisible) {
event.mouse.x /= _scaleFactor;
event.mouse.y /= _scaleFactor;
if (_adjustAspectRatio)
event.mouse.x /= _videoMode.scaleFactor;
event.mouse.y /= _videoMode.scaleFactor;
if (_videoMode.aspectRatio)
event.mouse.y = aspect2Real(event.mouse.y);
}
}
@ -161,7 +162,7 @@ void OSystem_GP2X::handleKbdMouse() {
_km.y_down_count = 1;
}
SDL_WarpMouse(_km.x, _km.y);
SDL_WarpMouse((Uint16)_km.x, (Uint16)_km.y);
}
}
}
@ -257,7 +258,6 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) {
if (_modeChanged) {
_modeChanged = false;
event.type = Common::EVENT_SCREEN_CHANGED;
_screenChangeCount++;
return true;
}
@ -593,3 +593,62 @@ bool OSystem_GP2X::remapKey(SDL_Event &ev,Common::Event &event) {
return false;
}
void OSystem_GP2X::setupKeymapper() {
#ifdef ENABLE_KEYMAPPER
using namespace Common;
Keymapper *mapper = getEventManager()->getKeymapper();
HardwareKeySet *keySet = new HardwareKeySet();
keySet->addHardwareKey(new HardwareKey( "a", KeyState(KEYCODE_a), "a", kActionKeyType ));
keySet->addHardwareKey(new HardwareKey( "s", KeyState(KEYCODE_s), "s", kActionKeyType ));
keySet->addHardwareKey(new HardwareKey( "d", KeyState(KEYCODE_d), "d", kActionKeyType ));
keySet->addHardwareKey(new HardwareKey( "f", KeyState(KEYCODE_f), "f", kActionKeyType ));
keySet->addHardwareKey(new HardwareKey( "n", KeyState(KEYCODE_n), "n (vk)", kTriggerLeftKeyType, kVirtualKeyboardActionType ));
keySet->addHardwareKey(new HardwareKey( "m", KeyState(KEYCODE_m), "m (remap)", kTriggerRightKeyType, kKeyRemapActionType ));
keySet->addHardwareKey(new HardwareKey( "[", KeyState(KEYCODE_LEFTBRACKET), "[ (select)", kSelectKeyType ));
keySet->addHardwareKey(new HardwareKey( "]", KeyState(KEYCODE_RIGHTBRACKET), "] (start)", kStartKeyType ));
mapper->registerHardwareKeySet(keySet);
Keymap *globalMap = new Keymap("global");
Keymap *guiMap = new Keymap("gui");
Action *act;
Event evt ;
act = new Action(globalMap, "MENU", "Menu", kGenericActionType, kSelectKeyType);
act->addKeyEvent(KeyState(KEYCODE_F5, ASCII_F5, 0));
act = new Action(globalMap, "SKCT", "Skip", kGenericActionType, kActionKeyType);
act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
act = new Action(globalMap, "PAUS", "Pause", kGenericActionType, kStartKeyType);
act->addKeyEvent(KeyState(KEYCODE_SPACE, ' ', 0));
act = new Action(globalMap, "SKLI", "Skip line", kGenericActionType, kActionKeyType);
act->addKeyEvent(KeyState(KEYCODE_PERIOD, '.', 0));
act = new Action(globalMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType);
act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0));
act = new Action(globalMap, "REMP", "Remap keys", kKeyRemapActionType);
act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
mapper->addGlobalKeymap(globalMap);
act = new Action(guiMap, "CLOS", "Close", kGenericActionType, kStartKeyType);
act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
act = new Action(guiMap, "CLIK", "Mouse click");
act->addLeftClickEvent();
act = new Action(guiMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType);
act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0));
act = new Action(guiMap, "REMP", "Remap keys", kKeyRemapActionType);
act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
mapper->addGlobalKeymap(guiMap);
mapper->pushKeymap("global");
#endif
}

View File

@ -26,21 +26,21 @@
#ifndef GP2X_COMMON_H
#define GP2X_COMMON_H
#define __GP2X__
#define USE_OSD
#include <SDL.h>
#include <SDL_gp2x.h>
#include "backends/base-backend.h"
#include "graphics/scaler.h"
#include <SDL.h>
#include <SDL_gp2x.h>
#define __GP2X__
#define USE_OSD
/* #define DISABLE_SCALERS */
#define MIXER_DOUBLE_BUFFERING 1
namespace Audio {
class MixerImpl;
}
//#define DISABLE_SCALERS
enum {
GFX_NORMAL = 0,
GFX_DOUBLESIZE = 1,
@ -65,11 +65,12 @@ public:
virtual void initBackend();
void beginGFXTransaction(void);
void endGFXTransaction(void);
TransactionError endGFXTransaction(void);
// Set the size of the video bitmap.
// Typically, 320x200
void initSize(uint w, uint h);
int getScreenChangeID() const { return _screenChangeCount; }
// Set colors of the palette
@ -106,7 +107,7 @@ public:
void disableCursorPalette(bool disable) {
_cursorPaletteDisabled = disable;
blitCursor();
};
}
// Shaking is used in SCUMM. Set current shake position.
void setShakePos(int shake_pos);
@ -121,9 +122,15 @@ public:
// Returns true if an event was retrieved.
virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
// Sets up the keymapper with the backends hardware key set
void setupKeymapper();
// Set function that generates samples
void setupMixer();
static void mixCallback(void *s, byte *samples, int len);
void closeMixer();
virtual Audio::Mixer *getMixer();
// Poll CD status
@ -152,6 +159,7 @@ public:
void deleteMutex(MutexRef mutex);
// Overlay
Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
void showOverlay();
void hideOverlay();
void clearOverlay();
@ -159,8 +167,8 @@ public:
void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
int16 getHeight();
int16 getWidth();
int16 getOverlayHeight() { return _overlayHeight; }
int16 getOverlayWidth() { return _overlayWidth; }
int16 getOverlayHeight() { return _videoMode.overlayHeight; }
int16 getOverlayWidth() { return _videoMode.overlayWidth; }
const GraphicsMode *getSupportedGraphicsModes() const;
int getDefaultGraphicsMode() const;
@ -176,6 +184,11 @@ public:
void displayMessageOnOSD(const char *msg);
virtual Common::SaveFileManager *getSavefileManager();
virtual FilesystemFactory *getFilesystemFactory();
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
virtual Common::SeekableReadStream *createConfigReadStream();
virtual Common::WriteStream *createConfigWriteStream();
protected:
bool _inited;
@ -195,7 +208,6 @@ protected:
// unseen game screen
SDL_Surface *_screen;
int _screenWidth, _screenHeight;
// temporary screen (for scalers)
SDL_Surface *_tmpscreen;
@ -203,8 +215,8 @@ protected:
// overlay
SDL_Surface *_overlayscreen;
int _overlayWidth, _overlayHeight;
bool _overlayVisible;
Graphics::PixelFormat _overlayFormat;
// Audio
int _samplesPerSec;
@ -215,42 +227,44 @@ protected:
uint32 _cdEndTime, _cdStopTime;
enum {
DF_WANT_RECT_OPTIM = 1 << 0,
DF_UPDATE_EXPAND_1_PIXEL = 1 << 1
DF_WANT_RECT_OPTIM = 1 << 0
};
enum {
kTransactionNone = 0,
kTransactionCommit = 1,
kTransactionActive = 2
kTransactionActive = 1,
kTransactionRollback = 2
};
struct TransactionDetails {
int mode;
bool modeChanged;
int w;
int h;
bool sizeChanged;
bool fs;
bool fsChanged;
bool ar;
bool arChanged;
bool needHotswap;
bool needUpdatescreen;
bool needUnload;
bool needToggle;
bool normal1xScaler;
};
TransactionDetails _transactionDetails;
struct VideoState {
bool setup;
bool fullscreen;
bool aspectRatio;
int mode;
int scaleFactor;
int screenWidth, screenHeight;
int overlayWidth, overlayHeight;
};
VideoState _videoMode, _oldVideoMode;
virtual void setGraphicsModeIntern(); // overloaded by CE backend
/** Force full redraw on next updateScreen */
bool _forceFull;
ScalerProc *_scalerProc;
int _scalerType;
int _scaleFactor;
int _mode;
int _transactionMode;
bool _fullscreen;
bool _screenIsLocked;
Graphics::Surface _framebuffer;
@ -352,32 +366,50 @@ protected:
*/
MutexRef _graphicsMutex;
Common::SaveFileManager *_savefile;
FilesystemFactory *getFilesystemFactory();
#ifdef MIXER_DOUBLE_BUFFERING
SDL_mutex *_soundMutex;
SDL_cond *_soundCond;
SDL_Thread *_soundThread;
bool _soundThreadIsRunning;
bool _soundThreadShouldQuit;
byte _activeSoundBuf;
uint _soundBufSize;
byte *_soundBuffers[2];
void mixerProducerThread();
static int SDLCALL mixerProducerThreadEntry(void *arg);
void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize);
void deinitThreadedMixer();
#endif
FilesystemFactory *_fsFactory;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
SDL_TimerID _timerID;
Common::TimerManager *_timer;
protected:
void addDirtyRgnAuto(const byte *buf);
void makeChecksums(const byte *buf);
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false);
void drawMouse();
virtual void undrawMouse();
virtual void blitCursor();
void undrawMouse();
void blitCursor();
/** Set the position of the virtual mouse cursor. */
void setMousePos(int x, int y);
void fillMouseEvent(Common::Event &event, int x, int y);
void toggleMouseGrab();
void internUpdateScreen();
void loadGFXMode();
bool loadGFXMode();
void unloadGFXMode();
void hotswapGFXMode();
bool hotswapGFXMode();
void setFullscreenMode(bool enable);
void setAspectRatioCorrection(bool enable);
@ -386,7 +418,10 @@ protected:
bool saveScreenshot(const char *filename);
int effectiveScreenHeight() const { return (_adjustAspectRatio ? 240 : _screenHeight) * _scaleFactor; }
int effectiveScreenHeight() const {
return (_videoMode.aspectRatio ? real2Aspect(_videoMode.screenHeight) : _videoMode.screenHeight)
* _videoMode.scaleFactor;
}
void setupIcon();
void handleKbdMouse();

View File

@ -213,60 +213,3 @@ void gp2x_video_wait_vsync(void)
MEM_REG[0x2846>>1]=(MEM_REG[0x2846>>1] | 0x20) & ~2;
while (!(MEM_REG[0x2846>>1] & 2));
}
//char GP2X_get_battery_level() {
// Returns string of level in English for use in displayMessageOnOSD() to show battery level.
//
//if (gp2x_dev[1] == -1)
//{
// warning("Error occured getting voltage status");
// return "Unable to read battery level.";
//}
//
//int i;
//int battval;
//unsigned short cbv;
//int v;
//
//battval = 0;
//for (i = 0; i < 1000; i ++)
//{
// if (read (gp2x_dev[1], &cbv, 2) == 2)
// battval += cbv;
// if (gp2x_joystick_read() & GP2X_START)
// {
// needexit = 1;
// break;
// }
//}
//if (needexit) break;
//
//battval /= 1000;
// Do a very rough translation
//if (battval > 1016) v = 37;
//else if (battval > 974) v = 33;
//else if (battval > 943) v = 32;
//else if (battval > 915) v = 31;
//else if (battval > 896) v = 30;
//else if (battval > 837) v = 29;
//else if (battval > 815) v = 28;
//else if (battval > 788) v = 27;
//else if (battval > 745) v = 26;
//else if (battval > 708) v = 25;
//else if (battval > 678) v = 24;
//else if (battval > 649) v = 23;
//else if (battval > 605) v = 22;
//else if (battval > 573) v = 21;
//else if (battval > 534) v = 20;
//else if (battval > 496) v = 19;
//else if (battval > 448) v = 18;
//else v = 17;
//gp2x_printf (NULL, 0, 0, "Voltage: ~%d.%dV (%s)", v/10, v%10, v>26?"Battery Full" : v>24?"Battery Medium" : "Battery Empty");
//gp2x_video_RGB_flip(0);
//}
//close (gp2x_dev[1]);
//return "Voltage: ~%d.%dV (%s)", v/10, v%10, v>26?"Battery Full" : v>24?"Battery Medium" : "Battery Empty";
//}

View File

@ -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::setTimerCallback(TimerProc callback, int timer) {
// SDL_SetTimer(timer, (SDL_TimerCallback) callback);
//}
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();
}
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;

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,16 @@
MODULE := backends/platform/gp2x
MODULE_OBJS := \
gp2x-hw.o \
gp2x-mem.o \
gp2x-hw.o \
gp2x-mem.o \
events.o \
graphics.o \
gp2x.o
# gp2x-options.o
# overload_help.o
gp2x.o \
# gp2x-options.o \
# overload_help.o \
MODULE_DIRS += \
backends/platform/gp2x/
# We don't use the common.rules here on purpose
# We don't use the rules.mk here on purpose
OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)