aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
Diffstat (limited to 'backends')
-rw-r--r--backends/fs/psp/psp-stream.cpp291
-rw-r--r--backends/fs/psp/psp-stream.h32
-rw-r--r--backends/module.mk1
-rw-r--r--backends/platform/ds/arm7/source/main.cpp4
-rw-r--r--backends/platform/ds/arm9/makefile2
-rw-r--r--backends/platform/ds/arm9/source/dsmain.cpp4
-rw-r--r--backends/platform/ds/commoninclude/NDS/scummvm_ipc.h12
-rw-r--r--backends/platform/gp2x/graphics.cpp5
-rw-r--r--backends/platform/gp2xwiz/gp2xwiz-graphics.cpp5
-rw-r--r--backends/platform/linuxmoto/linuxmoto-graphics.cpp5
-rw-r--r--backends/platform/ps2/Makefile.ps291
-rw-r--r--backends/platform/ps2/elf32.h209
-rw-r--r--backends/platform/ps2/main_prog.ld97
-rw-r--r--backends/platform/ps2/module.mk3
-rw-r--r--backends/platform/ps2/plugin.ld214
-rw-r--r--backends/platform/ps2/plugin.syms8
-rw-r--r--backends/platform/ps2/ps2loader.cpp721
-rw-r--r--backends/platform/ps2/ps2loader.h137
-rw-r--r--backends/platform/ps2/systemps2.cpp6
-rw-r--r--backends/platform/psp/Makefile9
-rw-r--r--backends/platform/psp/audio.cpp181
-rw-r--r--backends/platform/psp/audio.h69
-rw-r--r--backends/platform/psp/display_client.cpp15
-rw-r--r--backends/platform/psp/display_manager.cpp3
-rw-r--r--backends/platform/psp/module.mk5
-rw-r--r--backends/platform/psp/mp3.cpp487
-rw-r--r--backends/platform/psp/mp3.h121
-rw-r--r--backends/platform/psp/osys_psp.cpp45
-rw-r--r--backends/platform/psp/osys_psp.h4
-rw-r--r--backends/platform/psp/psp.spec2
-rw-r--r--backends/platform/psp/psp_main.cpp3
-rw-r--r--backends/platform/psp/thread.h56
-rw-r--r--backends/platform/samsungtv/main.cpp2
-rw-r--r--backends/platform/sdl/graphics.cpp5
-rw-r--r--backends/platform/sdl/main.cpp2
-rw-r--r--backends/platform/sdl/sdl.cpp8
-rw-r--r--backends/platform/sdl/sdl.h2
-rw-r--r--backends/plugins/ps2/ps2-provider.cpp108
-rw-r--r--backends/plugins/ps2/ps2-provider.h (renamed from backends/platform/psp/thread.cpp)47
-rw-r--r--backends/saves/default/default-saves.cpp4
40 files changed, 1721 insertions, 1304 deletions
diff --git a/backends/fs/psp/psp-stream.cpp b/backends/fs/psp/psp-stream.cpp
index 9bcbe9d7cf..8cb7dfea17 100644
--- a/backends/fs/psp/psp-stream.cpp
+++ b/backends/fs/psp/psp-stream.cpp
@@ -32,48 +32,28 @@
#include <errno.h>
-#define MIN2(a,b) ((a < b) ? a : b)
-#define MIN3(a,b,c) ( (a < b) ? (a < c ? a : c) : (b < c ? b : c) )
-
-//#define __PSP_PRINT_TO_FILE__ /* For debugging suspend stuff, we have no screen output */
-//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+//#define __PSP_PRINT_TO_FILE__
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
-
#include "backends/platform/psp/trace.h"
-//#define DEBUG_BUFFERS /* to see the contents of the buffers being read */
-
-#ifdef DEBUG_BUFFERS
-void printBuffer(byte *ptr, uint32 len) {
- uint32 printLen = len <= 10 ? len : 10;
-
- for (int i = 0; i < printLen; i++) {
- PSP_INFO_PRINT("%x ", ptr[i]);
- }
-
- if (len > 10) {
- PSP_INFO_PRINT("... ");
- for (int i = len - 10; i < len; i++)
- PSP_INFO_PRINT("%x ", ptr[i]);
- }
-
- PSP_INFO_PRINT("\n");
-}
-#endif
-
-
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
- : StdioStream((void *)1), _path(path), _writeMode(writeMode),
- _ferror(false), _pos(0),
- _physicalPos(0), _fileSize(0), _inCache(false), _eos(false),
- _cacheStartOffset(-1), _cache(0),
- _errorSuspend(0), _errorSource(0),
- _errorPos(0), _errorHandle(0), _suspendCount(0) {
+ : StdioStream((void *)1), _path(path), _writeMode(writeMode) {
DEBUG_ENTER_FUNC();
- // assert(!path.empty()); // do we need this?
+ assert(!path.empty());
_handle = (void *)0; // Need to do this since base class asserts not 0.
+ _ferror = false;
+ _feof = false;
+ _pos = 0;
+
+ /* for error checking */
+ _errorSuspend = 0;
+ _errorSource = 0;
+ _errorPos = 0;
+ _errorHandle = 0;
+ _suspendCount = 0;
}
PSPIoStream::~PSPIoStream() {
@@ -83,12 +63,9 @@ PSPIoStream::~PSPIoStream() {
PSP_DEBUG_PRINT_FUNC("Suspended\n");
PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
- // Must do this before fclose() or resume() will reopen.
+ // Must do this before fclose() or resume() will reopen.
- fclose((FILE *)_handle); // We don't need a critical section. Worst case, the handle gets closed on its own
-
- if (_cache)
- free(_cache);
+ fclose((FILE *)_handle); // We don't need a critical section(?). Worst case, the handle gets closed on its own
PowerMan.endCriticalSection();
}
@@ -105,16 +82,6 @@ void *PSPIoStream::open() {
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
- if (_handle) {
- // Get the file size
- fseek((FILE *)_handle, 0, SEEK_END); // go to the end
- _fileSize = ftell((FILE *)_handle);
- fseek((FILE *)_handle, 0, SEEK_SET); // back to the beginning
-
- // Allocate the cache
- _cache = (char *)memalign(64, CACHE_SIZE);
- }
-
PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
PowerMan.endCriticalSection();
@@ -124,183 +91,100 @@ void *PSPIoStream::open() {
bool PSPIoStream::err() const {
DEBUG_ENTER_FUNC();
-
- if (_ferror) // We dump since no printing to screen with suspend
- PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], \
- _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
- _ferror, _errorSource, _errorSuspend, _pos,
- _errorPos, _errorHandle, _suspendCount);
+ if (_ferror)
+ PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
+ _ferror, _errorSource, _errorSuspend, _pos, _errorPos, _errorHandle, _suspendCount);
return _ferror;
}
void PSPIoStream::clearErr() {
- _ferror = false;
+ _ferror = false; // Remove regular error bit
}
bool PSPIoStream::eos() const {
- return _eos;
+ return _feof;
}
int32 PSPIoStream::pos() const {
return _pos;
}
+
int32 PSPIoStream::size() const {
- return _fileSize;
+ DEBUG_ENTER_FUNC();
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSP_DEBUG_PRINT_FUNC("Suspended\n");
+
+ fseek((FILE *)_handle, 0, SEEK_END);
+ int32 length = ftell((FILE *)_handle);
+ fseek((FILE *)_handle, _pos, SEEK_SET);
+
+ if (_pos < 0 || length < 0) { // Check for errors
+ _errorSource = 2;
+ PSP_ERROR("pos[%d] or length[%d] < 0!\n", _pos, length);
+ _ferror = true;
+ length = -1; // If our oldPos is bad, we want length to be bad too to signal
+ clearerr((FILE *)_handle);
+ }
+
+ PowerMan.endCriticalSection();
+
+ return length;
}
bool PSPIoStream::seek(int32 offs, int whence) {
DEBUG_ENTER_FUNC();
- PSP_DEBUG_PRINT_FUNC("offset[0x%x], whence[%d], _pos[0x%x], _physPos[0x%x]\n", offs, whence, _pos, _physicalPos);
- _eos = false;
-
- int32 posToSearchFor = 0;
- switch (whence) {
- case SEEK_CUR:
- posToSearchFor = _pos;
- break;
- case SEEK_END:
- posToSearchFor = _fileSize; // unsure. Does it take us here or to EOS - 1?
- break;
- }
- posToSearchFor += offs;
-
- // Check for bad values
- if (posToSearchFor < 0) {
- _ferror = true;
- return false;
- }
-
- if (posToSearchFor > _fileSize) {
+
+ // Check if we can access the file
+ if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ PSP_DEBUG_PRINT_FUNC("Suspended\n");
+
+ int ret = fseek((FILE *)_handle, offs, whence);
+
+ if (ret != 0) {
_ferror = true;
- _eos = true;
- return false;
+ PSP_ERROR("fseek returned with [%d], non-zero\n", ret);
+ clearerr((FILE *)_handle);
+ _feof = feof((FILE *)_handle);
+ _errorSource = 3;
+ } else { // everything ok
+ _feof = false; // Reset eof flag since we know it was ok
}
-
- // See if we can find it in cache
- if (isOffsetInCache(posToSearchFor)) {
- PSP_DEBUG_PRINT("seek offset[0x%x] found in cache. Cache starts[0x%x]\n", posToSearchFor, _cacheStartOffset);
- _inCache = true;
- } else { // not in cache
- _inCache = false;
- }
- _pos = posToSearchFor;
- return true;
+
+ _pos = ftell((FILE *)_handle); // update pos
+
+ PowerMan.endCriticalSection();
+
+ return (ret == 0);
}
uint32 PSPIoStream::read(void *ptr, uint32 len) {
DEBUG_ENTER_FUNC();
- PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x], ptr[%p]\n", _path.c_str(), len, ptr);
-
- if (_ferror || _eos)
- return 0;
-
- byte *destPtr = (byte *)ptr;
- uint32 lenFromFile = len; // how much we read from the actual file
- uint32 lenFromCache = 0; // how much we read from cache
- uint32 lenRemainingInFile = _fileSize - _pos;
-
- if (lenFromFile > lenRemainingInFile) {
- lenFromFile = lenRemainingInFile;
- _eos = true;
- }
-
- // Are we in cache?
- if (_inCache && isCacheValid()) {
- uint32 offsetInCache = _pos - _cacheStartOffset;
- // We can read at most what's in the cache or the remaining size of the file
- lenFromCache = MIN2(lenFromFile, CACHE_SIZE - offsetInCache); // unsure
-
- PSP_DEBUG_PRINT("reading 0x%x bytes from cache to %p. pos[0x%x] physPos[0x%x] cacheStart[0x%x]\n", lenFromCache, destPtr, _pos, _physicalPos, _cacheStartOffset);
-
- memcpy(destPtr, &_cache[offsetInCache], lenFromCache);
- _pos += lenFromCache;
-
- if (lenFromCache < lenFromFile) { // there's more to copy from the file
- lenFromFile -= lenFromCache;
- lenRemainingInFile -= lenFromCache; // since we moved pos
- destPtr += lenFromCache;
- } else { // we're done
-#ifdef DEBUG_BUFFERS
- printBuffer((byte *)ptr, len);
-#endif
-
- return lenFromCache; // how much we actually read
- }
- }
-
+ // Check if we can access the file
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSP_DEBUG_PRINT_FUNC("Suspended\n");
-
-
- synchronizePhysicalPos(); // we need to update our physical position
-
- if (lenFromFile <= MIN_READ_SIZE) { // We load the cache in case the read is small enough
- // This optimization is based on the principle that reading 1 byte is as expensive as 1000 bytes
- uint32 lenToCopyToCache = MIN2((uint32)MIN_READ_SIZE, lenRemainingInFile); // at most remaining file size
-
- PSP_DEBUG_PRINT("filling cache with 0x%x bytes from physicalPos[0x%x]. cacheStart[0x%x], pos[0x%x], fileSize[0x%x]\n", lenToCopyToCache, _physicalPos, _cacheStartOffset, _pos, _fileSize);
-
- size_t ret = fread(_cache, 1, lenToCopyToCache, (FILE *)_handle);
- if (ret != lenToCopyToCache) {
- PSP_ERROR("in filling cache, failed to get 0x%x bytes. Only got 0x%x\n", lenToCopyToCache, ret);
- _ferror = true;
- clearerr((FILE *)_handle);
- }
- _cacheStartOffset = _physicalPos;
- _inCache = true;
-
- _physicalPos += ret;
-
- PSP_DEBUG_PRINT("copying 0x%x bytes from cache to %p\n", lenFromFile, destPtr);
-
- // Copy to the destination buffer from cache
- memcpy(destPtr, _cache, lenFromFile);
- _pos += lenFromFile;
-
- } else { // Too big for cache. No caching
- PSP_DEBUG_PRINT("reading 0x%x bytes from file to %p. Pos[0x%x], physPos[0x%x]\n", lenFromFile, destPtr, _pos, _physicalPos);
- size_t ret = fread(destPtr, 1, lenFromFile, (FILE *)_handle);
-
- _physicalPos += ret; // Update pos
- _pos = _physicalPos;
-
- if (ret != lenFromFile) { // error
- PSP_ERROR("fread returned [0x%x] instead of len[0x%x]\n", ret, lenFromFile);
+
+ PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
+
+ size_t ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
+
+ _pos += ret; // Update pos
+
+ if (ret != len) { // Check for eof
+ _feof = feof((FILE *)_handle);
+ if (!_feof) { // It wasn't an eof. Must be an error
_ferror = true;
clearerr((FILE *)_handle);
- _errorSource = 4;
+ _pos = ftell((FILE *)_handle); // Update our position
+ _errorSource = 4;
+ PSP_ERROR("fread returned ret[%d] instead of len[%d]\n", ret, len);
}
- _inCache = false;
}
PowerMan.endCriticalSection();
-#ifdef DEBUG_BUFFERS
- printBuffer((byte *)ptr, len);
-#endif
-
- return lenFromCache + lenFromFile; // total of what was copied
-}
-
-// TODO: Test if seeking backwards/forwards has any effect on performance
-inline bool PSPIoStream::synchronizePhysicalPos() {
- if (_pos != _physicalPos) {
- if (fseek((FILE *)_handle, _pos - _physicalPos, SEEK_CUR) != 0)
- return false;
- _physicalPos = _pos;
- }
-
- return true;
-}
-
-inline bool PSPIoStream::isOffsetInCache(uint32 offset) {
- if (_cacheStartOffset != -1 &&
- offset >= (uint32)_cacheStartOffset &&
- offset < (uint32)(_cacheStartOffset + CACHE_SIZE))
- return true;
- return false;
+ return ret;
}
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
@@ -309,30 +193,18 @@ uint32 PSPIoStream::write(const void *ptr, uint32 len) {
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
PSP_DEBUG_PRINT_FUNC("Suspended\n");
- PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x]\n", _path.c_str(), len);
+ PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
- if (_ferror)
- return 0;
-
- _eos = false; // we can't have eos with write
- synchronizePhysicalPos();
-
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
- // If we're making the file bigger, adjust the size
- if (_physicalPos + (int)ret > _fileSize)
- _fileSize = _physicalPos + ret;
- _physicalPos += ret;
- _pos = _physicalPos;
- _inCache = false;
- _cacheStartOffset = -1; // invalidate cache
+ _pos += ret;
if (ret != len) { // Set error
_ferror = true;
clearerr((FILE *)_handle);
_pos = ftell((FILE *)_handle); // Update pos
_errorSource = 5;
- PSP_ERROR("fwrite returned[0x%x] instead of len[0x%x]\n", ret, len);
+ PSP_ERROR("fwrite returned[%d] instead of len[%d]\n", ret, len);
}
PowerMan.endCriticalSection();
@@ -352,7 +224,7 @@ bool PSPIoStream::flush() {
_ferror = true;
clearerr((FILE *)_handle);
_errorSource = 6;
- PSP_ERROR("fflush returned ret[%d]\n", ret);
+ PSP_ERROR("fflush returned ret[%u]\n", ret);
}
PowerMan.endCriticalSection();
@@ -414,9 +286,6 @@ int PSPIoStream::resume() {
// Resume our previous position
if (_handle > 0 && _pos > 0) {
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
-
- _physicalPos = _pos;
- _inCache = false;
if (ret != 0) { // Check for problem
_errorSuspend = ResumeError;
diff --git a/backends/fs/psp/psp-stream.h b/backends/fs/psp/psp-stream.h
index 9fd1ad0470..673630b685 100644
--- a/backends/fs/psp/psp-stream.h
+++ b/backends/fs/psp/psp-stream.h
@@ -35,39 +35,25 @@
*/
class PSPIoStream : public StdioStream, public Suspendable {
protected:
- Common::String _path;
- int _fileSize;
- bool _writeMode; // for resuming in the right mode
- int _physicalPos; // position in the real file
- int _pos; // position. Sometimes virtual
- bool _inCache; // whether we're in cache (virtual) mode
- bool _eos; // EOS flag
-
+ Common::String _path; /* Need to maintain for reopening after suspend */
+ bool _writeMode; /* "" */
+ int _pos; /* "" */
+ mutable int _ferror; /* Save file ferror */
+ mutable bool _feof; /* and eof */
+
enum {
SuspendError = 2,
ResumeError = 3
};
- enum {
- CACHE_SIZE = 1024,
- MIN_READ_SIZE = 1024 // reading less than 1024 takes exactly the same time as 1024
- };
-
- // For caching
- char *_cache;
- int _cacheStartOffset; // starting offset of the cache. -1 when cache is invalid
-
- mutable int _ferror; // file error state
- int _errorSuspend; // for debugging
+ int _errorSuspend;
mutable int _errorSource;
+
+ // Error checking
int _errorPos;
void * _errorHandle;
int _suspendCount;
- bool synchronizePhysicalPos(); // synchronize the physical and virtual positions
- bool isOffsetInCache(uint32 pos); // check if an offset is found in cache
- bool isCacheValid() { return _cacheStartOffset != -1; }
-
public:
/**
diff --git a/backends/module.mk b/backends/module.mk
index 59df56b468..46c9e166a6 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -35,6 +35,7 @@ MODULE_OBJS := \
plugins/sdl/sdl-provider.o \
plugins/win32/win32-provider.o \
plugins/psp/psp-provider.o \
+ plugins/ps2/ps2-provider.o \
saves/savefile.o \
saves/default/default-saves.o \
saves/posix/posix-saves.o \
diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp
index a4cde02ba6..7029d96405 100644
--- a/backends/platform/ds/arm7/source/main.cpp
+++ b/backends/platform/ds/arm7/source/main.cpp
@@ -38,7 +38,7 @@
#include <system.h>
#include <stdlib.h>
#include <string.h>
-#include <registers_alt.h> // Needed for SOUND_CR
+//#include <registers_alt.h> // not needed in current libnds
#include <NDS/scummvm_ipc.h>
//////////////////////////////////////////////////////////////////////
#ifdef USE_DEBUGGER
@@ -590,7 +590,7 @@ int main(int argc, char ** argv) {
IPC->reset = false;
- //fifoInit();
+ fifoInit();
for (int r = 0; r < 8; r++) {
IPC->adpcm.arm7Buffer[r] = (u8 *) malloc(512);
diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile
index 7f03f4c310..eca170ef96 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -75,7 +75,7 @@ else
ifdef DS_BUILD_K
else
- # USE_MAD = 1
+ USE_MAD = 1
endif
endif
endif
diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp
index 5a63e5f08f..7eb02f9070 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.cpp
@@ -702,7 +702,7 @@ void displayMode8Bit() {
- consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true, true);
+ consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true);
// Set this again because consoleinit resets it
videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
@@ -940,7 +940,7 @@ void displayMode16Bit() {
SUB_BG0_CR = BG_MAP_BASE(4) | BG_TILE_BASE(0);
SUB_BG0_Y0 = 0;
- consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false, true);
+ consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false);
// consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(4), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
for (int r = 0; r < 32 * 32; r++) {
diff --git a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h
index f41548f400..9344be68f9 100644
--- a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h
+++ b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h
@@ -33,18 +33,6 @@
//////////////////////////////////////////////////////////////////////
-typedef struct sTransferSoundData {
-//---------------------------------------------------------------------------------
- const void *data;
- u32 len;
- u32 rate;
- u8 vol;
- u8 pan;
- u8 format;
- u8 PADDING;
-} TransferSoundData, * pTransferSoundData;
-
-
//---------------------------------------------------------------------------------
diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp
index 4a3c668c52..1888cbe47c 100644
--- a/backends/platform/gp2x/graphics.cpp
+++ b/backends/platform/gp2x/graphics.cpp
@@ -1405,6 +1405,7 @@ void OSystem_GP2X::drawMouse() {
SDL_Rect zoomdst;
SDL_Rect dst;
int scale;
+ int width, height;
int hotX, hotY;
int tmpScreenWidth, tmpScreenHeight;
@@ -1425,12 +1426,16 @@ void OSystem_GP2X::drawMouse() {
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
dst.w = _mouseCurState.vW;
dst.h = _mouseCurState.vH;
hotX = _mouseCurState.vHotX;
hotY = _mouseCurState.vHotY;
} else {
scale = 1;
+ width = _videoMode.overlayWidth;
+ height = _videoMode.overlayHeight;
dst.w = _mouseCurState.rW;
dst.h = _mouseCurState.rH;
hotX = _mouseCurState.rHotX;
diff --git a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp b/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp
index 6abddd52f3..ff3bd725be 100644
--- a/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp
+++ b/backends/platform/gp2xwiz/gp2xwiz-graphics.cpp
@@ -149,6 +149,7 @@ void OSystem_GP2XWIZ::drawMouse() {
SDL_Rect dst;
int scale;
+ int width, height;
int hotX, hotY;
if (_videoMode.mode == GFX_HALF && !_overlayVisible){
@@ -161,12 +162,16 @@ void OSystem_GP2XWIZ::drawMouse() {
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
dst.w = _mouseCurState.vW;
dst.h = _mouseCurState.vH;
hotX = _mouseCurState.vHotX;
hotY = _mouseCurState.vHotY;
} else {
scale = 1;
+ width = _videoMode.overlayWidth;
+ height = _videoMode.overlayHeight;
dst.w = _mouseCurState.rW;
dst.h = _mouseCurState.rH;
hotX = _mouseCurState.rHotX;
diff --git a/backends/platform/linuxmoto/linuxmoto-graphics.cpp b/backends/platform/linuxmoto/linuxmoto-graphics.cpp
index a39416ebc4..d66d41dfab 100644
--- a/backends/platform/linuxmoto/linuxmoto-graphics.cpp
+++ b/backends/platform/linuxmoto/linuxmoto-graphics.cpp
@@ -168,6 +168,7 @@ void OSystem_LINUXMOTO::drawMouse() {
SDL_Rect dst;
int scale;
+ int width, height;
int hotX, hotY;
if (_videoMode.mode == GFX_HALF && !_overlayVisible) {
@@ -180,12 +181,16 @@ void OSystem_LINUXMOTO::drawMouse() {
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
dst.w = _mouseCurState.vW;
dst.h = _mouseCurState.vH;
hotX = _mouseCurState.vHotX;
hotY = _mouseCurState.vHotY;
} else {
scale = 1;
+ width = _videoMode.overlayWidth;
+ height = _videoMode.overlayHeight;
dst.w = _mouseCurState.rW;
dst.h = _mouseCurState.rH;
hotX = _mouseCurState.rHotX;
diff --git a/backends/platform/ps2/Makefile.ps2 b/backends/platform/ps2/Makefile.ps2
index bf7ac0aca0..d6ebc9bfc8 100644
--- a/backends/platform/ps2/Makefile.ps2
+++ b/backends/platform/ps2/Makefile.ps2
@@ -1,39 +1,52 @@
# $Header: Exp $
include $(PS2SDK)/Defs.make
-PS2_EXTRA = /works/devel/ps2/sdk-extra
+PS2_EXTRA = /home/tony/GSOC/ps2/sdk-extra
PS2_EXTRA_INCS = /zlib/include /libmad/ee/include /SjPcm/ee/src /tremor
-PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /tremor/tremor
+PS2_EXTRA_LIBS = /zlib/lib /libmad/ee/lib /SjPcm/ee/lib /vorbis /tremor/tremor
-ENABLED=STATIC_PLUGIN
+# Set to 1 to enable, 0 to disable dynamic modules
+DYNAMIC_MODULES = 1
+
+VERBOSE_BUILD=0
+
+# Test for dynamic plugins
+ifeq ($(DYNAMIC_MODULES),1)
+ENABLED = DYNAMIC_PLUGIN
+DEFINES += -DDYNAMIC_MODULES
+PRE_OBJS_FLAGS = -Wl,--whole-archive
+POST_OBJS_FLAGS = -Wl,--no-whole-archive
+else
+ENABLED = STATIC_PLUGIN
+endif
ENABLE_SCUMM = $(ENABLED)
-ENABLE_SCUMM_7_8 = $(ENABLED)
-ENABLE_HE = $(ENABLED)
+#ENABLE_SCUMM_7_8 = $(ENABLED)
+#ENABLE_HE = $(ENABLED)
ENABLE_AGI = $(ENABLED)
-ENABLE_AGOS = $(ENABLED)
-ENABLE_CINE = $(ENABLED)
-ENABLE_CRUISE = $(ENABLED)
-ENABLE_DRASCULA = $(ENABLED)
-ENABLE_GOB = $(ENABLED)
-ENABLE_KYRA = $(ENABLED)
-ENABLE_LURE = $(ENABLED)
+#ENABLE_AGOS = $(ENABLED)
+#ENABLE_CINE = $(ENABLED)
+#ENABLE_CRUISE = $(ENABLED)
+#ENABLE_DRASCULA = $(ENABLED)
+#ENABLE_GOB = $(ENABLED)
+#ENABLE_KYRA = $(ENABLED)
+#ENABLE_LURE = $(ENABLED)
# ENABLE_M4 = $(ENABLED)
-ENABLE_MADE = $(ENABLED)
-ENABLE_PARALLACTION = $(ENABLED)
-ENABLE_QUEEN = $(ENABLED)
-ENABLE_SAGA = $(ENABLED)
-ENABLE_SAGA2 = $(ENABLED)
-ENABLE_IHNM = $(ENABLED)
-ENABLE_SKY = $(ENABLED)
-ENABLE_SWORD1 = $(ENABLED)
-ENABLE_SWORD2 = $(ENABLED)
+#ENABLE_MADE = $(ENABLED)
+#ENABLE_PARALLACTION = $(ENABLED)
+#ENABLE_QUEEN = $(ENABLED)
+#ENABLE_SAGA = $(ENABLED)
+#ENABLE_SAGA2 = $(ENABLED)
+#ENABLE_IHNM = $(ENABLED)
+#ENABLE_SKY = $(ENABLED)
+#ENABLE_SWORD1 = $(ENABLED)
+#ENABLE_SWORD2 = $(ENABLED)
# ENABLE_TINSEL = $(ENABLED)
-ENABLE_TOUCHE = $(ENABLED)
+#ENABLE_TOUCHE = $(ENABLED)
HAVE_GCC3 = true
-CC = ee-gcc
+CC = ee-gcc
CXX = ee-g++
AS = ee-gcc
LD = ee-gcc
@@ -46,15 +59,21 @@ RM = rm -f
srcdir = ../../..
VPATH = $(srcdir)
INCDIR = ../../../
-# DEPDIR = .deps
+DEPDIR = .deps
+CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP
-DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_ZLIB -DFORCE_RTL -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar
+# Variables for dynamic plugin building
+PLUGIN_PREFIX =
+PLUGIN_SUFFIX = .plg
+PLUGIN_EXTRA_DEPS = plugin.syms elf/scummvm.elf
+PLUGIN_LDFLAGS = -nostartfiles -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -Wl,-q,--just-symbols=elf/scummvm.org.elf,-Tlinkfile,--retain-symbols-file,plugin.syms -lstdc++ -lc
+DEFINES = -DUSE_VORBIS -DUSE_MAD -DUSE_TREMOR -DUSE_ZLIB -DFORCE_RTL -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar -fno-exceptions -fno-rtti
-INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS))
+INCLUDES = $(addprefix -I$(PS2_EXTRA),$(PS2_EXTRA_INCS))
INCLUDES += -I $(PS2SDK)/ee/include -I $(PS2SDK)/common/include -I ./common -I . -I $(srcdir) -I $(srcdir)/engines
-TARGET = elf/scummvm.elf
+TARGET = elf/scummvm
OBJS := backends/platform/ps2/DmaPipe.o \
backends/platform/ps2/Gs2dScreen.o \
@@ -71,20 +90,20 @@ OBJS := backends/platform/ps2/DmaPipe.o \
backends/platform/ps2/systemps2.o \
backends/platform/ps2/ps2mutex.o \
backends/platform/ps2/ps2time.o \
- backends/platform/ps2/ps2debug.o
+ backends/platform/ps2/ps2debug.o \
+ backends/platform/ps2/ps2loader.o
MODULE_DIRS += .
include $(srcdir)/Makefile.common
-LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T $(PS2SDK)/ee/startup/linkfile
-LDFLAGS += -L $(PS2SDK)/ee/lib -L .
+LDFLAGS += -mno-crt0 $(PS2SDK)/ee/startup/crt0.o -T main_prog.ld #$(PS2SDK)/ee/startup/linkfile
+LDFLAGS += -G 0 -L $(PS2SDK)/ee/lib -L .
LDFLAGS += $(addprefix -L$(PS2_EXTRA),$(PS2_EXTRA_LIBS))
-LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++
-LDFLAGS += -s
-
-all: $(TARGET)
+LDFLAGS += -lmc -lpad -lmouse -lhdd -lpoweroff -lsjpcm -lmad -ltremor -lz -lm -lc -lfileXio -lkernel -lstdc++
+LDFLAGS +=
-$(TARGET): $(OBJS)
- $(LD) $^ $(LDFLAGS) -o $@
+all: $(TARGET).elf
+$(TARGET).elf: $(OBJS)
+ $(LD) $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LDFLAGS) -o $@
diff --git a/backends/platform/ps2/elf32.h b/backends/platform/ps2/elf32.h
new file mode 100644
index 0000000000..616cc4b4d2
--- /dev/null
+++ b/backends/platform/ps2/elf32.h
@@ -0,0 +1,209 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef BACKENDS_ELF_H
+#define BACKENDS_ELF_H
+
+/* ELF stuff */
+
+typedef unsigned short Elf32_Half, Elf32_Section;
+typedef unsigned int Elf32_Word, Elf32_Addr, Elf32_Off;
+typedef signed int Elf32_Sword;
+typedef Elf32_Half Elf32_Versym;
+
+#define EI_NIDENT (16)
+#define SELFMAG 6
+
+/* ELF File format structures. Look up ELF structure for more details */
+
+// ELF header (contains info about the file)
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+} Elf32_Ehdr;
+
+// Should be in e_ident
+#define ELFMAG "\177ELF\1\1" /* ELF Magic number */
+
+// e_type values
+#define ET_NONE 0 /* no file type */
+#define ET_REL 1 /* relocatable */
+#define ET_EXEC 2 /* executable */
+#define ET_DYN 3 /* shared object */
+#define ET_CORE 4 /* core file */
+
+// e_machine values
+#define EM_MIPS 8
+
+
+// Program header (contains info about segment)
+typedef struct {
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+} Elf32_Phdr;
+
+// p_type values
+#define PT_NULL 0 /* ignored */
+#define PT_LOAD 1 /* loadable segment */
+#define PT_DYNAMIC 2 /* dynamic linking info */
+#define PT_INTERP 3 /* info about interpreter */
+#define PT_NOTE 4 /* note segment */
+#define PT_SHLIB 5 /* reserved */
+#define PT_PHDR 6 /* Program header table */
+#define PT_MIPS_REGINFO 0x70000000 /* register usage info */
+
+// p_flags value
+#define PF_X 1 /* execute */
+#define PF_W 2 /* write */
+#define PF_R 4 /* read */
+
+// Section header (contains info about section)
+typedef struct {
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+} Elf32_Shdr;
+
+// sh_type values
+#define SHT_NULL 0 /* Inactive section */
+#define SHT_PROGBITS 1 /* Proprietary */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addend */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Info for dynamic linking */
+#define SHT_NOTE 7 /* Note section */
+#define SHT_NOBITS 8 /* Occupies no space */
+#define SHT_REL 9 /* Relocation entries without addend */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Minimal set of dynamic linking symbols */
+#define SHT_MIPS_LIBLSIT 0x70000000 /* Info about dynamic shared object libs */
+#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicts btw executables and shared objects */
+#define SHT_MIPS_GPTAB 0x70000003 /* Global pointer table */
+
+// sh_flags values
+#define SHF_WRITE 0 /* writable section */
+#define SHF_ALLOC 2 /* section occupies memory */
+#define SHF_EXECINSTR 4 /* machine instructions */
+#define SHF_MIPS_GPREL 0x10000000 /* Must be made part of global data area */
+
+
+// Symbol entry (contain info about a symbol)
+typedef struct {
+ Elf32_Word st_name; /* Symbol name (string tbl index) */
+ Elf32_Addr st_value; /* Symbol value */
+ Elf32_Word st_size; /* Symbol size */
+ unsigned char st_info; /* Symbol type and binding */
+ unsigned char st_other; /* Symbol visibility */
+ Elf32_Section st_shndx; /* Section index */
+} Elf32_Sym;
+
+// Extract from the st_info
+#define SYM_TYPE(x) ((x)&0xF)
+#define SYM_BIND(x) ((x)>>4)
+
+
+// Symbol binding values from st_info
+#define STB_LOCAL 0 /* Symbol not visible outside object */
+#define STB_GLOBAL 1 /* Symbol visible to all object files */
+#define STB_WEAK 2 /* Similar to STB_GLOBAL */
+
+// Symbol type values from st_info
+#define STT_NOTYPE 0 /* Not specified */
+#define STT_OBJECT 1 /* Data object e.g. variable */
+#define STT_FUNC 2 /* Function */
+#define STT_SECTION 3 /* Section */
+#define STT_FILE 4 /* Source file associated with object file */
+
+// Special section header index values from st_shndex
+#define SHN_UNDEF 0
+#define SHN_LOPROC 0xFF00 /* Extended values */
+#define SHN_ABS 0xFFF1 /* Absolute value: don't relocate */
+#define SHN_COMMON 0xFFF2 /* Common block. Not allocated yet */
+#define SHN_HIPROC 0xFF1F
+#define SHN_HIRESERVE 0xFFFF
+
+// Relocation entry (info about how to relocate)
+typedef struct {
+ Elf32_Addr r_offset; /* Address */
+ Elf32_Word r_info; /* Relocation type and symbol index */
+} Elf32_Rel;
+
+// Access macros for the relocation info
+#define REL_TYPE(x) ((x)&0xFF) /* Extract relocation type */
+#define REL_INDEX(x) ((x)>>8) /* Extract relocation index into symbol table */
+
+// MIPS relocation types
+#define R_MIPS_NONE 0
+#define R_MIPS_16 1
+#define R_MIPS_32 2
+#define R_MIPS_REL32 3
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_LO16 6
+#define R_MIPS_GPREL16 7
+#define R_MIPS_LITERAL 8
+#define R_MIPS_GOT16 9
+#define R_MIPS_PC16 10
+#define R_MIPS_CALL16 11
+#define R_MIPS_GPREL32 12
+#define R_MIPS_GOTHI16 13
+#define R_MIPS_GOTLO16 14
+#define R_MIPS_CALLHI16 15
+#define R_MIPS_CALLLO16 16
+
+// Mock function to get value of global pointer
+#define getGP() ({ \
+ unsigned int __valgp; \
+ __asm__ ("add %0, $gp, $0" : "=r"(__valgp) : ); \
+ __valgp; \
+})
+
+#endif /* BACKENDS_ELF_H */
diff --git a/backends/platform/ps2/main_prog.ld b/backends/platform/ps2/main_prog.ld
new file mode 100644
index 0000000000..de4b534135
--- /dev/null
+++ b/backends/platform/ps2/main_prog.ld
@@ -0,0 +1,97 @@
+ENTRY(_start);
+
+SECTIONS {
+ .text 0x00100000: {
+ _ftext = . ;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t*)
+ KEEP(*(.init))
+ KEEP(*(.fini))
+ QUAD(0)
+ }
+
+ PROVIDE(_etext = .);
+ PROVIDE(etext = .);
+
+ .reginfo : { *(.reginfo) }
+
+ /* Global/static constructors and deconstructors. */
+ .ctors ALIGN(16): {
+ KEEP(*crtbegin*.o(.ctors))
+ KEEP(*(EXCLUDE_FILE(*crtend*.o) .ctors))
+ KEEP(*(SORT(.ctors.*)))
+ KEEP(*(.ctors))
+ }
+ .dtors ALIGN(16): {
+ KEEP(*crtbegin*.o(.dtors))
+ KEEP(*(EXCLUDE_FILE(*crtend*.o) .dtors))
+ KEEP(*(SORT(.dtors.*)))
+ KEEP(*(.dtors))
+ }
+
+ /* Static data. */
+ .rodata ALIGN(128): {
+ *(.rodata)
+ *(.rodata.*)
+ *(.gnu.linkonce.r*)
+ }
+
+ .data ALIGN(128): {
+ _fdata = . ;
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d*)
+ SORT(CONSTRUCTORS)
+ }
+
+ .rdata ALIGN(128): { *(.rdata) }
+ .gcc_except_table ALIGN(128): { *(.gcc_except_table) }
+
+ _gp = ALIGN(128) + 0x7ff0;
+ .lit4 ALIGN(128): { *(.lit4) }
+ .lit8 ALIGN(128): { *(.lit8) }
+
+ .sdata ALIGN(128): {
+ *(.sdata)
+ *(.sdata.*)
+ *(.gnu.linkonce.s*)
+ }
+
+ _edata = .;
+ PROVIDE(edata = .);
+
+ /* Uninitialized data. */
+ .sbss ALIGN(128) : {
+ _fbss = . ;
+ *(.sbss)
+ *(.sbss.*)
+ *(.gnu.linkonce.sb*)
+ *(.scommon)
+ }
+
+ __plugin_hole_start = .;
+ . = _gp + 0x7ff0;
+ __plugin_hole_end = .;
+
+ COMMON :
+ {
+ *(COMMON)
+ }
+ . = ALIGN(128);
+
+ .bss ALIGN(128) : {
+ *(.bss)
+ *(.bss.*)
+ *(.gnu.linkonce.b*)
+ }
+ _end_bss = .;
+
+ _end = . ;
+ PROVIDE(end = .);
+
+ /* Symbols needed by crt0.s. */
+ PROVIDE(_heap_size = -1);
+ PROVIDE(_stack = -1);
+ PROVIDE(_stack_size = 128 * 1024);
+}
diff --git a/backends/platform/ps2/module.mk b/backends/platform/ps2/module.mk
index 86b12cb668..69a28b93c4 100644
--- a/backends/platform/ps2/module.mk
+++ b/backends/platform/ps2/module.mk
@@ -16,7 +16,8 @@ MODULE_OBJS := \
systemps2.o \
ps2mutex.o \
ps2time.o \
- ps2debug.o
+ ps2debug.o \
+ ps2loader.o
MODULE_DIRS += \
backends/platform/ps2/
diff --git a/backends/platform/ps2/plugin.ld b/backends/platform/ps2/plugin.ld
new file mode 100644
index 0000000000..d6ca6dcfe6
--- /dev/null
+++ b/backends/platform/ps2/plugin.ld
@@ -0,0 +1,214 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips",
+ "elf32-littlemips")
+OUTPUT_ARCH(mips:5900)
+SEARCH_DIR("/home/tony/GSOC/ps2/tools/ee/ee/lib");
+PHDRS
+{
+ plugin PT_LOAD ;
+ shorts PT_LOAD ;
+}
+/* Do we need any of these for elf?
+ __DYNAMIC = 0;
+_DYNAMIC_LINK = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x100000;
+ .interp : { *(.interp) } : plugin
+ .reginfo : { *(.reginfo) } : plugin
+ .dynamic : { *(.dynamic) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.dyn :
+ {
+ *(.rel.init)
+ *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+ *(.rel.fini)
+ *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+ *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+ *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+ *(.rel.ctors)
+ *(.rel.dtors)
+ *(.rel.got)
+ *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*)
+ *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*)
+ *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*)
+ *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*)
+ *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+ }
+ .rela.dyn :
+ {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+ *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+ *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+ *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0
+ .plt : { *(.plt) }
+ .text :
+ {
+ _ftext = . ;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.mips16.fn.*) *(.mips16.call.*)
+ } =0
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) }
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN(128) + (. & (128 - 1));
+ /* Ensure the __preinit_array_start label is properly aligned. We
+ could instead move the label definition inside the section, but
+ the linker would then create the section even if it turns out to
+ be empty, which isn't pretty. */
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+ .data :
+ {
+ _fdata = . ;
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .eh_frame : { KEEP (*(.eh_frame)) }
+ .gcc_except_table : { *(.gcc_except_table) }
+ .dynamic : { *(.dynamic) }
+ .ctors :
+ {
+ ___plugin_ctors = .;
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ __plugin_ctors_end = .;
+ }
+ .dtors :
+ {
+ ___plugin_dtors = .;
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ ___plugin_dtors_end = .;
+ }
+ .jcr : { KEEP (*(.jcr)) }
+
+ . = __plugin_hole_start;
+
+ .got : { *(.got.plt) *(.got) } : shorts
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata :
+ {
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ _fbss = .;
+ .sbss :
+ {
+ PROVIDE (__sbss_start = .);
+ PROVIDE (___sbss_start = .);
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ PROVIDE (__sbss_end = .);
+ PROVIDE (___sbss_end = .);
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(32 / 8);
+ }
+ . = ALIGN(32 / 8);
+ _end = .;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+
+ /* Symbols needed by crt0.s */
+ PROVIDE(_heap_size = -1);
+ PROVIDE(_stack = -1);
+ PROVIDE(_stack_size = 128 * 1024);
+}
diff --git a/backends/platform/ps2/plugin.syms b/backends/platform/ps2/plugin.syms
new file mode 100644
index 0000000000..24ee1a19dc
--- /dev/null
+++ b/backends/platform/ps2/plugin.syms
@@ -0,0 +1,8 @@
+PLUGIN_getVersion
+PLUGIN_getType
+PLUGIN_getTypeVersion
+PLUGIN_getObject
+___plugin_ctors
+___plugin_ctors_end
+___plugin_dtors
+___plugin_dtors_end
diff --git a/backends/platform/ps2/ps2loader.cpp b/backends/platform/ps2/ps2loader.cpp
new file mode 100644
index 0000000000..bea697bf07
--- /dev/null
+++ b/backends/platform/ps2/ps2loader.cpp
@@ -0,0 +1,721 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <sys/_default_fcntl.h>
+
+#include <ps2utils.h>
+
+#include "backends/platform/ps2/ps2loader.h"
+//#include "backends/platform/ps2/powerman.h" //TODO
+
+//#define __PS2_DEBUG_PLUGINS__
+
+#ifdef __PS2_DEBUG_PLUGINS__
+#define DBG(x,...) fprintf(stderr,x, ## __VA_ARGS__)
+#else
+#define DBG(x,...)
+#endif
+
+#define seterror(x,...) fprintf(stderr,x, ## __VA_ARGS__)
+
+extern char __plugin_hole_start; // Indicates start of hole in program file for shorts
+extern char __plugin_hole_end; // Indicates end of hole in program file
+extern char _gp[]; // Value of gp register
+
+DECLARE_SINGLETON(ShortSegmentManager) // For singleton
+
+// Get rid of symbol table in memory
+void DLObject::discard_symtab() {
+ free(_symtab);
+ free(_strtab);
+ _symtab = NULL;
+ _strtab = NULL;
+ _symbol_cnt = 0;
+}
+
+// Unload all objects from memory
+void DLObject::unload() {
+ discard_symtab();
+ free(_segment);
+ _segment = NULL;
+
+ if (_shortsSegment) {
+ ShortsMan.deleteSegment(_shortsSegment);
+ _shortsSegment = NULL;
+ }
+}
+
+/**
+ * Follow the instruction of a relocation section.
+ *
+ * @param fd File Descriptor
+ * @param offset Offset into the File
+ * @param size Size of relocation section
+ * @param relSegment Base address of relocated segment in memory (memory offset)
+ *
+ */
+bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) {
+ Elf32_Rel *rel = NULL; // relocation entry
+
+ // Allocate memory for relocation table
+ if (!(rel = (Elf32_Rel *)malloc(size))) {
+ seterror("Out of memory.");
+ return false;
+ }
+
+ // Read in our relocation table
+ if (lseek(fd, offset, SEEK_SET) < 0 ||
+ read(fd, rel, size) != (ssize_t)size) {
+ seterror("Relocation table load failed.");
+ free(rel);
+ return false;
+ }
+
+ // Treat each relocation entry. Loop over all of them
+ int cnt = size / sizeof(*rel);
+
+ DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
+
+ bool seenHi16 = false; // For treating HI/LO16 commands
+ int firstHi16 = -1; // Mark the point of the first hi16 seen
+ Elf32_Addr ahl = 0; // Calculated addend
+ int a = 0; // Addend: taken from the target
+
+ unsigned int *lastTarget = 0; // For processing hi16 when lo16 arrives
+ unsigned int relocation = 0;
+ int debugRelocs[10] = {0}; // For debugging
+ int extendedHi16 = 0; // Count extended hi16 treatments
+ Elf32_Addr lastHiSymVal = 0;
+ bool hi16InShorts = false;
+
+#define DEBUG_NUM 2
+
+ // Loop over relocation entries
+ for (int i = 0; i < cnt; i++) {
+ // Get the symbol this relocation entry is referring to
+ Elf32_Sym *sym = (Elf32_Sym *)(_symtab) + (REL_INDEX(rel[i].r_info));
+
+ // Get the target instruction in the code
+ unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset);
+
+ unsigned int origTarget = *target; // Save for debugging
+
+ // Act differently based on the type of relocation
+ switch (REL_TYPE(rel[i].r_info)) {
+
+ case R_MIPS_HI16: // Absolute addressing.
+ if (sym->st_shndx < SHN_LOPROC && // Only shift for plugin section (ie. has a real section index)
+ firstHi16 < 0) { // Only process first in block of HI16s
+ firstHi16 = i; // Keep the first Hi16 we saw
+ seenHi16 = true;
+ ahl = (*target & 0xffff) << 16; // Take lower 16 bits shifted up
+
+ lastHiSymVal = sym->st_value;
+ hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments
+ if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number
+ DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n",
+ i, rel[i].r_offset, ahl, *target);
+ }
+ break;
+
+ case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it
+ if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index)
+ if (!seenHi16) { // We MUST have seen HI16 first
+ seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i);
+ free(rel);
+ return false;
+ }
+
+ // Fix: bug in gcc makes LO16s connect to wrong HI16s sometimes (shorts and regular segment)
+ // Note that we can check the entire shorts segment because the executable's shorts don't belong to this plugin section
+ // and will be screened out above
+ bool lo16InShorts = ShortsMan.inGeneralSegment((char *)sym->st_value);
+
+ // Correct the bug by getting the proper value in ahl (taken from the current symbol)
+ if ((hi16InShorts && !lo16InShorts) || (!hi16InShorts && lo16InShorts)) {
+ ahl -= (lastHiSymVal & 0xffff0000); // We assume gcc meant the same offset
+ ahl += (sym->st_value & 0xffff0000);
+ }
+
+ ahl &= 0xffff0000; // Clean lower 16 bits for repeated LO16s
+ a = *target & 0xffff; // Take lower 16 bits of the target
+ a = (a << 16) >> 16; // Sign extend them
+ ahl += a; // Add lower 16 bits. AHL is now complete
+
+ // Fix: we can have LO16 access to the short segment sometimes
+ if (lo16InShorts) {
+ relocation = ahl + _shortsSegment->getOffset(); // Add in the short segment offset
+ } else // It's in the regular segment
+ relocation = ahl + (Elf32_Addr)_segment; // Add in the new offset for the segment
+
+ if (firstHi16 >= 0) { // We haven't treated the HI16s yet so do it now
+ for (int j = firstHi16; j < i; j++) {
+ if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16) continue; // Skip over non-Hi16s
+
+ lastTarget = (unsigned int *)((char *)relSegment + rel[j].r_offset); // get hi16 target
+ *lastTarget &= 0xffff0000; // Clear the lower 16 bits of the last target
+ *lastTarget |= (relocation >> 16) & 0xffff; // Take the upper 16 bits of the relocation
+ if (relocation & 0x8000)(*lastTarget)++; // Subtle: we need to add 1 to the HI16 in this case
+ }
+ firstHi16 = -1; // Reset so we'll know we treated it
+ } else {
+ extendedHi16++;
+ }
+
+ *target &= 0xffff0000; // Clear the lower 16 bits of current target
+ *target |= relocation & 0xffff; // Take the lower 16 bits of the relocation
+
+ if (debugRelocs[1]++ < DEBUG_NUM)
+ DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
+ i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
+ if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
+ DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
+ i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
+ }
+ break;
+
+ case R_MIPS_26: // Absolute addressing (for jumps and branches only)
+ if (sym->st_shndx < SHN_LOPROC) { // Only relocate for main segment
+ a = *target & 0x03ffffff; // Get 26 bits' worth of the addend
+ a = (a << 6) >> 6; // Sign extend a
+ relocation = ((a << 2) + (Elf32_Addr)_segment) >> 2; // a already points to the target. Subtract our offset
+ *target &= 0xfc000000; // Clean lower 26 target bits
+ *target |= (relocation & 0x03ffffff);
+
+ if (debugRelocs[3]++ < DEBUG_NUM)
+ DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
+ i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
+ } else {
+ if (debugRelocs[4]++ < DEBUG_NUM)
+ DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
+ i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
+ }
+ break;
+
+ case R_MIPS_GPREL16: // GP Relative addressing
+ if (_shortsSegment->getOffset() != 0 && // Only relocate if we shift the shorts section
+ ShortsMan.inGeneralSegment((char *)sym->st_value)) { // Only relocate things in the plugin hole
+ a = *target & 0xffff; // Get 16 bits' worth of the addend
+ a = (a << 16) >> 16; // Sign extend it
+
+ relocation = a + _shortsSegment->getOffset();
+
+ *target &= 0xffff0000; // Clear the lower 16 bits of the target
+ *target |= relocation & 0xffff;
+
+ if (debugRelocs[5]++ < DEBUG_NUM)
+ DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n",
+ i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
+ }
+
+ break;
+
+ case R_MIPS_32: // Absolute addressing
+ if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section.
+ a = *target; // Get full 32 bits of addend
+
+ if (ShortsMan.inGeneralSegment((char *)sym->st_value)) // Check if we're in the shorts segment
+ relocation = a + _shortsSegment->getOffset(); // Shift by shorts offset
+ else // We're in the main section
+ relocation = a + (Elf32_Addr)_segment; // Shift by main offset
+ *target = relocation;
+
+ if (debugRelocs[6]++ < DEBUG_NUM)
+ DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
+ }
+ break;
+
+ default:
+ seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i);
+ free(rel);
+ return false;
+ }
+ }
+
+ DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16);
+
+ free(rel);
+ return true;
+}
+
+bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) {
+ // Start reading the elf header. Check for errors
+ if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr) ||
+ memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || // Check MAGIC
+ ehdr->e_type != ET_EXEC || // Check for executable
+ ehdr->e_machine != EM_MIPS || // Check for MIPS machine type
+ ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header
+ ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header
+ seterror("Invalid file type.");
+ return false;
+ }
+
+ DBG("phoff = %d, phentsz = %d, phnum = %d\n",
+ ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum);
+
+ return true;
+}
+
+bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num) {
+ // Read program header
+ if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 ||
+ read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) {
+ seterror("Program header load failed.");
+ return false;
+ }
+
+ // Check program header values
+ if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) {
+ seterror("Invalid program header.");
+ return false;
+ }
+
+ DBG("offs = %x, filesz = %x, memsz = %x, align = %x\n",
+ phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align);
+
+ return true;
+
+}
+
+bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) {
+
+ char *baseAddress = 0;
+
+ // We need to take account of non-allocated segment for shorts
+ if (phdr->p_flags & PF_X) { // This is a relocated segment
+
+ // Attempt to allocate memory for segment
+ int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here
+ DBG("extra mem is %x\n", extra);
+
+ if (phdr->p_align < 0x10000) phdr->p_align = 0x10000; // Fix for wrong alignment on e.g. AGI
+
+ if (!(_segment = (char *)memalign(phdr->p_align, phdr->p_memsz + extra))) {
+ seterror("Out of memory.\n");
+ return false;
+ }
+ DBG("allocated segment @ %p\n", _segment);
+
+ // Get offset to load segment into
+ baseAddress = (char *)_segment + phdr->p_vaddr;
+ _segmentSize = phdr->p_memsz + extra;
+ } else { // This is a shorts section.
+ _shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr);
+
+ baseAddress = _shortsSegment->getStart();
+ DBG("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n",
+ _shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset());
+
+ }
+
+ // Set bss segment to 0 if necessary (assumes bss is at the end)
+ if (phdr->p_memsz > phdr->p_filesz) {
+ DBG("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz);
+ memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
+ }
+ // Read the segment into memory
+ if (lseek(fd, phdr->p_offset, SEEK_SET) < 0 ||
+ read(fd, baseAddress, phdr->p_filesz) != (ssize_t)phdr->p_filesz) {
+ seterror("Segment load failed.");
+ return false;
+ }
+
+ return true;
+}
+
+
+Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) {
+
+ Elf32_Shdr *shdr = NULL;
+
+ // Allocate memory for section headers
+ if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) {
+ seterror("Out of memory.");
+ return NULL;
+ }
+
+ // Read from file into section headers
+ if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0 ||
+ read(fd, shdr, ehdr->e_shnum * sizeof(*shdr)) !=
+ (ssize_t)(ehdr->e_shnum * sizeof(*shdr))) {
+ seterror("Section headers load failed.");
+ return NULL;
+ }
+
+ return shdr;
+}
+
+int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+
+ // Loop over sections, looking for symbol table linked to a string table
+ for (int i = 0; i < ehdr->e_shnum; i++) {
+ //DBG("Section %d: type = %x, size = %x, entsize = %x, link = %x\n",
+ // i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link);
+
+ if (shdr[i].sh_type == SHT_SYMTAB &&
+ shdr[i].sh_entsize == sizeof(Elf32_Sym) &&
+ shdr[i].sh_link < ehdr->e_shnum &&
+ shdr[shdr[i].sh_link].sh_type == SHT_STRTAB &&
+ _symtab_sect < 0) {
+ _symtab_sect = i;
+ }
+ }
+
+ // Check for no symbol table
+ if (_symtab_sect < 0) {
+ seterror("No symbol table.");
+ return -1;
+ }
+
+ DBG("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size);
+
+ // Allocate memory for symbol table
+ if (!(_symtab = malloc(shdr[_symtab_sect].sh_size))) {
+ seterror("Out of memory.");
+ return -1;
+ }
+
+ // Read symbol table into memory
+ if (lseek(fd, shdr[_symtab_sect].sh_offset, SEEK_SET) < 0 ||
+ read(fd, _symtab, shdr[_symtab_sect].sh_size) !=
+ (ssize_t)shdr[_symtab_sect].sh_size) {
+ seterror("Symbol table load failed.");
+ return -1;
+ }
+
+ // Set number of symbols
+ _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym);
+ DBG("Loaded %d symbols.\n", _symbol_cnt);
+
+ return _symtab_sect;
+
+}
+
+bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) {
+
+ int string_sect = shdr[_symtab_sect].sh_link;
+
+ // Allocate memory for string table
+ if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) {
+ seterror("Out of memory.");
+ return false;
+ }
+
+ // Read string table into memory
+ if (lseek(fd, shdr[string_sect].sh_offset, SEEK_SET) < 0 ||
+ read(fd, _strtab, shdr[string_sect].sh_size) !=
+ (ssize_t)shdr[string_sect].sh_size) {
+ seterror("Symbol table strings load failed.");
+ return false;
+ }
+ return true;
+}
+
+void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) {
+
+ int shortsCount = 0, othersCount = 0;
+ DBG("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset);
+
+ // Loop over symbols, add relocation offset
+ Elf32_Sym *s = (Elf32_Sym *)_symtab;
+ for (int c = _symbol_cnt; c--; s++) {
+ // Make sure we don't relocate special valued symbols
+ if (s->st_shndx < SHN_LOPROC) {
+ if (!ShortsMan.inGeneralSegment((char *)s->st_value)) {
+ othersCount++;
+ s->st_value += offset;
+ if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
+ seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
+ } else { // shorts section
+ shortsCount++;
+ s->st_value += shortsOffset;
+ if (!_shortsSegment->inSegment((char *)s->st_value))
+ seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
+ }
+
+ }
+
+ }
+
+ DBG("Relocated %d short symbols, %d others.\n", shortsCount, othersCount);
+}
+
+bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+
+ // Loop over sections, finding relocation sections
+ for (int i = 0; i < ehdr->e_shnum; i++) {
+
+ Elf32_Shdr *curShdr = &(shdr[i]);
+ //Elf32_Shdr *linkShdr = &(shdr[curShdr->sh_info]);
+
+ if (curShdr->sh_type == SHT_REL && // Check for a relocation section
+ curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size
+ (int)curShdr->sh_link == _symtab_sect && // Check that the sh_link connects to our symbol table
+ curShdr->sh_info < ehdr->e_shnum && // Check that the relocated section exists
+ (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { // Check if relocated section resides in memory
+ if (!ShortsMan.inGeneralSegment((char *)shdr[curShdr->sh_info].sh_addr)) { // regular segment
+ if (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, _segment)) {
+ return false;
+ }
+ } else { // In Shorts segment
+ if (!relocate(fd, curShdr->sh_offset, curShdr->sh_size, (void *)_shortsSegment->getOffset())) {
+ return false;
+ }
+ }
+
+ }
+ }
+
+ return true;
+}
+
+
+bool DLObject::load(int fd) {
+ fprintf(stderr, "In DLObject::load\n");
+
+ Elf32_Ehdr ehdr; // ELF header
+ Elf32_Phdr phdr; // Program header
+ Elf32_Shdr *shdr; // Section header
+ bool ret = true;
+
+ if (readElfHeader(fd, &ehdr) == false) {
+ return false;
+ }
+
+ for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments
+
+ fprintf(stderr, "Loading segment %d\n", i);
+
+ if (readProgramHeaders(fd, &ehdr, &phdr, i) == false)
+ return false;
+
+ if (!loadSegment(fd, &phdr))
+ return false;
+ }
+
+ if ((shdr = loadSectionHeaders(fd, &ehdr)) == NULL)
+ ret = false;
+
+ if (ret && ((_symtab_sect = loadSymbolTable(fd, &ehdr, shdr)) < 0))
+ ret = false;
+
+ if (ret && (loadStringTable(fd, shdr) == false))
+ ret = false;
+
+ if (ret)
+ relocateSymbols((Elf32_Addr)_segment, _shortsSegment->getOffset()); // Offset by our segment allocated address
+
+ if (ret && (relocateRels(fd, &ehdr, shdr) == false))
+ ret = false;
+
+ free(shdr);
+
+ return ret;
+}
+
+bool DLObject::open(const char *path) {
+ int fd;
+ void *ctors_start, *ctors_end;
+
+ DBG("open(\"%s\")\n", path);
+
+ // Get the address of the global pointer
+ _gpVal = (unsigned int) & _gp;
+ DBG("_gpVal is %x\n", _gpVal);
+
+ PowerMan.beginCriticalSection();
+
+ if ((fd = ::open(path, O_RDONLY)) < 0) {
+ seterror("%s not found.", path);
+ return false;
+ }
+
+ // Try to load and relocate
+ if (!load(fd)) {
+ ::close(fd);
+ unload();
+ return false;
+ }
+
+ ::close(fd);
+
+ PowerMan.endCriticalSection();
+
+ // flush data cache
+ sceKernelDcacheWritebackAll();
+
+ // Get the symbols for the global constructors and destructors
+ ctors_start = symbol("___plugin_ctors");
+ ctors_end = symbol("___plugin_ctors_end");
+ _dtors_start = symbol("___plugin_dtors");
+ _dtors_end = symbol("___plugin_dtors_end");
+
+ if (ctors_start == NULL || ctors_end == NULL || _dtors_start == NULL ||
+ _dtors_end == NULL) {
+ seterror("Missing ctors/dtors.");
+ _dtors_start = _dtors_end = NULL;
+ unload();
+ return false;
+ }
+
+ DBG("Calling constructors.\n");
+ for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++)
+ (**f)();
+
+ DBG("%s opened ok.\n", path);
+ return true;
+}
+
+bool DLObject::close() {
+ if (_dtors_start != NULL && _dtors_end != NULL)
+ for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++)
+ (**f)();
+ _dtors_start = _dtors_end = NULL;
+ unload();
+ return true;
+}
+
+void *DLObject::symbol(const char *name) {
+ DBG("symbol(\"%s\")\n", name);
+
+ if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) {
+ seterror("No symbol table loaded.");
+ return NULL;
+ }
+
+ Elf32_Sym *s = (Elf32_Sym *)_symtab;
+ for (int c = _symbol_cnt; c--; s++) {
+
+ // We can only import symbols that are global or weak in the plugin
+ if ((SYM_BIND(s->st_info) == STB_GLOBAL || SYM_BIND(s->st_info) == STB_WEAK) &&
+ /*_strtab[s->st_name] == '_' && */ // Try to make this more efficient
+ !strcmp(name, _strtab + s->st_name)) {
+
+ // We found the symbol
+ DBG("=> %p\n", (void*)s->st_value);
+ return (void*)s->st_value;
+ }
+ }
+
+ seterror("Symbol \"%s\" not found.", name);
+ return NULL;
+}
+
+
+
+ShortSegmentManager::ShortSegmentManager() {
+ _shortsStart = &__plugin_hole_start ;
+ _shortsEnd = &__plugin_hole_end;
+}
+
+ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) {
+ char *lastAddress = origAddr;
+ Common::List<Segment *>::iterator i;
+
+ // Find a block that fits, starting from the beginning
+ for (i = _list.begin(); i != _list.end(); ++i) {
+ char *currAddress = (*i)->getStart();
+
+ if ((int)(currAddress - lastAddress) >= size) break;
+
+ lastAddress = (*i)->getEnd();
+ }
+
+ if ((Elf32_Addr)lastAddress & 3)
+ lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4
+
+ if (lastAddress + size > _shortsEnd) {
+ seterror("Error. No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n",
+ size, lastAddress, _shortsEnd);
+ return NULL;
+ }
+
+ Segment *seg = new Segment(lastAddress, size, origAddr); // Create a new segment
+
+ if (lastAddress + size > _highestAddress) _highestAddress = lastAddress + size; // Keep track of maximum
+
+ _list.insert(i, seg);
+
+ DBG("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n",
+ size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress);
+
+ return seg;
+}
+
+void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) {
+ DBG("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd());
+ _list.remove(seg);
+ delete seg;
+}
+
+static char dlerr[MAXDLERRLEN];
+
+void *dlopen(const char *filename, int flags) {
+ DLObject *obj = new DLObject(dlerr);
+ if (obj->open(filename))
+ return (void *)obj;
+ delete obj;
+ return NULL;
+}
+
+int dlclose(void *handle) {
+ DLObject *obj = (DLObject *)handle;
+ if (obj == NULL) {
+ strcpy(dlerr, "Handle is NULL.");
+ return -1;
+ }
+ if (obj->close()) {
+ delete obj;
+ return 0;
+ }
+ return -1;
+}
+
+void *dlsym(void *handle, const char *symbol) {
+ if (handle == NULL) {
+ strcpy(dlerr, "Handle is NULL.");
+ return NULL;
+ }
+ return ((DLObject *)handle)->symbol(symbol);
+}
+
+const char *dlerror() {
+ return dlerr;
+}
+
+void dlforgetsyms(void *handle) {
+ if (handle != NULL)
+ ((DLObject *)handle)->discard_symtab();
+}
+
+
+#endif /* DYNAMIC_MODULES && __PLAYSTATION2__ */
diff --git a/backends/platform/ps2/ps2loader.h b/backends/platform/ps2/ps2loader.h
new file mode 100644
index 0000000000..7c412e7b05
--- /dev/null
+++ b/backends/platform/ps2/ps2loader.h
@@ -0,0 +1,137 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef PS2LOADER_H
+#define PS2LOADER_H
+
+#include "elf32.h"
+#include "common/list.h"
+#include "common/singleton.h"
+
+#define MAXDLERRLEN 80
+
+#define ShortsMan ShortSegmentManager::instance()
+
+class ShortSegmentManager : public Common::Singleton<ShortSegmentManager> {
+private:
+ char *_shortsStart;
+ char *_shortsEnd;
+
+public:
+ char *getShortsStart() {
+ return _shortsStart;
+ }
+ bool inGeneralSegment(char *addr) {
+ return ((char *)addr >= _shortsStart && (char *)addr < _shortsEnd);
+ }
+
+ class Segment {
+ private:
+ friend class ShortSegmentManager;
+ Segment(char *start, int size, char *origAddr) : _startAddress(start), _size(size), _origAddress(origAddr) {}
+ ~Segment() {}
+ char *_startAddress; // Start of shorts segment in memory
+ int _size; // Size of shorts segment
+ char *_origAddress; // Original address this segment was supposed to be at
+ public:
+ char *getStart() {
+ return _startAddress;
+ }
+ char *getEnd() {
+ return (_startAddress + _size);
+ }
+ Elf32_Addr getOffset() {
+ return (Elf32_Addr)(_startAddress - _origAddress);
+ }
+ bool inSegment(char *addr) {
+ return ((char *)addr >= _startAddress && (char *)addr <= _startAddress + _size);
+ }
+ };
+
+ Segment *newSegment(int size, char *origAddr);
+ void deleteSegment(Segment *);
+
+private:
+ ShortSegmentManager();
+ friend class Common::Singleton<ShortSegmentManager>;
+ Common::List<Segment *> _list;
+ char *_highestAddress;
+};
+
+
+
+
+class DLObject {
+protected:
+ char *_errbuf; /* For error messages, at least MAXDLERRLEN in size */
+
+ ShortSegmentManager::Segment *_shortsSegment; // For assigning shorts ranges
+ void *_segment, *_symtab;
+ char *_strtab;
+ int _symbol_cnt;
+ int _symtab_sect;
+ void *_dtors_start, *_dtors_end;
+
+ unsigned int _gpVal; // Value of Global Pointer
+ int _segmentSize;
+
+ void seterror(const char *fmt, ...);
+ void unload();
+ bool relocate(int fd, unsigned long offset, unsigned long size, void *);
+ bool load(int fd);
+
+ bool readElfHeader(int fd, Elf32_Ehdr *ehdr);
+ bool readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num);
+ bool loadSegment(int fd, Elf32_Phdr *phdr);
+ Elf32_Shdr *loadSectionHeaders(int fd, Elf32_Ehdr *ehdr);
+ int loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
+ bool loadStringTable(int fd, Elf32_Shdr *shdr);
+ void relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset);
+ bool relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr);
+
+public:
+ bool open(const char *path);
+ bool close();
+ void *symbol(const char *name);
+ void discard_symtab();
+
+ DLObject(char *errbuf = NULL) : _errbuf(_errbuf), _shortsSegment(NULL), _segment(NULL), _symtab(NULL),
+ _strtab(NULL), _symbol_cnt(0), _symtab_sect(-1), _dtors_start(NULL), _dtors_end(NULL), _gpVal(0) ,
+ _segmentSize(0) {}
+};
+
+
+
+#define RTLD_LAZY 0
+
+extern "C" {
+ void *dlopen(const char *filename, int flags);
+ int dlclose(void *handle);
+ void *dlsym(void *handle, const char *symbol);
+ const char *dlerror();
+ void dlforgetsyms(void *handle);
+}
+
+#endif /* PS2LOADER_H */
diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp
index 7659d5194d..120f6ee157 100644
--- a/backends/platform/ps2/systemps2.cpp
+++ b/backends/platform/ps2/systemps2.cpp
@@ -59,6 +59,8 @@
#include "backends/platform/ps2/ps2debug.h"
#include "backends/fs/ps2/ps2-fs-factory.h"
+#include "backends/plugins/ps2/ps2-provider.h"
+
#include "backends/saves/default/default-saves.h"
#include "common/config-manager.h"
@@ -132,6 +134,10 @@ extern "C" int main(int argc, char *argv[]) {
g_systemPs2->init();
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new PS2PluginProvider());
+#endif
+
sioprintf("init done. starting ScummVM.\n");
int res = scummvm_main(argc, argv);
sioprintf("scummvm_main terminated: %d\n", res);
diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile
index 7f8bb63b0a..8e83563d10 100644
--- a/backends/platform/psp/Makefile
+++ b/backends/platform/psp/Makefile
@@ -129,8 +129,7 @@ SDLFLAGS := $(shell $(PSPBIN)/sdl-config --cflags)
SDLLIBS := $(shell $(PSPBIN)/sdl-config --libs)
# PSP LIBS
PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \
- -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \
- -lpspkernel
+ -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspkernel
# Add in PSPSDK includes and libraries.
CXXFLAGS += $(SDLFLAGS)
@@ -148,10 +147,8 @@ OBJS := powerman.o \
cursor.o \
trace.o \
psploader.o \
- pspkeyboard.o \
- audio.o \
- thread.o \
- mp3.o
+ pspkeyboard.o
+
# Include common Scummvm makefile
include $(srcdir)/Makefile.common
diff --git a/backends/platform/psp/audio.cpp b/backends/platform/psp/audio.cpp
deleted file mode 100644
index bf1fb9ab41..0000000000
--- a/backends/platform/psp/audio.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * 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 for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $
- * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $
- *
- */
-
-#include <pspthreadman.h>
-#include <pspaudio.h>
-
-#include "common/scummsys.h"
-#include "backends/platform/psp/audio.h"
-#include "backends/platform/psp/thread.h"
-
-//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
-//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
-
-#include "backends/platform/psp/trace.h"
-
-bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData) {
- DEBUG_ENTER_FUNC();
- if (_init) {
- PSP_ERROR("audio device already initialized\n");
- return true;
- }
-
- PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n",
- freq, numOfChannels, numOfSamples, callback, (uint32)userData);
-
- numOfSamples = PSP_AUDIO_SAMPLE_ALIGN(numOfSamples);
- uint32 bufLen = numOfSamples * numOfChannels * NUM_BUFFERS * sizeof(uint16);
-
- PSP_DEBUG_PRINT("total buffer size[%d]\n", bufLen);
-
- _buffers[0] = (byte *)memalign(64, bufLen);
- if (!_buffers[0]) {
- PSP_ERROR("failed to allocate memory for audio buffers\n");
- return false;
- }
- memset(_buffers[0], 0, bufLen); // clean the buffer
-
- // Fill in the rest of the buffer pointers
- byte *pBuffer = _buffers[0];
- for (int i = 1; i < NUM_BUFFERS; i++) {
- pBuffer += numOfSamples * numOfChannels * sizeof(uint16);
- _buffers[i] = pBuffer;
- }
-
- // Reserve a HW channel for our audio
- _pspChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, numOfSamples, numOfChannels == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO);
- if (_pspChannel < 0) {
- PSP_ERROR("failed to reserve audio channel\n");
- return false;
- }
-
- PSP_DEBUG_PRINT("reserved channel[%d] for audio\n", _pspChannel);
-
- // Save our data
- _numOfChannels = numOfChannels;
- _numOfSamples = numOfSamples;
- _bufferSize = numOfSamples * numOfChannels * sizeof(uint16); // should be the right size to send the app
- _callback = callback;
- _userData = userData;
- _bufferToFill = 0;
- _bufferToPlay = 0;
-
- _init = true;
- _paused = true; // start in paused mode
-
- createThread();
-
- return true;
-}
-
-bool PspAudio::createThread() {
- DEBUG_ENTER_FUNC();
- int threadId = sceKernelCreateThread("audioThread", thread, PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD, THREAD_ATTR_USER, 0);
-
- if (threadId < 0) { // error
- PSP_ERROR("failed to create audio thread. Error code %d\n", threadId);
- return false;
- }
-
- PspAudio *_this = this; // trick to get into context when the thread starts
-
- if (sceKernelStartThread(threadId, sizeof(uint32 *), &_this) < 0) {
- PSP_ERROR("failed to start thread %d\n", threadId);
- return false;
- }
-
- PSP_DEBUG_PRINT("created audio thread[%x]\n", threadId);
-
- return true;
-}
-
-// Static function to be called upon thread startup. Will call a non-static function
-int PspAudio::thread(SceSize, void *__this) {
- DEBUG_ENTER_FUNC();
- PspAudio *_this = *(PspAudio **)__this; // get our this for the context
-
- _this->audioThread();
- return 0;
-};
-
-// The real thread function
-void PspAudio::audioThread() {
- assert(_callback);
- PSP_DEBUG_PRINT_FUNC("audio thread started\n");
-
- while (_init) { // Keep looping so long as we haven't been told to stop
- if (_paused)
- PSP_DEBUG_PRINT("audio thread paused\n");
- while (_paused) { // delay until we stop pausing
- sceKernelDelayThread(100000); // 100ms
- if (!_paused)
- PSP_DEBUG_PRINT("audio thread unpaused\n");
- }
-
- PSP_DEBUG_PRINT("remaining samples[%d]\n", remainingSamples);
-
- PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill);
- _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in
- nextBuffer(_bufferToFill);
-
- PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay);
- playBuffer();
- nextBuffer(_bufferToPlay);
- } // while _init
-
- // destroy everything
- free(_buffers[0]);
- sceAudioChRelease(_pspChannel);
- PSP_DEBUG_PRINT("audio thread exiting. ****************************\n");
-}
-
-// Much faster than using %
-inline void PspAudio::nextBuffer(int &bufferIdx) {
- DEBUG_ENTER_FUNC();
- bufferIdx++;
- if (bufferIdx >= NUM_BUFFERS)
- bufferIdx = 0;
-}
-
-// Don't do it with blocking
-inline bool PspAudio::playBuffer() {
- DEBUG_ENTER_FUNC();
- int ret;
- if (_numOfChannels == 1)
- ret = sceAudioOutputBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
- else
- ret = sceAudioOutputPannedBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
-
- if (ret < 0) {
- PSP_ERROR("failed to output audio. Error[%d]\n", ret);
- return false;
- }
- return true;
-}
-
-void PspAudio::close() {
- PSP_DEBUG_PRINT("close had been called ***************\n");
- _init = false;
-}
diff --git a/backends/platform/psp/audio.h b/backends/platform/psp/audio.h
deleted file mode 100644
index 603f8f6bfc..0000000000
--- a/backends/platform/psp/audio.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * 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 for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $
- * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $
- *
- */
-
-#ifndef PSP_AUDIO_H
-#define PSP_AUDIO_H
-
-class PspAudio {
-public:
- enum {
- NUM_BUFFERS = 2,
- FREQUENCY = 44100 /* only frequency we allow */
- };
- typedef void (* callbackFunc)(void *userData, byte *samples, int len);
- PspAudio() : _pspChannel(0),
- _numOfChannels(0), _numOfSamples(0), _callback(0),
- _bufferToPlay(0), _bufferToFill(0),
- _init(false), _paused(true) {
- for (int i=0; i<NUM_BUFFERS; i++)
- _buffers[i] = 0;
- }
- ~PspAudio() { close(); }
- bool playBuffer();
- void nextBuffer(int &bufferIdx);
- static int thread(SceSize, void *);
- void audioThread();
- bool open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData);
- bool createThread();
- void close();
- uint32 getFrequency() { return FREQUENCY; }
- void pause() { _paused = true; }
- void unpause() { _paused = false; }
-
-private:
- int _pspChannel; // chosen hardware output channel
- uint32 _numOfChannels; // 1 for mono; 2 for stereo
- uint32 _numOfSamples;
- callbackFunc _callback; // the callback to call between outputting audio
- void *_userData; // userData to send with callback
- byte *_buffers[NUM_BUFFERS];
- int _bufferToPlay; // the next buffer to output
- int _bufferToFill;
- int _bufferSize;
- bool _init; // flag for initialization
- bool _paused;
-};
-
-#endif /* PSP_AUDIO_H */
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp
index c5a6250188..90c41e796d 100644
--- a/backends/platform/psp/display_client.cpp
+++ b/backends/platform/psp/display_client.cpp
@@ -686,18 +686,17 @@ void GuRenderer::fillVertices(Vertex *vertices) {
uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0;
uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0;
- // Save scaled offset on screen
- float scaledOffsetOnScreenX = scaleSourceToOutputX(_offsetOnScreen.x);
- float scaledOffsetOnScreenY = scaleSourceToOutputY(_offsetOnScreen.y);
-
float imageStartX, imageStartY, imageEndX, imageEndY;
- imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutputX(_maxTextureOffset.x));
- imageStartY = gapY + scaledOffsetOnScreenY;
+ imageStartX = gapX + (scaleSourceToOutputX(_maxTextureOffset.x));
+ imageStartY = gapY;
+
+ imageStartX += scaleSourceToOutputX(_offsetOnScreen.x);
+ imageStartY += scaleSourceToOutputY(_offsetOnScreen.y);
if (_fullScreen) { // shortcut
- imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX;
- imageEndY = PSP_SCREEN_HEIGHT - gapY + scaledOffsetOnScreenY; // needed for screen shake
+ imageEndX = PSP_SCREEN_WIDTH - gapX;
+ imageEndY = PSP_SCREEN_HEIGHT - gapY;
} else { /* !fullScreen */
imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width);
imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height);
diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp
index c2f21e084b..0982512a86 100644
--- a/backends/platform/psp/display_manager.cpp
+++ b/backends/platform/psp/display_manager.cpp
@@ -34,7 +34,6 @@
#include "backends/platform/psp/default_display_client.h"
#include "backends/platform/psp/cursor.h"
#include "backends/platform/psp/pspkeyboard.h"
-#include "backends/platform/psp/thread.h"
#define USE_DISPLAY_CALLBACK // to use callback for finishing the render
#include "backends/platform/psp/display_manager.h"
@@ -65,7 +64,7 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = {
void MasterGuRenderer::setupCallbackThread() {
DEBUG_ENTER_FUNC();
- int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD, THREAD_ATTR_USER, 0);
+ int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, 0x11, 4*1024, THREAD_ATTR_USER, 0);
PSP_DEBUG_PRINT("Display CB thread id is %x\n", thid);
diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk
index 99170ce7fb..f7191fe14f 100644
--- a/backends/platform/psp/module.mk
+++ b/backends/platform/psp/module.mk
@@ -12,10 +12,7 @@ MODULE_OBJS := powerman.o \
cursor.o \
trace.o \
psploader.o \
- pspkeyboard.o \
- audio.o \
- thread.o \
- mp3.o
+ pspkeyboard.o
MODULE_DIRS += \
backends/platform/psp/
diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp
deleted file mode 100644
index 972c5a8ba8..0000000000
--- a/backends/platform/psp/mp3.cpp
+++ /dev/null
@@ -1,487 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * 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 for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/debug.h"
-#include "common/stream.h"
-#include "common/util.h"
-#include "common/singleton.h"
-#include "common/mutex.h"
-
-#include "sound/audiostream.h"
-
-#include <pspaudiocodec.h>
-#include <psputility_modules.h>
-#include <pspthreadman.h>
-#include <pspsysmem.h>
-#include <pspmodulemgr.h>
-#include <psputility_avmodules.h>
-#include <mad.h>
-#include "backends/platform/psp/mp3.h"
-
-//#define DISABLE_PSP_MP3 // to make us use the regular MAD decoder instead
-
-//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
-//#define __PSP_DEBUG_PRINT__
-#include "backends/platform/psp/trace.h"
-
-//#define PRINT_BUFFERS /* to debug MP3 buffers */
-
-namespace Audio {
-
-class Mp3PspStream;
-
-bool Mp3PspStream::_decoderInit = false; // has the decoder been initialized
-#ifdef DISABLE_PSP_MP3
-bool Mp3PspStream::_decoderFail = true; // pretend the decoder failed
-#else
-bool Mp3PspStream::_decoderFail = false; // has the decoder failed to load
-#endif
-
-bool Mp3PspStream::initDecoder() {
- DEBUG_ENTER_FUNC();
-
- if (_decoderInit) {
- PSP_ERROR("Already initialized!");
- return true;
- }
-
- // Based on PSP firmware version, we need to do different things to do Media Engine processing
- uint32 firmware = sceKernelDevkitVersion();
- PSP_DEBUG_PRINT("Firmware version 0x%x\n", firmware);
- if (firmware == 0x01050001){
- if (!loadStartAudioModule((char *)(void *)"flash0:/kd/me_for_vsh.prx",
- PSP_MEMORY_PARTITION_KERNEL)) {
- PSP_ERROR("failed to load me_for_vsh.prx. ME cannot start.\n");
- _decoderFail = true;
- return false;
- }
- if (!loadStartAudioModule((char *)(void *)"flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL)) {
- PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n");
- _decoderFail = true;
- return false;
- }
- } else {
- if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) {
- PSP_ERROR("failed to load AVCODEC module.\n");
- _decoderFail = true;
- return false;
- }
- }
-
- PSP_INFO_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening
-
- _decoderInit = true;
- return true;
-}
-
-bool Mp3PspStream::stopDecoder() {
- DEBUG_ENTER_FUNC();
-
- if (!_decoderInit)
- return true;
-
- // Based on PSP firmware version, we need to do different things to do Media Engine processing
- if (sceKernelDevkitVersion() == 0x01050001){
-/* if (!unloadAudioModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL) ||
- !unloadAudioModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL) {
- PSP_ERROR("failed to unload audio module\n");
- return false;
- }
-*/
- }else{
- if (sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) < 0) {
- PSP_ERROR("failed to unload avcodec module\n");
- return false;
- }
- }
-
- _decoderInit = false;
- return true;
-}
-
-//Load a PSP audio module
-bool Mp3PspStream::loadStartAudioModule(const char *modname, int partition){
- DEBUG_ENTER_FUNC();
-
- SceKernelLMOption option;
- SceUID modid;
-
- memset(&option, 0, sizeof(option));
- option.size = sizeof(option);
- option.mpidtext = partition;
- option.mpiddata = partition;
- option.position = 0;
- option.access = 1;
-
- modid = sceKernelLoadModule(modname, 0, &option);
- if (modid < 0) {
- PSP_ERROR("Failed to load module %s. Got error 0x%x\n", modname, modid);
- return false;
- }
-
- int ret = sceKernelStartModule(modid, 0, NULL, NULL, NULL);
- if (ret < 0) {
- PSP_ERROR("Failed to start module %s. Got error 0x%x\n", modname, ret);
- return false;
- }
- return true;
-}
-
-// TODO: make parallel function for unloading the 1.50 modules
-
-Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
- _inStream(inStream),
- _disposeAfterUse(dispose),
- _pcmLength(0),
- _posInFrame(0),
- _state(MP3_STATE_INIT),
- _length(0, 1000),
- _sampleRate(0),
- _totalTime(mad_timer_zero) {
-
- DEBUG_ENTER_FUNC();
-
- assert(_decoderInit); // must be initialized by now
-
- // let's leave the buffer guard -- who knows, it may be good?
- memset(_buf, 0, sizeof(_buf));
- memset(_codecInBuffer, 0, sizeof(_codecInBuffer));
-
- initStream(); // init needed stuff for the stream
-
- while (_state != MP3_STATE_EOS)
- findValidHeader(); // get a first header so we can read basic stuff
-
- _sampleRate = _header.samplerate; // copy it before it gets destroyed
-
- _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());
-
- //initStreamME(); // init the stuff needed for the ME to work
-
- deinitStream();
- //releaseStreamME();
-
- _state = MP3_STATE_INIT;
-}
-
-int Mp3PspStream::initStream() {
- DEBUG_ENTER_FUNC();
-
- if (_state != MP3_STATE_INIT)
- deinitStream();
-
- // Init MAD
- mad_stream_init(&_stream);
- mad_header_init(&_header);
-
- // Reset the stream data
- _inStream->seek(0, SEEK_SET);
- _totalTime = mad_timer_zero;
- _posInFrame = 0;
-
- // Update state
- _state = MP3_STATE_READY;
-
- // Read the first few sample bytes into the buffer
- readMP3DataIntoBuffer();
-
- return true;
-}
-
-bool Mp3PspStream::initStreamME() {
- // The following will eventually go into the thread
- sceAudiocodecReleaseEDRAM(_codecParams); // do we need this?
-
- memset(_codecParams, 0, sizeof(_codecParams));
-
- // Init the MP3 hardware
- int ret = 0;
- ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002);
- if (ret < 0) {
- PSP_ERROR("failed to init MP3 ME module. sceAudiocodecCheckNeedMem returned 0x%x.\n", ret);
- return false;
- }
- PSP_DEBUG_PRINT("sceAudiocodecCheckNeedMem returned %d\n", ret);
- ret = sceAudiocodecGetEDRAM(_codecParams, 0x1002);
- if (ret < 0) {
- PSP_ERROR("failed to init MP3 ME module. sceAudiocodecGetEDRAM returned 0x%x.\n", ret);
- return false;
- }
- PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret);
-
- PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate);
- _codecParams[10] = _sampleRate;
-
- ret = sceAudiocodecInit(_codecParams, 0x1002);
- if (ret < 0) {
- PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret);
- return false;
- }
-
- return true;
-}
-
-Mp3PspStream::~Mp3PspStream() {
- DEBUG_ENTER_FUNC();
-
- deinitStream();
- releaseStreamME(); // free the memory used for this stream
-
- if (_disposeAfterUse == DisposeAfterUse::YES)
- delete _inStream;
-}
-
-void Mp3PspStream::deinitStream() {
- DEBUG_ENTER_FUNC();
-
- if (_state == MP3_STATE_INIT)
- return;
-
- // Deinit MAD
- mad_header_finish(&_header);
- mad_stream_finish(&_stream);
-
- _state = MP3_STATE_EOS;
-}
-
-void Mp3PspStream::releaseStreamME() {
- sceAudiocodecReleaseEDRAM(_codecParams);
-}
-
-void Mp3PspStream::decodeMP3Data() {
- DEBUG_ENTER_FUNC();
-
- do {
- if (_state == MP3_STATE_INIT) {
- initStream();
- initStreamME();
- }
-
- if (_state == MP3_STATE_EOS)
- return;
-
- findValidHeader(); // seach for next valid header
-
- while (_state == MP3_STATE_READY) {
- _stream.error = MAD_ERROR_NONE;
-
- uint32 frame_size = _stream.next_frame - _stream.this_frame;
- uint32 samplesPerFrame = _header.layer == MAD_LAYER_III ? 576 : 1152; // Varies by layer
- // calculate frame size -- try
- //uint32 calc_frame_size = ((144 * _header.bitrate) / 22050) + (_header.flags & MAD_FLAG_PADDING ? 1 : 0);
-
- // Get stereo/mono
- uint32 multFactor = 1;
- if (_header.mode != MAD_MODE_SINGLE_CHANNEL) // mono - x2 for 16bit
- multFactor *= 2; // stereo - x4 for 16bit
-
- PSP_DEBUG_PRINT("MP3 frame size[%d]. Samples[%d]. Multfactor[%d] pad[%d]\n", frame_size, samplesPerFrame, multFactor, _header.flags & MAD_FLAG_PADDING);
- memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned
-
- // set up parameters for ME
- _codecParams[6] = (unsigned long)_codecInBuffer;
- _codecParams[8] = (unsigned long)_pcmSamples;
- _codecParams[7] = frame_size;
- _codecParams[9] = samplesPerFrame * multFactor; // x2 for stereo
-
- // debug
-#ifdef PRINT_BUFFERS
- PSP_DEBUG_PRINT("mp3 frame:\n");
- for (int i=0; i < (int)frame_size; i++) {
- PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]);
- }
- PSP_DEBUG_PRINT("\n");
-#endif
- // Decode the next frame
- // This function blocks. We'll want to put it in a thread
- int ret = sceAudiocodecDecode(_codecParams, 0x1002);
- if (ret < 0) {
- PSP_ERROR("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret);
- // handle error here
- }
-
-#ifdef PRINT_BUFFERS
- PSP_DEBUG_PRINT("PCM frame:\n");
- for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2
- PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]);
- }
- PSP_DEBUG_PRINT("\n");
-#endif
- _pcmLength = samplesPerFrame;
- _posInFrame = 0;
- break;
- }
- } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
-
- if (_stream.error != MAD_ERROR_NONE) // catch EOS
- _state = MP3_STATE_EOS;
-}
-
-void Mp3PspStream::readMP3DataIntoBuffer() {
- DEBUG_ENTER_FUNC();
-
- uint32 remaining = 0;
-
- // Give up immediately if we already used up all data in the stream
- if (_inStream->eos()) {
- _state = MP3_STATE_EOS;
- return;
- }
-
- if (_stream.next_frame) {
- // If there is still data in the MAD stream, we need to preserve it.
- // Note that we use memmove, as we are reusing the same buffer,
- // and hence the data regions we copy from and to may overlap.
- remaining = _stream.bufend - _stream.next_frame;
- assert(remaining < BUFFER_SIZE); // Paranoia check
- memmove(_buf, _stream.next_frame, remaining); // TODO: may want another buffer
- }
-
- // Try to read the next block
- uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining);
- if (size <= 0) {
- _state = MP3_STATE_EOS;
- return;
- }
-
- // Feed the data we just read into the stream decoder
- _stream.error = MAD_ERROR_NONE;
- mad_stream_buffer(&_stream, _buf, size + remaining); // just setup the pointers
-}
-
-bool Mp3PspStream::seek(const Timestamp &where) {
- DEBUG_ENTER_FUNC();
-
- if (where == _length) {
- _state = MP3_STATE_EOS;
- return true;
- } else if (where > _length) {
- return false;
- }
-
- const uint32 time = where.msecs();
-
- mad_timer_t destination;
- mad_timer_set(&destination, time / 1000, time % 1000, 1000);
-
- // Check if we need to rewind
- if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) {
- initStream();
- initStreamME();
- }
-
- // The ME will need clear data no matter what once we seek?
- //if (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
- // initStreamME();
-
- // Skip ahead
- while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
- findValidHeader();
-
- return (_state != MP3_STATE_EOS);
-}
-
-// Seek in the stream, finding the next valid header
-void Mp3PspStream::findValidHeader() {
- DEBUG_ENTER_FUNC();
-
- if (_state != MP3_STATE_READY)
- return;
-
- // If necessary, load more data into the stream decoder
- if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3DataIntoBuffer();
-
- while (_state != MP3_STATE_EOS) {
- _stream.error = MAD_ERROR_NONE;
-
- // Decode the next header.
- if (mad_header_decode(&_header, &_stream) == -1) {
- if (_stream.error == MAD_ERROR_BUFLEN) {
- readMP3DataIntoBuffer(); // Read more data
- continue;
- } else if (MAD_RECOVERABLE(_stream.error)) {
- debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
- continue;
- } else {
- warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
- break;
- }
- }
-
- // Sum up the total playback time so far
- mad_timer_add(&_totalTime, _header.duration);
- break;
- }
-
- if (_stream.error != MAD_ERROR_NONE)
- _state = MP3_STATE_EOS;
-}
-
-int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) {
- DEBUG_ENTER_FUNC();
-
- int samples = 0;
-#ifdef PRINT_BUFFERS
- int16 *debugBuffer = buffer;
-#endif
-
- // Keep going as long as we have input available
- while (samples < numSamples && _state != MP3_STATE_EOS) {
- const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header));
-
- while (samples < len) {
- *buffer++ = _pcmSamples[_posInFrame << 1];
- samples++;
- if (MAD_NCHANNELS(&_header) == 2) {
- *buffer++ = _pcmSamples[(_posInFrame << 1) + 1];
- samples++;
- }
- _posInFrame++; // always skip an extra sample since ME always outputs stereo
- }
-
- //memcpy(buffer, &_pcmSamples[_posInFrame], len << 1); // 16 bits
- //_posInFrame += len; // next time we start from the middle
-
- if (_posInFrame >= _pcmLength) {
- // We used up all PCM data in the current frame -- read & decode more
- decodeMP3Data();
- }
- }
-
-#ifdef PRINT_BUFFERS
- PSP_INFO_PRINT("buffer:\n");
- for (int i = 0; i<numSamples; i++)
- PSP_INFO_PRINT("%d ", debugBuffer[i]);
- PSP_INFO_PRINT("\n\n");
-#endif
-
- return samples;
-}
-
-} // End of namespace Audio
-
-
diff --git a/backends/platform/psp/mp3.h b/backends/platform/psp/mp3.h
deleted file mode 100644
index f8802f930c..0000000000
--- a/backends/platform/psp/mp3.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * 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 for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef SOUND_MP3_PSP_H
-#define SOUND_MP3_PSP_H
-
-#include "common/types.h"
-#include "common/scummsys.h"
-
-namespace Common {
- class SeekableReadStream;
-}
-
-namespace Audio {
-
-class AudioStream;
-class SeekableAudioStream;
-
-class Mp3PspStream : public SeekableAudioStream {
-protected:
- enum State {
- MP3_STATE_INIT, // Need to init the decoder
- MP3_STATE_READY, // ready for processing data
- MP3_STATE_EOS // end of data reached (may need to loop)
- };
-
- #define MAX_SAMPLES_PER_FRAME 2048 * 2
- int16 _pcmSamples[MAX_SAMPLES_PER_FRAME] __attribute__((aligned(64))); // samples to output PCM data into
- byte _codecInBuffer[3072] __attribute__((aligned(64))); // the codec always needs alignment
- unsigned long _codecParams[65]__attribute__((aligned(64))); // TODO: change to struct
-
- Common::SeekableReadStream *_inStream;
- DisposeAfterUse::Flag _disposeAfterUse;
-
- uint32 _pcmLength; // how many pcm samples we have (/2 for mono)
-
- uint _posInFrame; // position in frame
- State _state; // what state the stream is in
-
- Timestamp _length;
- uint32 _sampleRate;
-
- mad_timer_t _totalTime;
- mad_stream _stream; //
- mad_header _header; // This is all we need from libmad
-
- static bool _decoderInit; // has the decoder been initialized
- static bool _decoderFail; // has the decoder failed to load
-
- enum {
- BUFFER_SIZE = 5 * 8192
- };
-
- // This buffer contains a slab of input data
- byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
-
- void decodeMP3Data();
- void readMP3DataIntoBuffer();
-
- static bool loadStartAudioModule(const char *modname, int partition);
- int initStream();
- void findValidHeader();
- void deinitStream();
-
- // to init and uninit ME decoder
- static bool initDecoder();
- static bool stopDecoder();
-
- // ME functions for stream
- bool initStreamME();
- void releaseStreamME();
-
-public:
- Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose);
- ~Mp3PspStream();
-
- // This function avoids having to create streams when it's not possible
- static inline bool isOkToCreateStream() {
- if (_decoderFail) // fatal failure
- return false;
- if (!_decoderInit) // if we're not initialized
- if (!initDecoder()) // check if we failed init
- return false;
- return true;
- }
-
- int readBuffer(int16 *buffer, const int numSamples);
-
- bool endOfData() const { return _state == MP3_STATE_EOS; }
- bool isStereo() const { return MAD_NCHANNELS(&_header) == 2; }
- int getRate() const { return _header.samplerate; }
-
- bool seek(const Timestamp &where);
- Timestamp getLength() const { return _length; }
-};
-
-} // End of namespace Audio
-
-#endif // #ifndef SOUND_MP3_PSP_H
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index a36ae1847f..58d98bc219 100644
--- a/backends/platform/psp/osys_psp.cpp
+++ b/backends/platform/psp/osys_psp.cpp
@@ -37,7 +37,6 @@
#include "backends/platform/psp/psppixelformat.h"
#include "backends/platform/psp/osys_psp.h"
#include "backends/platform/psp/powerman.h"
-#include "backends/platform/psp/thread.h"
#include "backends/saves/psp/psp-saves.h"
#include "backends/timer/default/default-timer.h"
@@ -49,7 +48,6 @@
#include "backends/platform/psp/trace.h"
-#define USE_PSP_AUDIO
#define SAMPLES_PER_SEC 44100
@@ -60,11 +58,7 @@ static int timer_handler(int t) {
}
void OSystem_PSP::initSDL() {
-#ifdef USE_PSP_AUDIO
- SDL_Init(0);
-#else
- SDL_Init(SDL_INIT_AUDIO);
-#endif
+ SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
}
OSystem_PSP::~OSystem_PSP() {}
@@ -91,7 +85,7 @@ void OSystem_PSP::initBackend() {
_inputHandler.init();
initSDL();
-
+
_savefile = new PSPSaveFileManager;
_timer = new DefaultTimerManager();
@@ -299,18 +293,17 @@ bool OSystem_PSP::pollEvent(Common::Event &event) {
return _inputHandler.getAllInputs(event);
}
+
uint32 OSystem_PSP::getMillis() {
- return PspThread::getMillis();
+ return SDL_GetTicks();
}
void OSystem_PSP::delayMillis(uint msecs) {
- PspThread::delayMillis(msecs);
+ SDL_Delay(msecs);
}
void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) {
- _pspTimer.setCallback((PspTimer::CallbackFunc)callback);
- _pspTimer.setIntervalMs(interval);
- _pspTimer.start();
+ SDL_SetTimer(interval, (SDL_TimerCallback)callback);
}
OSystem::MutexRef OSystem_PSP::createMutex(void) {
@@ -338,6 +331,8 @@ void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) {
}
void OSystem_PSP::setupMixer(void) {
+ SDL_AudioSpec desired;
+ SDL_AudioSpec obtained;
// Determine the desired output sampling frequency.
uint32 samplesPerSec = 0;
@@ -354,22 +349,6 @@ void OSystem_PSP::setupMixer(void) {
while (samples * 16 > samplesPerSec * 2)
samples >>= 1;
- assert(!_mixer);
-
-#ifdef USE_PSP_AUDIO
- if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) {
- PSP_ERROR("failed to open audio\n");
- return;
- }
- samplesPerSec = _audio.getFrequency(); // may have been changed by audio system
- _mixer = new Audio::MixerImpl(this, samplesPerSec);
- assert(_mixer);
- _mixer->setReady(true);
- _audio.unpause();
-#else
- SDL_AudioSpec obtained;
- SDL_AudioSpec desired;
-
memset(&desired, 0, sizeof(desired));
desired.freq = samplesPerSec;
desired.format = AUDIO_S16SYS;
@@ -377,7 +356,8 @@ void OSystem_PSP::setupMixer(void) {
desired.samples = samples;
desired.callback = mixCallback;
desired.userdata = this;
-
+
+ assert(!_mixer);
if (SDL_OpenAudio(&desired, &obtained) != 0) {
warning("Could not open audio: %s", SDL_GetError());
_mixer = new Audio::MixerImpl(this, samplesPerSec);
@@ -396,15 +376,10 @@ void OSystem_PSP::setupMixer(void) {
SDL_PauseAudio(0);
}
-#endif /* USE_PSP_AUDIO */
}
void OSystem_PSP::quit() {
-#ifdef USE_PSP_AUDIO
- _audio.close();
-#else
SDL_CloseAudio();
-#endif
SDL_Quit();
sceKernelExitGame();
}
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index 3f075d0139..8c5b40dcdf 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -38,8 +38,6 @@
#include "backends/platform/psp/pspkeyboard.h"
#include "backends/platform/psp/display_manager.h"
#include "backends/platform/psp/input.h"
-#include "backends/platform/psp/audio.h"
-#include "backends/timer/psp/timer.h"
#include <SDL.h>
@@ -57,8 +55,6 @@ private:
DisplayManager _displayManager;
PSPKeyboard _keyboard;
InputHandler _inputHandler;
- PspAudio _audio;
- PspTimer _pspTimer;
void initSDL();
diff --git a/backends/platform/psp/psp.spec b/backends/platform/psp/psp.spec
index ac325b7fd6..debdab3208 100644
--- a/backends/platform/psp/psp.spec
+++ b/backends/platform/psp/psp.spec
@@ -1,3 +1,3 @@
%rename lib old_lib
*lib:
-%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspaudiocodec -lpspkernel
+%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspkernel
diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp
index e6940eba13..e568184990 100644
--- a/backends/platform/psp/psp_main.cpp
+++ b/backends/platform/psp/psp_main.cpp
@@ -39,7 +39,6 @@
#include <base/main.h>
#include <base/plugins.h>
#include "backends/platform/psp/powerman.h"
-#include "backends/platform/psp/thread.h"
#include "backends/plugins/psp/psp-provider.h"
#include "backends/platform/psp/psppixelformat.h"
@@ -141,7 +140,7 @@ int CallbackThread(SceSize /*size*/, void *arg) {
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
- int thid = sceKernelCreateThread("power_thread", CallbackThread, PRIORITY_POWER_THREAD, STACK_POWER_THREAD, THREAD_ATTR_USER, 0);
+ int thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, THREAD_ATTR_USER, 0);
if (thid >= 0) {
sceKernelStartThread(thid, 0, 0);
}
diff --git a/backends/platform/psp/thread.h b/backends/platform/psp/thread.h
deleted file mode 100644
index e83eead68e..0000000000
--- a/backends/platform/psp/thread.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * 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 for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/portdefs.h $
- * $Id: portdefs.h 38687 2009-02-21 12:08:52Z joostp $
- *
- */
-
-#ifndef PSP_THREAD_H
-#define PSP_THREAD_H
-
-#include "common/scummsys.h"
-
-class PspThread {
-public:
- static void delayMillis(uint32 ms);
- static void delayMicros(uint32 us);
- static uint32 getMillis();
- static uint32 getMicros();
-};
-
-enum ThreadPriority {
- PRIORITY_MAIN_THREAD = 36,
- PRIORITY_TIMER_THREAD = 30,
- PRIORITY_AUDIO_THREAD = 25, // must be higher than timer or we get stuttering
- PRIORITY_POWER_THREAD = 20, // quite a light thread
- PRIORITY_DISPLAY_THREAD = 17 // very light thread for callbacks only
-};
-
-enum StackSizes {
- STACK_AUDIO_THREAD = 16 * 1024,
- STACK_TIMER_THREAD = 32 * 1024,
- STACK_DISPLAY_THREAD = 2 * 1024,
- STACK_POWER_THREAD = 4 * 1024
-};
-
-#endif /* PSP_THREADS_H */
-
-
diff --git a/backends/platform/samsungtv/main.cpp b/backends/platform/samsungtv/main.cpp
index 2c025b750c..a6b8376912 100644
--- a/backends/platform/samsungtv/main.cpp
+++ b/backends/platform/samsungtv/main.cpp
@@ -43,7 +43,7 @@ extern "C" int Game_Main(char *path, char *) {
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(0, 0);
- ((OSystem_SDL *)g_system)->deinit();
+ g_system->quit(); // TODO: Consider removing / replacing this!
return res;
}
diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp
index 82670cfcb7..9d0d872c3d 100644
--- a/backends/platform/sdl/graphics.cpp
+++ b/backends/platform/sdl/graphics.cpp
@@ -1673,6 +1673,7 @@ void OSystem_SDL::drawMouse() {
SDL_Rect dst;
int scale;
+ int width, height;
int hotX, hotY;
dst.x = _mouseCurState.x;
@@ -1680,12 +1681,16 @@ void OSystem_SDL::drawMouse() {
if (!_overlayVisible) {
scale = _videoMode.scaleFactor;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
dst.w = _mouseCurState.vW;
dst.h = _mouseCurState.vH;
hotX = _mouseCurState.vHotX;
hotY = _mouseCurState.vHotY;
} else {
scale = 1;
+ width = _videoMode.overlayWidth;
+ height = _videoMode.overlayHeight;
dst.w = _mouseCurState.rW;
dst.h = _mouseCurState.rH;
hotX = _mouseCurState.rHotX;
diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp
index 13e614a4a2..b38b815438 100644
--- a/backends/platform/sdl/main.cpp
+++ b/backends/platform/sdl/main.cpp
@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
// Invoke the actual ScummVM main entry point:
int res = scummvm_main(argc, argv);
- ((OSystem_SDL *)g_system)->deinit();
+ g_system->quit(); // TODO: Consider removing / replacing this!
return res;
}
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index f8ae824acf..e54d70e8b2 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -482,7 +482,7 @@ bool OSystem_SDL::getFeatureState(Feature f) {
}
}
-void OSystem_SDL::deinit() {
+void OSystem_SDL::quit() {
if (_cdrom) {
SDL_CDStop(_cdrom);
SDL_CDClose(_cdrom);
@@ -504,14 +504,10 @@ void OSystem_SDL::deinit() {
SDL_Quit();
- // Event Manager requires save manager for storing
+ // Even Manager requires save manager for storing
// recorded events
delete getEventManager();
delete _savefile;
-}
-
-void OSystem_SDL::quit() {
- deinit();
#if !defined(SAMSUNGTV)
exit(0);
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 341a59c8cf..b6baa52391 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -202,8 +202,6 @@ public:
// Quit
virtual void quit(); // overloaded by CE backend
- void deinit();
-
virtual void getTimeAndDate(TimeDate &t) const;
virtual Common::TimerManager *getTimerManager();
diff --git a/backends/plugins/ps2/ps2-provider.cpp b/backends/plugins/ps2/ps2-provider.cpp
new file mode 100644
index 0000000000..3e966bbd08
--- /dev/null
+++ b/backends/plugins/ps2/ps2-provider.cpp
@@ -0,0 +1,108 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * 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 for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#if defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
+#include "backends/plugins/ps2/ps2-provider.h"
+#include "backends/plugins/dynamic-plugin.h"
+#include "common/fs.h"
+
+#include "backends/platform/ps2/ps2loader.h"
+
+
+class PS2Plugin : public DynamicPlugin {
+protected:
+ void *_dlHandle;
+ Common::String _filename;
+
+ virtual VoidFunc findSymbol(const char *symbol) {
+ void *func = dlsym(_dlHandle, symbol);
+ if (!func)
+ warning("Failed loading symbol '%s' from plugin '%s' (%s)", symbol, _filename.c_str(), dlerror());
+
+ // FIXME HACK: This is a HACK to circumvent a clash between the ISO C++
+ // standard and POSIX: ISO C++ disallows casting between function pointers
+ // and data pointers, but dlsym always returns a void pointer. For details,
+ // see e.g. <http://www.trilithium.com/johan/2004/12/problem-with-dlsym/>.
+ assert(sizeof(VoidFunc) == sizeof(func));
+ VoidFunc tmp;
+ memcpy(&tmp, &func, sizeof(VoidFunc));
+ return tmp;
+ }
+
+public:
+ PS2Plugin(const Common::String &filename)
+ : _dlHandle(0), _filename(filename) {}
+
+ ~PS2Plugin() {
+ if (_dlHandle) unloadPlugin();
+ }
+
+ bool loadPlugin() {
+ assert(!_dlHandle);
+ _dlHandle = dlopen(_filename.c_str(), RTLD_LAZY);
+
+ if (!_dlHandle) {
+ warning("Failed loading plugin '%s' (%s)", _filename.c_str(), dlerror());
+ return false;
+ }
+
+ bool ret = DynamicPlugin::loadPlugin();
+
+ if (ret)
+ dlforgetsyms(_dlHandle);
+
+ return ret;
+ }
+
+ void unloadPlugin() {
+ DynamicPlugin::unloadPlugin();
+ if (_dlHandle) {
+ if (dlclose(_dlHandle) != 0)
+ warning("Failed unloading plugin '%s' (%s)", _filename.c_str(), dlerror());
+ _dlHandle = 0;
+ }
+ }
+};
+
+
+Plugin* PS2PluginProvider::createPlugin(const Common::FSNode &node) const {
+ return new PS2Plugin(node.getPath());
+}
+
+bool PS2PluginProvider::isPluginFilename(const Common::FSNode &node) const {
+ // Check the plugin suffix
+ Common::String filename = node.getName();
+ fprintf(stderr, "Testing name %s", filename.c_str());
+ if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg")) {
+ fprintf(stderr," fail.\n");
+ return false;
+ }
+
+ fprintf(stderr," success!\n");
+ return true;
+}
+
+#endif // defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
diff --git a/backends/platform/psp/thread.cpp b/backends/plugins/ps2/ps2-provider.h
index 88e7b6fe38..6a357db63d 100644
--- a/backends/platform/psp/thread.cpp
+++ b/backends/plugins/ps2/ps2-provider.h
@@ -18,35 +18,26 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.h $
- * $Id: osys_psp.h 49173 2010-05-24 03:05:17Z bluddy $
+ * $URL$
+ * $Id$
*
*/
-#include <time.h>
-#include <psptypes.h>
-#include <psprtc.h>
-#include <pspthreadman.h>
-
-#include "backends/platform/psp/thread.h"
-
-void PspThread::delayMillis(uint32 ms) {
- sceKernelDelayThread(ms * 1000);
-}
-
-void PspThread::delayMicros(uint32 us) {
- sceKernelDelayThread(us);
-}
-
-uint32 PspThread::getMillis() {
- uint32 ticks[2];
- sceRtcGetCurrentTick((u64 *)ticks);
- return (ticks[0]/1000);
-}
-
-uint32 PspThread::getMicros() {
- uint32 ticks[2];
- sceRtcGetCurrentTick((u64 *)ticks);
- return ticks[0];
-}
+#ifndef BACKENDS_PLUGINS_PS2_PS2_PROVIDER_H
+#define BACKENDS_PLUGINS_PS2_PS2_PROVIDER_H
+#include "base/plugins.h"
+
+#if defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
+class PS2PluginProvider : public FilePluginProvider {
+protected:
+ Plugin* createPlugin(const Common::FSNode &node) const;
+
+ bool isPluginFilename(const Common::FSNode &node) const;
+
+};
+
+#endif // defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__)
+
+#endif /* BACKENDS_PLUGINS_PS2_PS2_PROVIDER_H */
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 1ab898d2d6..6a91f2cbe1 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -131,11 +131,11 @@ bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
// There is a nicely portable workaround, too: Make this method overloadable.
if (remove(file.getPath().c_str()) != 0) {
#ifndef _WIN32_WCE
- if (errno == EACCES)
+ /* if (errno == EACCES)
setError(Common::kWritePermissionDenied, "Search or write permission denied: "+file.getName());
if (errno == ENOENT)
- setError(Common::kPathDoesNotExist, "removeSavefile: '"+file.getName()+"' does not exist or path is invalid");
+ setError(Common::kPathDoesNotExist, "removeSavefile: '"+file.getName()+"' does not exist or path is invalid"); */
#endif
return false;
} else {