diff options
Diffstat (limited to 'backends')
220 files changed, 6063 insertions, 3545 deletions
diff --git a/backends/audiocd/audiocd.h b/backends/audiocd/audiocd.h index 5ea5bfcfd4..f218db7f72 100644 --- a/backends/audiocd/audiocd.h +++ b/backends/audiocd/audiocd.h @@ -26,8 +26,8 @@ #ifndef BACKENDS_AUDIOCD_ABSTRACT_H #define BACKENDS_AUDIOCD_ABSTRACT_H -#include "common/noncopyable.h" #include "common/scummsys.h" +#include "common/noncopyable.h" /** * Abstract Audio CD manager class. Subclasses implement the actual diff --git a/backends/audiocd/sdl/sdl-audiocd.cpp b/backends/audiocd/sdl/sdl-audiocd.cpp index b906a3786f..62ab333f54 100644 --- a/backends/audiocd/sdl/sdl-audiocd.cpp +++ b/backends/audiocd/sdl/sdl-audiocd.cpp @@ -25,6 +25,9 @@ #if defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/audiocd/sdl/sdl-audiocd.h" SdlAudioCDManager::SdlAudioCDManager() diff --git a/backends/base-backend.cpp b/backends/base-backend.cpp index aa08e94c32..42ab7b887a 100644 --- a/backends/base-backend.cpp +++ b/backends/base-backend.cpp @@ -25,6 +25,7 @@ #include "backends/base-backend.h" #include "backends/events/default/default-events.h" +#include "backends/audiocd/default/default-audiocd.h" #include "gui/message.h" void BaseBackend::displayMessageOnOSD(const char *msg) { @@ -71,6 +72,14 @@ void BaseBackend::fillScreen(uint32 col) { #define DEFAULT_CONFIG_FILE "scummvm.ini" #endif +BaseBackend::BaseBackend() { + _audiocdManager = 0; +} + +BaseBackend::~BaseBackend() { + delete _audiocdManager; +} + Common::SeekableReadStream *BaseBackend::createConfigReadStream() { Common::FSNode file(DEFAULT_CONFIG_FILE); return file.createReadStream(); @@ -85,12 +94,10 @@ Common::WriteStream *BaseBackend::createConfigWriteStream() { #endif } -static DefaultAudioCDManager *s_audiocdManager = 0; - AudioCDManager *BaseBackend::getAudioCDManager() { - if (!s_audiocdManager) - s_audiocdManager = new DefaultAudioCDManager(); - return (AudioCDManager *)s_audiocdManager; + if (!_audiocdManager) + _audiocdManager = new DefaultAudioCDManager(); + return _audiocdManager; } void BaseBackend::resetGraphicsScale() { diff --git a/backends/base-backend.h b/backends/base-backend.h index bcacde9aad..de94d85523 100644 --- a/backends/base-backend.h +++ b/backends/base-backend.h @@ -28,10 +28,12 @@ #include "common/system.h" #include "backends/events/default/default-events.h" -#include "backends/audiocd/default/default-audiocd.h" class BaseBackend : public OSystem, Common::EventSource { public: + BaseBackend(); + ~BaseBackend(); + virtual Common::EventManager *getEventManager(); virtual void displayMessageOnOSD(const char *msg); virtual void fillScreen(uint32 col); @@ -42,6 +44,9 @@ public: virtual AudioCDManager *getAudioCDManager(); virtual void resetGraphicsScale(); + +protected: + AudioCDManager *_audiocdManager; }; diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index deea8d35ca..379e77a48d 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -25,6 +25,9 @@ #if defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "backends/events/sdl/sdl-events.h" #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp index 4919c04174..2d4102eec6 100644 --- a/backends/fs/ds/ds-fs-factory.cpp +++ b/backends/fs/ds/ds-fs-factory.cpp @@ -22,12 +22,15 @@ * $Id$ */ +// Disable symbol overrides for FILE as that is used in FLAC headers +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #if defined(__DS__) #include "backends/fs/ds/ds-fs-factory.h" #include "backends/fs/ds/ds-fs.h" #include "dsmain.h" //for the isGBAMPAvailable() function -DECLARE_SINGLETON(DSFilesystemFactory) +DECLARE_SINGLETON(DSFilesystemFactory); AbstractFSNode *DSFilesystemFactory::makeRootFileNode() const { if (DS::isGBAMPAvailable()) { diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp index cbc1c054fe..2308824d57 100644 --- a/backends/fs/ds/ds-fs.cpp +++ b/backends/fs/ds/ds-fs.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides for FILE as that is used in FLAC headers +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "common/str.h" #include "common/util.h" //#include <NDS/ARM9/console.h> //basic print funcionality @@ -30,8 +33,7 @@ #include "backends/fs/stdiostream.h" #include "dsmain.h" #include "fat/gba_nds_fat.h" - - +#include "common/bufferedstream.h" namespace DS { @@ -39,9 +41,13 @@ namespace DS { // DSFileSystemNode - Flash ROM file system using Zip files // ////////////////////////////////////////////////////////////// -ZipFile* DSFileSystemNode::_zipFile = NULL; -char currentDir[128]; -bool readPastEndOfFile = false; +ZipFile* DSFileSystemNode::_zipFile = NULL; // FIXME: Avoid non-const global vars +char currentDir[128]; // FIXME: Avoid non-const global vars +bool readPastEndOfFile = false; // FIXME: Avoid non-const global vars + +enum { + WRITE_BUFFER_SIZE = 512 +}; DSFileSystemNode::DSFileSystemNode() { _displayName = "ds:/"; @@ -200,11 +206,12 @@ AbstractFSNode *DSFileSystemNode::getParent() const { } Common::SeekableReadStream *DSFileSystemNode::createReadStream() { - return DSFileStream::makeFromPath(getPath().c_str(), false); + return DSFileStream::makeFromPath(getPath(), false); } Common::WriteStream *DSFileSystemNode::createWriteStream() { - return DSFileStream::makeFromPath(getPath().c_str(), true); + Common::WriteStream *stream = DSFileStream::makeFromPath(getPath(), true); + return Common::wrapBufferedWriteStream(stream, WRITE_BUFFER_SIZE); } ////////////////////////////////////////////////////////////////////////// @@ -380,26 +387,22 @@ Common::SeekableReadStream *GBAMPFileSystemNode::createReadStream() { if (!strncmp(getPath().c_str(), "mp:/", 4)) { return DSFileStream::makeFromPath(getPath().c_str() + 3, false); } else { - return DSFileStream::makeFromPath(getPath().c_str(), false); + return DSFileStream::makeFromPath(getPath(), false); } } Common::WriteStream *GBAMPFileSystemNode::createWriteStream() { - return DSFileStream::makeFromPath(getPath().c_str(), true); + Common::WriteStream *stream = DSFileStream::makeFromPath(getPath(), true); + return Common::wrapBufferedWriteStream(stream, WRITE_BUFFER_SIZE); } - DSFileStream::DSFileStream(void *handle) : _handle(handle) { assert(handle); - _writeBufferPos = 0; } DSFileStream::~DSFileStream() { - if (_writeBufferPos > 0) { - flush(); - } std_fclose((FILE *)_handle); } @@ -416,12 +419,10 @@ bool DSFileStream::eos() const { } int32 DSFileStream::pos() const { - assert(_writeBufferPos == 0); // This method may only be called when reading! return std_ftell((FILE *)_handle); } int32 DSFileStream::size() const { - assert(_writeBufferPos == 0); // This method may only be called when reading! int32 oldPos = std_ftell((FILE *)_handle); std_fseek((FILE *)_handle, 0, SEEK_END); int32 length = std_ftell((FILE *)_handle); @@ -431,39 +432,18 @@ int32 DSFileStream::size() const { } bool DSFileStream::seek(int32 offs, int whence) { - if (_writeBufferPos > 0) { - flush(); - } return std_fseek((FILE *)_handle, offs, whence) == 0; } uint32 DSFileStream::read(void *ptr, uint32 len) { - if (_writeBufferPos > 0) { - flush(); - } return std_fread(ptr, 1, len, (FILE *)_handle); } uint32 DSFileStream::write(const void *ptr, uint32 len) { - if (_writeBufferPos + len < WRITE_BUFFER_SIZE) { - memcpy(_writeBuffer + _writeBufferPos, ptr, len); - _writeBufferPos += len; - return len; - } else { - if (_writeBufferPos > 0) { - flush(); - } - return std_fwrite(ptr, 1, len, (FILE *)_handle); - } + return std_fwrite(ptr, 1, len, (FILE *)_handle); } bool DSFileStream::flush() { - - if (_writeBufferPos > 0) { - std_fwrite(_writeBuffer, 1, _writeBufferPos, (FILE *) _handle); - _writeBufferPos = 0; - } - return std_fflush((FILE *)_handle) == 0; } @@ -476,15 +456,13 @@ DSFileStream *DSFileStream::makeFromPath(const Common::String &path, bool writeM } - - // Stdio replacements enum { MAX_FILE_HANDLES = 32 }; -static bool inited = false; -static DS::fileHandle s_handle[MAX_FILE_HANDLES]; +static bool inited = false; // FIXME: Avoid non-const global vars +static DS::fileHandle s_handle[MAX_FILE_HANDLES]; // FIXME: Avoid non-const global vars FILE *std_fopen(const char *name, const char *mode) { if (!inited) { @@ -694,18 +672,18 @@ int std_fseek(FILE *handle, long int offset, int whence) { } switch (whence) { - case SEEK_CUR: - handle->pos += offset; - break; - case SEEK_SET: - handle->pos = offset; - break; - case SEEK_END: - handle->pos = handle->size + offset; - break; - default: - handle->pos = offset; - break; + case SEEK_CUR: + handle->pos += offset; + break; + case SEEK_SET: + handle->pos = offset; + break; + case SEEK_END: + handle->pos = handle->size + offset; + break; + default: + handle->pos = offset; + break; } return 0; diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h index 6961022848..c891dac8f9 100644 --- a/backends/fs/ds/ds-fs.h +++ b/backends/fs/ds/ds-fs.h @@ -171,16 +171,10 @@ struct fileHandle { class DSFileStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable { protected: - enum { - WRITE_BUFFER_SIZE = 512 - }; /** File handle to the actual file. */ void *_handle; - char _writeBuffer[WRITE_BUFFER_SIZE]; - int _writeBufferPos; - public: /** * Given a path, invokes fopen on that path and wrap the result in a @@ -205,6 +199,14 @@ public: }; +// FIXME/TODO: Get rid of the following hacks. Top priority: Get rid of +// the 'FILE' (re)definition. Simply calling it STD_FILE or so wold already +// suffice (need to adjust affected code, of course). +// Once the OSystem::logMessage() patch is in SVN, we should also be +// able to get rid of stderr, stdout, stdin. +// Moreover, the std_FOO() functions could then be moved to a private +// header, or even completely merged into DSFileStream, and all other +// DS code switch to use that. #undef stderr #undef stdout #undef stdin diff --git a/backends/fs/n64/romfsstream.cpp b/backends/fs/n64/romfsstream.cpp index 2d30f852ca..c833a228f5 100644 --- a/backends/fs/n64/romfsstream.cpp +++ b/backends/fs/n64/romfsstream.cpp @@ -59,7 +59,7 @@ int32 RomfsStream::size() const { } bool RomfsStream::seek(int32 offs, int whence) { - return romfs_seek((ROMFILE *)_handle, offs, whence) == 0; + return romfs_seek((ROMFILE *)_handle, offs, whence) >= 0; } uint32 RomfsStream::read(void *ptr, uint32 len) { diff --git a/backends/fs/ps2/ps2-fs-factory.cpp b/backends/fs/ps2/ps2-fs-factory.cpp index 8d3c22d2d0..8b5202bff4 100644 --- a/backends/fs/ps2/ps2-fs-factory.cpp +++ b/backends/fs/ps2/ps2-fs-factory.cpp @@ -23,10 +23,14 @@ */ #if defined(__PLAYSTATION2__) + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/fs/ps2/ps2-fs-factory.h" #include "backends/fs/ps2/ps2-fs.cpp" -DECLARE_SINGLETON(Ps2FilesystemFactory) +DECLARE_SINGLETON(Ps2FilesystemFactory); AbstractFSNode *Ps2FilesystemFactory::makeRootFileNode() const { return new Ps2FilesystemNode(); diff --git a/backends/fs/psp/psp-fs-factory.cpp b/backends/fs/psp/psp-fs-factory.cpp index 7a22954919..7ed84de034 100644 --- a/backends/fs/psp/psp-fs-factory.cpp +++ b/backends/fs/psp/psp-fs-factory.cpp @@ -26,7 +26,7 @@ #include "backends/fs/psp/psp-fs-factory.h" #include "backends/fs/psp/psp-fs.cpp" -DECLARE_SINGLETON(PSPFilesystemFactory) +DECLARE_SINGLETON(PSPFilesystemFactory); AbstractFSNode *PSPFilesystemFactory::makeRootFileNode() const { return new PSPFilesystemNode(); diff --git a/backends/fs/psp/psp-fs.cpp b/backends/fs/psp/psp-fs.cpp index 5b3d298001..16a0e9cd5b 100644 --- a/backends/fs/psp/psp-fs.cpp +++ b/backends/fs/psp/psp-fs.cpp @@ -27,6 +27,7 @@ #include "engines/engine.h" #include "backends/fs/abstract-fs.h" #include "backends/fs/psp/psp-stream.h" +#include "common/bufferedstream.h" #include <sys/stat.h> #include <unistd.h> @@ -251,7 +252,7 @@ Common::SeekableReadStream *PSPFilesystemNode::createReadStream() { Common::SeekableReadStream *stream = PspIoStream::makeFromPath(getPath(), false); - return new Common::BufferedSeekableReadStream(stream, READ_BUFFER_SIZE, DisposeAfterUse::YES); + return Common::wrapBufferedSeekableReadStream(stream, READ_BUFFER_SIZE, DisposeAfterUse::YES); } Common::WriteStream *PSPFilesystemNode::createWriteStream() { @@ -259,7 +260,7 @@ Common::WriteStream *PSPFilesystemNode::createWriteStream() { Common::WriteStream *stream = PspIoStream::makeFromPath(getPath(), true); - return new Common::BufferedWriteStream(stream, WRITE_BUFFER_SIZE, DisposeAfterUse::YES); + return Common::wrapBufferedWriteStream(stream, WRITE_BUFFER_SIZE); } #endif //#ifdef __PSP__ diff --git a/backends/fs/stdiostream.cpp b/backends/fs/stdiostream.cpp index 8845d796c6..d0600f41a6 100644 --- a/backends/fs/stdiostream.cpp +++ b/backends/fs/stdiostream.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use FILE, fopen etc. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/fs/stdiostream.h" StdioStream::StdioStream(void *handle) : _handle(handle) { diff --git a/backends/fs/wii/wii-fs-factory.cpp b/backends/fs/wii/wii-fs-factory.cpp index 2e8051029d..6a11d7d12e 100644 --- a/backends/fs/wii/wii-fs-factory.cpp +++ b/backends/fs/wii/wii-fs-factory.cpp @@ -37,7 +37,7 @@ #include <smb.h> #endif -DECLARE_SINGLETON(WiiFilesystemFactory) +DECLARE_SINGLETON(WiiFilesystemFactory); WiiFilesystemFactory::WiiFilesystemFactory() : _dvdMounted(false), diff --git a/backends/fs/windows/windows-fs-factory.cpp b/backends/fs/windows/windows-fs-factory.cpp index c74868b40d..f7b9c837f2 100644 --- a/backends/fs/windows/windows-fs-factory.cpp +++ b/backends/fs/windows/windows-fs-factory.cpp @@ -23,6 +23,10 @@ */ #if defined(WIN32) + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/fs/windows/windows-fs-factory.h" #include "backends/fs/windows/windows-fs.cpp" diff --git a/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.cpp b/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.cpp deleted file mode 100644 index 8cb3eed083..0000000000 --- a/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.cpp +++ /dev/null @@ -1,445 +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$ - * - */ - -#ifdef GP2XWIZ - -#include "backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h" -#include "backends/events/gp2xsdl/gp2xsdl-events.h" - -#include "common/mutex.h" -#include "graphics/scaler/aspect.h" -#include "graphics/scaler/downscaler.h" - -static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"1x", "Fullscreen", GFX_NORMAL}, -// {"½x", "Downscale", GFX_HALF}, - {0, 0, 0} -}; - -const OSystem::GraphicsMode *GP2XWIZSdlGraphicsManager::getSupportedGraphicsModes() const { - return s_supportedGraphicsModes; -} - -int GP2XWIZSdlGraphicsManager::getDefaultGraphicsMode() const { - return GFX_NORMAL; -} - -bool GP2XWIZSdlGraphicsManager::setGraphicsMode(int mode) { - Common::StackLock lock(_graphicsMutex); - - assert(_transactionMode == kTransactionActive); - - if (_oldVideoMode.setup && _oldVideoMode.mode == mode) - return true; - - int newScaleFactor = 1; - - switch (mode) { - case GFX_NORMAL: - newScaleFactor = 1; - break; - case GFX_HALF: - newScaleFactor = 1; - break; - default: - warning("unknown gfx mode %d", mode); - return false; - } - - _transactionDetails.normal1xScaler = (mode == GFX_NORMAL); - if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor) - _transactionDetails.needHotswap = true; - - _transactionDetails.needUpdatescreen = true; - - _videoMode.mode = mode; - _videoMode.scaleFactor = newScaleFactor; - - return true; -} - -void GP2XWIZSdlGraphicsManager::setGraphicsModeIntern() { - Common::StackLock lock(_graphicsMutex); - ScalerProc *newScalerProc = 0; - - switch (_videoMode.mode) { - case GFX_NORMAL: - newScalerProc = Normal1x; - break; - case GFX_HALF: - newScalerProc = DownscaleAllByHalf; - break; - - default: - error("Unknown gfx mode %d", _videoMode.mode); - } - - _scalerProc = newScalerProc; - - if (!_screen || !_hwscreen) - return; - - // Blit everything to the screen - _forceFull = true; - - // Even if the old and new scale factors are the same, we may have a - // different scaler for the cursor now. - blitCursor(); -} - -void GP2XWIZSdlGraphicsManager::initSize(uint w, uint h) { - assert(_transactionMode == kTransactionActive); - - // Avoid redundant res changes - if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight) - return; - - _videoMode.screenWidth = w; - _videoMode.screenHeight = h; - if (w > 320 || h > 240){ - setGraphicsMode(GFX_HALF); - setGraphicsModeIntern(); - ((GP2XSdlEventManager *)g_system->getEventManager())->toggleMouseGrab(); - } - - _transactionDetails.sizeChanged = true; -} - -bool GP2XWIZSdlGraphicsManager::loadGFXMode() { - _videoMode.overlayWidth = 320; - _videoMode.overlayHeight = 240; - _videoMode.fullscreen = true; - - if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400) - _videoMode.aspectRatioCorrection = false; - - return SdlGraphicsManager::loadGFXMode(); -} - -void GP2XWIZSdlGraphicsManager::drawMouse() { - if (!_mouseVisible || !_mouseSurface) { - _mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0; - return; - } - - SDL_Rect dst; - int scale; - int hotX, hotY; - - if (_videoMode.mode == GFX_HALF && !_overlayVisible){ - dst.x = _mouseCurState.x/2; - dst.y = _mouseCurState.y/2; - } else { - dst.x = _mouseCurState.x; - dst.y = _mouseCurState.y; - } - - if (!_overlayVisible) { - scale = _videoMode.scaleFactor; - dst.w = _mouseCurState.vW; - dst.h = _mouseCurState.vH; - hotX = _mouseCurState.vHotX; - hotY = _mouseCurState.vHotY; - } else { - scale = 1; - dst.w = _mouseCurState.rW; - dst.h = _mouseCurState.rH; - hotX = _mouseCurState.rHotX; - hotY = _mouseCurState.rHotY; - } - - // The mouse is undrawn using virtual coordinates, i.e. they may be - // scaled and aspect-ratio corrected. - - _mouseBackup.x = dst.x - hotX; - _mouseBackup.y = dst.y - hotY; - _mouseBackup.w = dst.w; - _mouseBackup.h = dst.h; - - // We draw the pre-scaled cursor image, so now we need to adjust for - // scaling, shake position and aspect ratio correction manually. - - if (!_overlayVisible) { - dst.y += _currentShakePos; - } - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - dst.y = real2Aspect(dst.y); - - dst.x = scale * dst.x - _mouseCurState.rHotX; - dst.y = scale * dst.y - _mouseCurState.rHotY; - dst.w = _mouseCurState.rW; - dst.h = _mouseCurState.rH; - - // Note that SDL_BlitSurface() and addDirtyRect() will both perform any - // clipping necessary - - if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0) - error("SDL_BlitSurface failed: %s", SDL_GetError()); - - // The screen will be updated using real surface coordinates, i.e. - // they will not be scaled or aspect-ratio corrected. - addDirtyRect(dst.x, dst.y, dst.w, dst.h, true); -} - -void GP2XWIZSdlGraphicsManager::undrawMouse() { - const int x = _mouseBackup.x; - const int y = _mouseBackup.y; - - // When we switch bigger overlay off mouse jumps. Argh! - // This is intended to prevent undrawing offscreen mouse - if (!_overlayVisible && (x >= _videoMode.screenWidth || y >= _videoMode.screenHeight)) - return; - - if (_mouseBackup.w != 0 && _mouseBackup.h != 0){ - if (_videoMode.mode == GFX_HALF && !_overlayVisible){ - addDirtyRect(x*2, y*2, _mouseBackup.w*2, _mouseBackup.h*2); - } else { - addDirtyRect(x, y, _mouseBackup.w, _mouseBackup.h); - } - } -} - -void GP2XWIZSdlGraphicsManager::internUpdateScreen() { - SDL_Surface *srcSurf, *origSurf; - int height, width; - ScalerProc *scalerProc; - int scale1; - -#if defined (DEBUG) && ! defined(_WIN32_WCE) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?) - assert(_hwscreen != NULL); - assert(_hwscreen->map->sw_data != NULL); -#endif - - // If the shake position changed, fill the dirty area with blackness - if (_currentShakePos != _newShakePos) { - SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor}; - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - blackrect.h = real2Aspect(blackrect.h - 1) + 1; - - SDL_FillRect(_hwscreen, &blackrect, 0); - - _currentShakePos = _newShakePos; - - _forceFull = true; - } - - // Check whether the palette was changed in the meantime and update the - // screen surface accordingly. - if (_screen && _paletteDirtyEnd != 0) { - SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart, - _paletteDirtyStart, - _paletteDirtyEnd - _paletteDirtyStart); - - _paletteDirtyEnd = 0; - - _forceFull = true; - } - -#ifdef USE_OSD - // OSD visible (i.e. non-transparent)? - if (_osdAlpha != SDL_ALPHA_TRANSPARENT) { - // Updated alpha value - const int diff = SDL_GetTicks() - _osdFadeStartTime; - if (diff > 0) { - if (diff >= kOSDFadeOutDuration) { - // Back to full transparency - _osdAlpha = SDL_ALPHA_TRANSPARENT; - } else { - // Do a linear fade out... - const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100; - _osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration; - } - SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha); - _forceFull = true; - } - } -#endif - - if (!_overlayVisible) { - origSurf = _screen; - srcSurf = _tmpscreen; - width = _videoMode.screenWidth; - height = _videoMode.screenHeight; - scalerProc = _scalerProc; - scale1 = _videoMode.scaleFactor; - } else { - origSurf = _overlayscreen; - srcSurf = _tmpscreen2; - width = _videoMode.overlayWidth; - height = _videoMode.overlayHeight; - scalerProc = Normal1x; - - scale1 = 1; - } - - // Add the area covered by the mouse cursor to the list of dirty rects if - // we have to redraw the mouse. - if (_mouseNeedsRedraw) - undrawMouse(); - - // Force a full redraw if requested - if (_forceFull) { - _numDirtyRects = 1; - _dirtyRectList[0].x = 0; - _dirtyRectList[0].y = 0; - _dirtyRectList[0].w = width; - _dirtyRectList[0].h = height; - } - - // Only draw anything if necessary - if (_numDirtyRects > 0 || _mouseNeedsRedraw) { - SDL_Rect *r; - SDL_Rect dst; - uint32 srcPitch, dstPitch; - SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects; - - for (r = _dirtyRectList; r != lastRect; ++r) { - dst = *r; - dst.x++; // Shift rect by one since 2xSai needs to access the data around - dst.y++; // any pixel to scale it, and we want to avoid mem access crashes. - - if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0) - error("SDL_BlitSurface failed: %s", SDL_GetError()); - } - - SDL_LockSurface(srcSurf); - SDL_LockSurface(_hwscreen); - - srcPitch = srcSurf->pitch; - dstPitch = _hwscreen->pitch; - - for (r = _dirtyRectList; r != lastRect; ++r) { - register int dst_y = r->y + _currentShakePos; - register int dst_h = 0; - register int dst_w = r->w; - register int orig_dst_y = 0; - register int dst_x = r->x; - register int src_y; - register int src_x; - - if (dst_y < height) { - dst_h = r->h; - if (dst_h > height - dst_y) - dst_h = height - dst_y; - - orig_dst_y = dst_y; - src_x = dst_x; - src_y = dst_y; - - if (_videoMode.aspectRatioCorrection && !_overlayVisible) - dst_y = real2Aspect(dst_y); - - assert(scalerProc != NULL); - - if (_videoMode.mode == GFX_HALF && scalerProc == DownscaleAllByHalf){ - if (dst_x%2==1){ - dst_x--; - dst_w++; - } - if (dst_y%2==1){ - dst_y--; - dst_h++; - } - src_x = dst_x; - src_y = dst_y; - dst_x = dst_x / 2; - dst_y = dst_y / 2; - } - scalerProc((byte *)srcSurf->pixels + (src_x * 2 + 2) + (src_y + 1) * srcPitch, srcPitch, - (byte *)_hwscreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, dst_w, dst_h); - } - - if (_videoMode.mode == GFX_HALF && scalerProc == DownscaleAllByHalf){ - r->w = r->w / 2; - r->h = dst_h / 2; - } else { - r->w = r->w; - r->h = dst_h; - } - - r->x = dst_x; - r->y = dst_y; - - -#ifdef USE_SCALERS - if (_videoMode.aspectRatioCorrection && orig_dst_y < height && !_overlayVisible) - r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1); -#endif - } - SDL_UnlockSurface(srcSurf); - SDL_UnlockSurface(_hwscreen); - - // Readjust the dirty rect list in case we are doing a full update. - // This is necessary if shaking is active. - if (_forceFull) { - _dirtyRectList[0].y = 0; - _dirtyRectList[0].h = (_videoMode.mode == GFX_HALF) ? effectiveScreenHeight()/2 : effectiveScreenHeight(); - } - - drawMouse(); - -#ifdef USE_OSD - if (_osdAlpha != SDL_ALPHA_TRANSPARENT) { - SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0); - } -#endif - // Finally, blit all our changes to the screen - SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList); - } - - _numDirtyRects = 0; - _forceFull = false; - _mouseNeedsRedraw = false; -} - -void GP2XWIZSdlGraphicsManager::showOverlay() { - if (_videoMode.mode == GFX_HALF){ - _mouseCurState.x = _mouseCurState.x / 2; - _mouseCurState.y = _mouseCurState.y / 2; - } - SdlGraphicsManager::showOverlay(); -} - -void GP2XWIZSdlGraphicsManager::hideOverlay() { - if (_videoMode.mode == GFX_HALF){ - _mouseCurState.x = _mouseCurState.x * 2; - _mouseCurState.y = _mouseCurState.y * 2; - } - SdlGraphicsManager::hideOverlay(); -} - -void GP2XWIZSdlGraphicsManager::warpMouse(int x, int y) { - if (_mouseCurState.x != x || _mouseCurState.y != y) { - if (_videoMode.mode == GFX_HALF && !_overlayVisible){ - x = x / 2; - y = y / 2; - } - } - SdlGraphicsManager::warpMouse(x, y); -} - -#endif diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index 151795a9d8..8e36077ecb 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -25,6 +25,9 @@ #if defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "backends/graphics/sdl/sdl-graphics.h" #include "backends/events/sdl/sdl-events.h" #include "backends/platform/sdl/sdl.h" @@ -698,7 +701,7 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w bool SdlGraphicsManager::loadGFXMode() { _forceFull = true; -#if !defined(__MAEMO__) && !defined(GP2XWIZ) && !defined(LINUXMOTO) && !defined(DINGUX) +#if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) && !defined(OPENPANDORA) _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor; _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor; diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index 067d8453a5..2f913055fc 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -26,9 +26,9 @@ #ifdef ENABLE_KEYMAPPER -#include "gui/GuiManager.h" -#include "gui/PopUpWidget.h" -#include "gui/ScrollBarWidget.h" +#include "gui/gui-manager.h" +#include "gui/widgets/popup.h" +#include "gui/widgets/scrollbar.h" #include "gui/ThemeEval.h" #include "common/translation.h" diff --git a/backends/log/log.cpp b/backends/log/log.cpp new file mode 100644 index 0000000000..3ba1d67b16 --- /dev/null +++ b/backends/log/log.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$ + * + */ + +#include "backends/log/log.h" + +#include "common/stream.h" +#include "common/str.h" +#include "common/system.h" + +#include "base/version.h" + +namespace Backends { +namespace Log { + +Log::Log(OSystem *system) + : _system(system), _stream(0), _startOfLine(true) { + assert(system); +} + +void Log::open(Common::WriteStream *stream) { + // Close the previous log + close(); + + _stream = stream; + + // Output information about the ScummVM version at the start of the log + // file + print(gScummVMFullVersion); + print("\n"); + print(gScummVMFeatures); + print("\n"); + print("--- Log opened.\n"); + _startOfLine = true; +} + +void Log::close() { + if (_stream) { + // Output a message to indicate that the log was closed successfully + print("--- Log closed successfully.\n"); + + delete _stream; + _stream = 0; + } +} + +void Log::print(const char *message, const bool printTime) { + if (!_stream) + return; + + while (*message) { + if (_startOfLine) { + _startOfLine = false; + if (printTime) + printTimeStamp(); + } + + const char *msgStart = message; + // scan for end of line/string + while (*message && *message != '\n') + ++message; + + if (*message == '\n') { + ++message; + _startOfLine = true; + } + + // TODO: It might be wise to check for write errors and/or incomplete + // writes here, since losing certain bits of the log is not nice. + _stream->write(msgStart, message - msgStart); + } + + _stream->flush(); +} + +void Log::printTimeStamp() { + TimeDate date; + _system->getTimeAndDate(date); + + _stream->writeString(Common::String::format("[%d-%02d-%02d %02d:%02d:%02d] ", + date.tm_year + 1900, date.tm_mon, date.tm_mday, + date.tm_hour, date.tm_min, date.tm_sec)); +} + +} // End of namespace Log +} // End of namespace Backends + diff --git a/backends/log/log.h b/backends/log/log.h new file mode 100644 index 0000000000..b869191541 --- /dev/null +++ b/backends/log/log.h @@ -0,0 +1,132 @@ +/* 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_LOG_LOG_H +#define BACKENDS_LOG_LOG_H + +#include "common/scummsys.h" + +class OSystem; + +namespace Common { +class WriteStream; +} // End of namespace Common + +namespace Backends { +namespace Log { + +/** + * Log file writer. + * + * This can be used by the backends to implement file logging functionality. + */ +class Log { +public: + /** + * Constructor for the logger object. + * + * @param system The OSystem instance to use. Must be non-null. + */ + Log(OSystem *system); + ~Log() { close(); } + + /** + * Opens a new log file. + * + * The previous log, which was handled by this logger, will be closed + * before the new stream is associated. + * + * The current implemention will always call flush after data is written + * to the log file. It might thus be wise to pass an unbuffered write + * stream here to avoid unnecessary overhead. + * @see Common::WriteStream::flush + * + * Calling open with stream being 0 is valid and will result in the same + * behavior as calling close, but it may have additional overhead. + * @see close + * + * This function will output information about the ScummVM version and + * the features built into ScummVM automatically. It will also add a short + * notice to indicate that the log was opened successfully. + * + * @param stream Stream where to output the log contents. + * Note that the stream will be deleted by the logger. + */ + void open(Common::WriteStream *stream); + + /** + * Closes the current log file. + * + * This function will output a line saying that the log was closed + * successfully. This can be used to check whether a log is incomplete + * because of whatever reasons. + */ + void close(); + + /** + * Prints a message to the log stream. + * + * This has optional support to output a timestamp on every new line. + * The timestamp will look like: "[YYYY-MM-DD HH:MM:SS] ". + * Printing of a timestamp is done by default. + * + * It might be noteworthy that this function does not append a new line + * to the given message. + * + * In case no stream is associated with this logger, this function will + * quit immediatly. + * + * @param message The message to write. + * @param printTimeOnNewline Whether to print a timestamp on the start of + * a new line. + */ + void print(const char *message, const bool printTimeOnNewline = true); +private: + /** + * Prints a time stamp in the form: "[YYYY-MM-DD HH:MM:SS] ". + */ + void printTimeStamp(); + + /** + * The OSystem instance used to query data like the time. + */ + OSystem *_system; + + /** + * Where to write the output too. + */ + Common::WriteStream *_stream; + + /** + * Whether we are at the start of a line. + */ + bool _startOfLine; +}; + +} // End of namespace Log +} // End of namespace Backends + +#endif + diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp index 4f73d7384b..fd32777a1b 100644 --- a/backends/midi/alsa.cpp +++ b/backends/midi/alsa.cpp @@ -22,6 +22,9 @@ * $Id$ */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(USE_ALSA) diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp index 3486532549..7bf702de58 100644 --- a/backends/midi/camd.cpp +++ b/backends/midi/camd.cpp @@ -22,6 +22,9 @@ * $Id$ */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(__amigaos4__) diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp index aa0ad75f0a..97db5cb292 100644 --- a/backends/midi/coreaudio.cpp +++ b/backends/midi/coreaudio.cpp @@ -24,6 +24,9 @@ #ifdef MACOSX +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + // HACK to disable deprecated warnings under Mac OS X 10.5. // Apple depracted the AUGraphNewNode & AUGraphGetNodeInfo APIs // in favor of the new AUGraphAddNode & AUGraphNodeInfo APIs. diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp index 08f36a8b0f..bca16df61a 100644 --- a/backends/midi/coremidi.cpp +++ b/backends/midi/coremidi.cpp @@ -24,6 +24,9 @@ #ifdef MACOSX +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/config-manager.h" #include "common/util.h" #include "sound/musicplugin.h" diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp index 8c006b2cd9..5e4088fa17 100644 --- a/backends/midi/dmedia.cpp +++ b/backends/midi/dmedia.cpp @@ -29,6 +29,9 @@ #if defined(IRIX) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include "common/util.h" #include "common/config-manager.h" diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp index e3d2c35b39..c0098742d0 100644 --- a/backends/midi/seq.cpp +++ b/backends/midi/seq.cpp @@ -28,6 +28,9 @@ * both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html) */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(USE_SEQ_MIDI) diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp index b00188dfea..01e28aa5ca 100644 --- a/backends/midi/stmidi.cpp +++ b/backends/midi/stmidi.cpp @@ -36,6 +36,9 @@ #if defined __MINT__ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include <osbind.h> #include "sound/mpu401.h" #include "common/util.h" diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp index 16c1cc43be..d79a83809f 100644 --- a/backends/midi/timidity.cpp +++ b/backends/midi/timidity.cpp @@ -34,6 +34,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #if defined(USE_TIMIDITY) diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index 31f057df18..81b29219b4 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -24,6 +24,9 @@ #if defined(WIN32) && !defined(_WIN32_WCE) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #define WIN32_LEAN_AND_MEAN #include <windows.h> // winnt.h defines ARRAYSIZE, but we want our own one... diff --git a/backends/module.mk b/backends/module.mk index 8cada4d94f..96dfbda9c4 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -20,7 +20,6 @@ MODULE_OBJS := \ fs/windows/windows-fs-factory.o \ graphics/dinguxsdl/dinguxsdl-graphics.o \ graphics/gp2xsdl/gp2xsdl-graphics.o \ - graphics/gp2xwizsdl/gp2xwizsdl-graphics.o \ graphics/linuxmotosdl/linuxmotosdl-graphics.o \ graphics/opengl/glerrorcheck.o \ graphics/opengl/gltexture.o \ @@ -32,6 +31,7 @@ MODULE_OBJS := \ keymapper/keymap.o \ keymapper/keymapper.o \ keymapper/remap-dialog.o \ + log/log.o \ midi/alsa.o \ midi/camd.o \ midi/coreaudio.o \ @@ -45,6 +45,13 @@ MODULE_OBJS := \ mixer/sdl/sdl-mixer.o \ mixer/symbiansdl/symbiansdl-mixer.o \ mutex/sdl/sdl-mutex.o \ + plugins/elf/elf-loader.o \ + plugins/elf/mips-loader.o \ + plugins/elf/shorts-segment-manager.o \ + plugins/elf/ppc-loader.o \ + plugins/elf/arm-loader.o \ + plugins/elf/elf-provider.o \ + plugins/elf/version.o \ plugins/posix/posix-provider.o \ plugins/sdl/sdl-provider.o \ plugins/win32/win32-provider.o \ @@ -67,7 +74,8 @@ endif ifeq ($(BACKEND),ds) MODULE_OBJS += \ fs/ds/ds-fs-factory.o \ - fs/ds/ds-fs.o + fs/ds/ds-fs.o \ + plugins/ds/ds-provider.o endif ifeq ($(BACKEND),n64) @@ -78,7 +86,8 @@ endif ifeq ($(BACKEND),ps2) MODULE_OBJS += \ - fs/ps2/ps2-fs-factory.o + fs/ps2/ps2-fs-factory.o \ + plugins/ps2/ps2-provider.o endif ifeq ($(BACKEND),psp) @@ -92,7 +101,8 @@ endif ifeq ($(BACKEND),wii) MODULE_OBJS += \ - fs/wii/wii-fs-factory.o + fs/wii/wii-fs-factory.o \ + plugins/wii/wii-provider.o endif # Include common rules diff --git a/backends/mutex/sdl/sdl-mutex.cpp b/backends/mutex/sdl/sdl-mutex.cpp index 737126057c..46ce269417 100644 --- a/backends/mutex/sdl/sdl-mutex.cpp +++ b/backends/mutex/sdl/sdl-mutex.cpp @@ -25,6 +25,9 @@ #if defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "backends/mutex/sdl/sdl-mutex.h" #if defined(__SYMBIAN32__) diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build index 1c407bd469..f3fb77cbcf 100644 --- a/backends/platform/android/README.build +++ b/backends/platform/android/README.build @@ -82,7 +82,8 @@ Then build ScummVM: export ANDROID_TOP=<root of built Android source> - ./configure --backend=android --host=android --enable-zlib #and any other flags + ./configure --backend=android --host=android --enable-zlib --disable-timidity + # ... and any other configure flags you want make scummvm.apk This will build a "monolithic" ScummVM package, with the engines diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index dcc4e37458..7a4ae24e6b 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -109,7 +109,7 @@ static void JNU_ThrowByName(JNIEnv* env, const char* name, const char* msg) { env->DeleteLocalRef(cls); } -// floating point. use sparingly. +// floating point. use sparingly. template <class T> static inline T scalef(T in, float numerator, float denominator) { return static_cast<float>(in) * numerator / denominator; @@ -177,7 +177,6 @@ private: GLESPaletteTexture* _game_texture; int _shake_offset; Common::Rect _focus_rect; - bool _full_screen_dirty; // Overlay layer GLES4444Texture* _overlay_texture; @@ -300,6 +299,7 @@ public: virtual void getTimeAndDate(TimeDate &t) const; virtual Common::TimerManager *getTimerManager(); virtual FilesystemFactory *getFilesystemFactory(); + virtual void logMessage(LogMessageType::Type type, const char *message); virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); }; @@ -320,7 +320,6 @@ OSystem_Android::OSystem_Android(jobject am) _fsFactory(new POSIXFilesystemFactory()), _asset_archive(new AndroidAssetArchive(am)), _shake_offset(0), - _full_screen_dirty(false), _event_queue_lock(createMutex()) { } @@ -862,6 +861,9 @@ void OSystem_Android::hideOverlay() { void OSystem_Android::clearOverlay() { ENTER("clearOverlay()"); _overlay_texture->fillBuffer(0); + + // Shouldn't need this, but works around a 'blank screen' bug on Nexus1 + updateScreen(); } void OSystem_Android::grabOverlay(OverlayColor *buf, int pitch) { @@ -887,6 +889,9 @@ void OSystem_Android::copyRectToOverlay(const OverlayColor *buf, int pitch, // This 'pitch' is pixels not bytes _overlay_texture->updateBuffer(x, y, w, h, buf, pitch * sizeof(buf[0])); + + // Shouldn't need this, but works around a 'blank screen' bug on Nexus1? + updateScreen(); } int16 OSystem_Android::getOverlayHeight() { @@ -1262,6 +1267,23 @@ void OSystem_Android::addSysArchivesToSearchSet(Common::SearchSet &s, } } +void OSystem_Android::logMessage(LogMessageType::Type type, const char *message) { + switch (type) { + case LogMessageType::kDebug: + BaseBackend::logMessage(type, message); + break; + + case LogMessageType::kWarning: + __android_log_write(ANDROID_LOG_WARN, "ScummVM", message); + break; + + case LogMessageType::kError: + // FIXME: From the name it looks like this will also quit the program. + // This shouldn't do that though. + __android_log_assert("Fatal error", "ScummVM", "%s", message); + break; + } +} static jint ScummVM_scummVMMain(JNIEnv* env, jobject self, jobjectArray args) { OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self); diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java index d39aa363ef..6986f3988d 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java @@ -23,6 +23,8 @@ import javax.microedition.khronos.egl.EGLSurface; import java.io.File; import java.util.concurrent.Semaphore; +import java.util.Map; +import java.util.LinkedHashMap; // At least in Android 2.1, eglCreateWindowSurface() requires an @@ -109,6 +111,51 @@ public class ScummVM implements SurfaceHolder.Callback { } } + // For debugging + private static final Map<String, Integer> attribs; + static { + attribs = new LinkedHashMap<String, Integer>(); + attribs.put("CONFIG_ID", EGL10.EGL_CONFIG_ID); + attribs.put("BUFFER_SIZE", EGL10.EGL_BUFFER_SIZE); + attribs.put("RED_SIZE", EGL10.EGL_RED_SIZE); + attribs.put("GREEN_SIZE", EGL10.EGL_GREEN_SIZE); + attribs.put("BLUE_SIZE", EGL10.EGL_BLUE_SIZE); + attribs.put("ALPHA_SIZE", EGL10.EGL_ALPHA_SIZE); + //attribs.put("BIND_TO_RGB", EGL10.EGL_BIND_TO_TEXTURE_RGB); + //attribs.put("BIND_TO_RGBA", EGL10.EGL_BIND_TO_TEXTURE_RGBA); + attribs.put("CONFIG_CAVEAT", EGL10.EGL_CONFIG_CAVEAT); + attribs.put("DEPTH_SIZE", EGL10.EGL_DEPTH_SIZE); + attribs.put("LEVEL", EGL10.EGL_LEVEL); + attribs.put("MAX_PBUFFER_WIDTH", EGL10.EGL_MAX_PBUFFER_WIDTH); + attribs.put("MAX_PBUFFER_HEIGHT", EGL10.EGL_MAX_PBUFFER_HEIGHT); + attribs.put("MAX_PBUFFER_PIXELS", EGL10.EGL_MAX_PBUFFER_PIXELS); + //attribs.put("MAX_SWAP_INTERVAL", EGL10.EGL_MAX_SWAP_INTERVAL); + //attribs.put("MIN_SWAP_INTERVAL", EGL10.EGL_MIN_SWAP_INTERVAL); + attribs.put("NATIVE_RENDERABLE", EGL10.EGL_NATIVE_RENDERABLE); + attribs.put("NATIVE_VISUAL_ID", EGL10.EGL_NATIVE_VISUAL_ID); + attribs.put("NATIVE_VISUAL_TYPE", EGL10.EGL_NATIVE_VISUAL_TYPE); + attribs.put("SAMPLE_BUFFERS", EGL10.EGL_SAMPLE_BUFFERS); + attribs.put("SAMPLES", EGL10.EGL_SAMPLES); + attribs.put("STENCIL_SIZE", EGL10.EGL_STENCIL_SIZE); + attribs.put("SURFACE_TYPE", EGL10.EGL_SURFACE_TYPE); + attribs.put("TRANSPARENT_TYPE", EGL10.EGL_TRANSPARENT_TYPE); + attribs.put("TRANSPARENT_RED_VALUE", EGL10.EGL_TRANSPARENT_RED_VALUE); + attribs.put("TRANSPARENT_GREEN_VALUE", EGL10.EGL_TRANSPARENT_GREEN_VALUE); + attribs.put("TRANSPARENT_BLUE_VALUE", EGL10.EGL_TRANSPARENT_BLUE_VALUE); + } + private void dumpEglConfig(EGLConfig config) { + int[] value = new int[1]; + for (Map.Entry<String, Integer> entry : attribs.entrySet()) { + egl.eglGetConfigAttrib(eglDisplay, config, + entry.getValue(), value); + if (value[0] == EGL10.EGL_NONE) + Log.d(LOG_TAG, entry.getKey() + ": NONE"); + else + Log.d(LOG_TAG, String.format("%s: %d", + entry.getKey(), value[0])); + } + } + // Called by ScummVM thread (from initBackend) private void createScummVMGLContext() { egl = (EGL10)EGLContext.getEGL(); @@ -125,10 +172,75 @@ public class ScummVM implements SurfaceHolder.Callback { EGLConfig[] configs = new EGLConfig[numConfigs]; egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs, num_config); - eglConfig = configs[0]; + + if (false) { + Log.d(LOG_TAG, + String.format("Found %d EGL configurations.", numConfigs)); + for (EGLConfig config : configs) + dumpEglConfig(config); + } + + // Android's eglChooseConfig is busted in several versions and + // devices so we have to filter/rank the configs again ourselves. + eglConfig = chooseEglConfig(configs); + if (false) { + Log.d(LOG_TAG, + String.format("Chose EGL config from %d possibilities.", numConfigs)); + dumpEglConfig(eglConfig); + } eglContext = egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, null); + if (eglContext == EGL10.EGL_NO_CONTEXT) + throw new RuntimeException("Failed to create context"); + } + + private EGLConfig chooseEglConfig(EGLConfig[] configs) { + int best = 0; + int bestScore = -1; + int[] value = new int[1]; + for (int i = 0; i < configs.length; i++) { + EGLConfig config = configs[i]; + int score = 10000; + egl.eglGetConfigAttrib(eglDisplay, config, + EGL10.EGL_SURFACE_TYPE, value); + if ((value[0] & EGL10.EGL_WINDOW_BIT) == 0) + continue; // must have + + egl.eglGetConfigAttrib(eglDisplay, config, + EGL10.EGL_CONFIG_CAVEAT, value); + if (value[0] != EGL10.EGL_NONE) + score -= 1000; + + // Must be at least 555, but then smaller is better + final int[] colorBits = {EGL10.EGL_RED_SIZE, + EGL10.EGL_GREEN_SIZE, + EGL10.EGL_BLUE_SIZE, + EGL10.EGL_ALPHA_SIZE}; + for (int component : colorBits) { + egl.eglGetConfigAttrib(eglDisplay, config, + component, value); + if (value[0] >= 5) + score += 10; // boost if >5 bits accuracy + score -= value[0]; // penalize for wasted bits + } + + egl.eglGetConfigAttrib(eglDisplay, config, + EGL10.EGL_DEPTH_SIZE, value); + score -= value[0]; // penalize for wasted bits + + if (score > bestScore) { + best = i; + bestScore = score; + } + } + + if (bestScore < 0) { + Log.e(LOG_TAG, "Unable to find an acceptable EGL config, expect badness."); + return configs[0]; + } + + return configs[best]; } // Called by ScummVM thread @@ -137,12 +249,13 @@ public class ScummVM implements SurfaceHolder.Callback { try { surfaceLock.acquire(); } catch (InterruptedException e) { - Log.e(this.toString(), - "Interrupted while waiting for surface lock", e); + Log.e(LOG_TAG, "Interrupted while waiting for surface lock", e); return; } eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeSurface, null); + if (eglSurface == EGL10.EGL_NO_SURFACE) + Log.e(LOG_TAG, "CreateWindowSurface failed!"); egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); GL10 gl = (GL10)eglContext.getGL(); @@ -302,8 +415,8 @@ public class ScummVM implements SurfaceHolder.Callback { if (buf_size < 0) { int guess = AUDIO_FRAME_SIZE * sample_rate / 100; // 10ms of audio Log.w(LOG_TAG, String.format( - "Unable to get min audio buffer size (error %d). Guessing %dB.", - buf_size, guess)); + "Unable to get min audio buffer size (error %d). Guessing %dB.", + buf_size, guess)); buf_size = guess; } Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio", diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp index d4c002fbd0..81a8f7fbc7 100644 --- a/backends/platform/android/video.cpp +++ b/backends/platform/android/video.cpp @@ -38,6 +38,9 @@ #include "backends/platform/android/video.h" +// Unfortunately, Android devices are too varied to make broad assumptions :/ +#define TEXSUBIMAGE_IS_EXPENSIVE 0 + #undef LOG_TAG #define LOG_TAG "ScummVM-video" @@ -158,13 +161,11 @@ void GLESTexture::allocBuffer(GLuint w, GLuint h) { // later (perhaps with multiple TexSubImage2D operations). CHECK_GL_ERROR(); glBindTexture(GL_TEXTURE_2D, _texture_name); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - CHECK_GL_ERROR(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); CHECK_GL_ERROR(); glTexImage2D(GL_TEXTURE_2D, 0, glFormat(), @@ -177,6 +178,7 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, const void* buf, int pitch) { ENTER("updateBuffer(%u, %u, %u, %u, %p, %d)", x, y, w, h, buf, pitch); glBindTexture(GL_TEXTURE_2D, _texture_name); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); setDirtyRect(Common::Rect(x, y, x+w, y+h)); @@ -185,7 +187,25 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, glFormat(), glType(), buf); } else { // GLES removed the ability to specify pitch, so we - // have to do this row by row. + // have to do this ourselves. + if (h == 0) + return; + +#if TEXSUBIMAGE_IS_EXPENSIVE + byte tmpbuf[w * h * bytesPerPixel()]; + const byte* src = static_cast<const byte*>(buf); + byte* dst = tmpbuf; + GLuint count = h; + do { + memcpy(dst, src, w * bytesPerPixel()); + dst += w * bytesPerPixel(); + src += pitch; + } while (--count); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, + glFormat(), glType(), tmpbuf); +#else + // This version avoids the intermediate copy at the expense of + // repeat glTexSubImage2D calls. On some devices this is worse. const byte* src = static_cast<const byte*>(buf); do { glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, @@ -193,16 +213,15 @@ void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, ++y; src += pitch; } while (--h); +#endif } } void GLESTexture::fillBuffer(byte x) { - byte tmpbuf[_surface.h * _surface.w * bytesPerPixel()]; - memset(tmpbuf, 0, _surface.h * _surface.w * bytesPerPixel()); - glBindTexture(GL_TEXTURE_2D, _texture_name); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h, - glFormat(), glType(), tmpbuf); - setDirty(); + int rowbytes = _surface.w * bytesPerPixel(); + byte tmpbuf[_surface.h * rowbytes]; + memset(tmpbuf, x, _surface.h * rowbytes); + updateBuffer(0, 0, _surface.w, _surface.h, tmpbuf, rowbytes); } void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { @@ -215,6 +234,7 @@ void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { //glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); const GLint crop[4] = {0, _surface.h, _surface.w, -_surface.h}; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glColor4ub(0xff, 0xff, 0xff, 0xff); // Android GLES bug? glDrawTexiOES(x, y, 0, w, h); } else #endif diff --git a/backends/platform/dc/dcmain.cpp b/backends/platform/dc/dcmain.cpp index 5fde919650..269f400cf5 100644 --- a/backends/platform/dc/dcmain.cpp +++ b/backends/platform/dc/dcmain.cpp @@ -31,7 +31,7 @@ #include "icon.h" #include "DCLauncherDialog.h" #include <common/config-manager.h> -#include <common/stream.h> +#include <common/memstream.h> #include "backends/plugins/dc/dc-provider.h" #include "sound/mixer_intern.h" diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp index 07ac9460ec..6c8289684f 100644 --- a/backends/platform/dc/vmsave.cpp +++ b/backends/platform/dc/vmsave.cpp @@ -28,7 +28,7 @@ #include "dc.h" #include "icon.h" #include <common/savefile.h> -#include <gui/GuiManager.h> +#include <gui/gui-manager.h> #include <gui/message.h> #include <common/zlib.h> diff --git a/backends/platform/dingux/dingux.cpp b/backends/platform/dingux/dingux.cpp index 98bf51f49c..e982934fb7 100644 --- a/backends/platform/dingux/dingux.cpp +++ b/backends/platform/dingux/dingux.cpp @@ -45,4 +45,3 @@ void OSystem_SDL_Dingux::initBackend() { } #endif - diff --git a/backends/platform/dingux/dingux.h b/backends/platform/dingux/dingux.h index 80b2ecae5f..b56787528b 100644 --- a/backends/platform/dingux/dingux.h +++ b/backends/platform/dingux/dingux.h @@ -43,4 +43,3 @@ public: #endif /* DINGUX */ #endif /* SDL_DINGUX_COMMON_H */ - diff --git a/backends/platform/dingux/main.cpp b/backends/platform/dingux/main.cpp index 587c65334e..91899a55cf 100644 --- a/backends/platform/dingux/main.cpp +++ b/backends/platform/dingux/main.cpp @@ -24,7 +24,8 @@ */ #include "backends/platform/dingux/dingux.h" -#include "backends/plugins/posix/posix-provider.h" +#include "backends/plugins/sdl/sdl-provider.h" +//#include "backends/plugins/posix/posix-provider.h" #include "base/main.h" #if defined(DINGUX) @@ -39,7 +40,8 @@ int main(int argc, char* argv[]) { ((OSystem_SDL_Dingux *)g_system)->init(); #ifdef DYNAMIC_MODULES - PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); + PluginManager::instance().addPluginProvider(new SDLPluginProvider()); +// PluginManager::instance().addPluginProvider(new POSIXPluginProvider()); #endif // Invoke the actual ScummVM main entry point: @@ -50,4 +52,3 @@ int main(int argc, char* argv[]) { } #endif - diff --git a/backends/platform/ds/arm9/dist/readme_ds.txt b/backends/platform/ds/arm9/dist/readme_ds.txt index c4f1263452..ee1db719f4 100644 --- a/backends/platform/ds/arm9/dist/readme_ds.txt +++ b/backends/platform/ds/arm9/dist/readme_ds.txt @@ -41,6 +41,10 @@ Visit the main ScummVM website <http://www.scummvm.org> What's New? ------------------------------------------------------------------------ +ScummVM DS 1.2.0 + + * New game supported: Fascination + ScummVM DS 1.1.1 * Bugfix release: no new features @@ -323,7 +327,7 @@ CANNOT DO THIS. ------------------------------------------------------------------------ I'm glad you asked. Here is a list of the compatible games in version -1.1.1. Demo versions of the games listed should work too. +1.2.0. Demo versions of the games listed should work too. Flight of the Amazon Queen, Beneath a Steel Sky, and Lure of the Temptress have generously been released as freeware by the original @@ -392,6 +396,8 @@ Gobliins 2 D Goblins 3 D +Fascination D This game is untested on the DS + Ween: The Prophecy D Bargon Attack D diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index bf9fc1d826..781738265c 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -104,6 +104,10 @@ vpath %.s $(srcdir) # I actually had to use # ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' LDFLAGS='C:/Progra~1/devkitpro/libnds/lib/libnds9.a' --disable-shared --disable-debugging + +# handy command to find where the big symbols are in the ELF: +# arm-eabi-nm -S --radix=d --demangle scummvm.elf |sort -n -r --key=2 |less + ARM = 1 USE_ARM_SOUND_ASM = 1 USE_ARM_COSTUME_ASM = 1 @@ -241,7 +245,7 @@ ifdef USE_MAD DEFINES += -DUSE_MAD endif -DEFINES += -DREDUCE_MEMORY_USAGE +DEFINES += -DREDUCE_MEMORY_USAGE -DDISABLE_DEBUGGER -DUSE_TEXT_CONSOLE -DDISABLE_MASS_ADD -DDISABLE_NES_APU LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections @@ -345,7 +349,7 @@ MODULE_DIRS += . ndsall: @[ -d $(BUILD) ] || mkdir -p $(BUILD) - make -C ./$(BUILD) -f ../makefile scummvm.nds scummvm.ds.gba + $(MAKE) -C ./$(BUILD) -f ../makefile scummvm.nds scummvm.ds.gba include $(srcdir)/Makefile.common diff --git a/backends/platform/ds/arm9/source/cdaudio.cpp b/backends/platform/ds/arm9/source/cdaudio.cpp index 5860dea4f2..a69aedc91d 100644 --- a/backends/platform/ds/arm9/source/cdaudio.cpp +++ b/backends/platform/ds/arm9/source/cdaudio.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides for FILE as that is used in FLAC headers +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "cdaudio.h" #include "backends/fs/ds/ds-fs.h" #include "common/config-manager.h" @@ -74,6 +77,7 @@ struct decoderFormat { unsigned char sample[1024]; } __attribute__ ((packed)); +static bool s_started = false; static bool s_active = false; static WaveHeader waveHeader; static Header blockHeader; @@ -140,9 +144,8 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { char str[100]; - if (path[strlen(path.c_str()) - 1] != '/') { - path = path + "/"; - } + if (path.lastChar() != '/') + path += '/'; Common::String fname; @@ -196,7 +199,6 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { dataChunkStart = DS::std_ftell(s_file); - static bool started = false; sampleNum = 0; blockCount = 0; @@ -204,11 +206,11 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { IPC->streamFillNeeded[1] = true; IPC->streamFillNeeded[2] = true; IPC->streamFillNeeded[3] = true; - if (!started) { + if (!s_started) { fillPos = 0; audioBuffer = (s16 *) malloc(BUFFER_SIZE * 2); decompressionBuffer = (s16 *) malloc(waveHeader.fmtExtra * 2); - started = true; + s_started = true; // consolePrintf("****Starting buffer*****\n"); memset(audioBuffer, 0, BUFFER_SIZE * 2); memset(decompressionBuffer, 0, waveHeader.fmtExtra * 2); @@ -252,7 +254,12 @@ void update() { } #ifdef ARM_ADPCM -extern "C" void ARM_adcpm(int *block, int len, int stepTableIndex, +// FIXME: This code, as well as the source file adpcm_arm.s, are +// apparently unused. Maybe that is a mistake? Or maybe there is a bug +// in ARM_adpcm (then this should be reported and fixed). Or maybe there +// are other good reasons to prefer the C code, but then this as well as +// the assembler source file should be removed. +extern "C" void ARM_adpcm(int *block, int len, int stepTableIndex, int firstSample, s16 *decompressionBuffer); #endif @@ -469,20 +476,20 @@ void stopTrack() { } bool trackExists(int num) { - Common::String path = ConfMan.get("path"); - + Common::String path; char fname[128]; + FILE *file; sprintf(fname, "track%d.wav", num); - if (path[strlen(path.c_str()) - 1] == '/') { - path = path + fname; - } else { - path = path + "/" + fname; - } + path = ConfMan.get("path"); + if (path.lastChar() != '/') + path += '/'; + path += fname; + consolePrintf("Looking for %s...", path.c_str()); - FILE *file = DS::std_fopen(path.c_str(), "r"); + file = DS::std_fopen(path.c_str(), "r"); if (file) { consolePrintf("Success!\n"); setActive(true); @@ -492,27 +499,24 @@ bool trackExists(int num) { sprintf(fname, "track%02d.wav", num); - path = ConfMan.get("path"); - - if (path[strlen(path.c_str()) - 1] == '/') { - path = path + fname; - } else { - path = path + "/" + fname; - } + path = ConfMan.get("path"); + if (path.lastChar() != '/') + path += '/'; + path += fname; consolePrintf("Looking for %s...", path.c_str()); - - if ((file = DS::std_fopen(path.c_str(), "r"))) { + file = DS::std_fopen(path.c_str(), "r"); + if (file) { consolePrintf("Success!\n"); setActive(true); DS::std_fclose(file); return true; - } else { - setActive(false); - consolePrintf("Failed!\n"); - return false; } + + setActive(false); + consolePrintf("Failed!\n"); + return false; } bool checkCD() { diff --git a/backends/platform/ds/arm9/source/cdaudio.h b/backends/platform/ds/arm9/source/cdaudio.h index 6e53ef7bd2..7a85c97dbd 100644 --- a/backends/platform/ds/arm9/source/cdaudio.h +++ b/backends/platform/ds/arm9/source/cdaudio.h @@ -29,6 +29,9 @@ namespace DS { namespace CD { +// FIXME/TODO: The code in this file should be turned into a custom +// AudioCDManager subclass, see backends/audiocd/ and common/system.h + void setActive(bool active); void playTrack(int track, int numLoops, int startFrame, int duration); void stopTrack(); diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index 1525647c2e..303e504873 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -71,6 +71,9 @@ // - Try discworld? +// Disable symbol overrides for FILE +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include <nds.h> @@ -105,6 +108,7 @@ #endif #include "engine.h" +#include "backends/plugins/ds/ds-provider.h" #include "backends/fs/ds/ds-fs.h" #include "base/version.h" #include "common/util.h" @@ -2784,7 +2788,7 @@ bool getIndyFightState() { // Fast Ram /////////////////// -#define FAST_RAM_SIZE (24000) +#define FAST_RAM_SIZE (22500) #define ITCM_DATA __attribute__((section(".itcm"))) u8 *fastRamPointer; @@ -3213,6 +3217,9 @@ int main(void) { const char *argv[] = {"/scummvmds"}; #endif +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new DSPluginProvider()); +#endif while (1) { scummvm_main(ARRAYSIZE(argv), (char **) &argv); diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp index 6721a4910a..a693d2aee3 100644 --- a/backends/platform/ds/arm9/source/dsoptions.cpp +++ b/backends/platform/ds/arm9/source/dsoptions.cpp @@ -26,13 +26,13 @@ #include "dsoptions.h" #include "dsmain.h" #include "gui/dialog.h" -#include "gui/GuiManager.h" -#include "gui/ListWidget.h" -#include "gui/TabWidget.h" +#include "gui/gui-manager.h" +#include "gui/widgets/list.h" +#include "gui/widgets/tab.h" #include "osystem_ds.h" #include "engines/scumm/scumm.h" #include "touchkeyboard.h" -#include "gui/PopUpWidget.h" +#include "gui/widgets/popup.h" #include "common/translation.h" diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h index 1bdc7c1f27..8ba8e6e4da 100644 --- a/backends/platform/ds/arm9/source/dsoptions.h +++ b/backends/platform/ds/arm9/source/dsoptions.h @@ -34,7 +34,7 @@ #include "gui/object.h" #include "gui/widget.h" #include "gui/dialog.h" -#include "gui/TabWidget.h" +#include "gui/widgets/tab.h" #include "scumm/dialogs.h" namespace DS { diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c index 07affd8839..7f0757ef53 100644 --- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c +++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c @@ -194,7 +194,8 @@ const char lfn_offset_table[13]={0x01,0x03,0x05,0x07,0x09,0x0E,0x10,0x12,0x14,0x // available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA // Files -_VARS_IN_RAM FAT_FILE openFiles[MAX_FILES_OPEN]; +FAT_FILE openFiles[MAX_FILES_OPEN] __attribute__((section(".itcm"))); +//_VARS_IN_RAM // Long File names _VARS_IN_RAM char lfnName[MAX_FILENAME_LENGTH]; diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp index d0fb8fff3b..462138d335 100644 --- a/backends/platform/ds/arm9/source/gbampsave.cpp +++ b/backends/platform/ds/arm9/source/gbampsave.cpp @@ -23,165 +23,61 @@ * */ +// Disable symbol overrides for FILE +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "gbampsave.h" #include "fat/gba_nds_fat.h" #include "backends/fs/ds/ds-fs.h" #include "common/config-manager.h" +#include "common/bufferedstream.h" -///////////////////////// -// GBAMP Save File -///////////////////////// - -GBAMPSaveFile::GBAMPSaveFile(char *name, bool saveOrLoad) { - handle = DS::std_fopen(name, saveOrLoad? "w": "r"); -// consolePrintf("%s handle is %d\n", name, handle); -// consolePrintf("Created %s\n", name); - bufferPos = 0; - saveSize = 0; - flushed = 0; -} - -GBAMPSaveFile::~GBAMPSaveFile() { - flushSaveBuffer(); - if (handle) DS::std_fclose(handle); -// consolePrintf("Closed file\n"); -} - -uint32 GBAMPSaveFile::read(void *buf, uint32 length) { - saveSize += length; -// consolePrintf("Read %d %d ", length, saveSize); - return DS::std_fread(buf, 1, length, handle); -} - -bool GBAMPSaveFile::eos() const { - return DS::std_feof(handle); -} - -bool GBAMPSaveFile::skip(uint32 bytes) { - return DS::std_fseek(handle, bytes, SEEK_CUR) == 0; -} +#define SAVE_BUFFER_SIZE 100000 -void GBAMPSaveFile::flushSaveBuffer() { - if (bufferPos != 0) { -// consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer); - flushed += bufferPos; - DS::std_fwrite(buffer, 1, bufferPos, handle); - bufferPos = 0; - } -} - -int32 GBAMPSaveFile::pos() const { - return DS::std_ftell(handle); -} - -int32 GBAMPSaveFile::size() const { - int position = pos(); - DS::std_fseek(handle, 0, SEEK_END); - int length = DS::std_ftell(handle); - DS::std_fseek(handle, position, SEEK_SET); - return length; -} - -bool GBAMPSaveFile::seek(int32 newPos, int whence) { - return DS::std_fseek(handle, newPos, whence) == 0; -} - - -uint32 GBAMPSaveFile::write(const void *buf, uint32 length) { - if (bufferPos + length > SAVE_BUFFER_SIZE) { - flushSaveBuffer(); - saveSize += length; -// consolePrintf("Writing %d bytes from %x", length, buf); -// DS::std_fwrite(buf, 1, length, handle); - - memcpy(buffer + bufferPos, buf, length); - bufferPos += length; - - saveSize += length; - - -/* int pos = 0; - - int rest = SAVE_BUFFER_SIZE - bufferPos; - memcpy(buffer + bufferPos, buf, rest); - bufferPos = 512; - pos += rest; - flushSaveBuffer(); - length -= rest; -// consolePrintf("First section: %d\n", rest); - - while (length >= 512) { - DS::std_fwrite(((char *) (buf)) + pos, 1, 512, handle); - length -= 512; - pos += 512; -// consolePrintf("Full chunk, %d left ", length); - } - - bufferPos = 0; - memcpy(buffer + bufferPos, ((char *) (buf)) + pos, length); - bufferPos += length; -// consolePrintf("%d left in buffer ", bufferPos);*/ - - } else { - - memcpy(buffer + bufferPos, buf, length); - bufferPos += length; - - saveSize += length; - } - -// if ((length > 100) || (length <= 0)) consolePrintf("Write %d bytes\n", length); - return length; +// This method copied from an old version of the savefile.cpp, since it's been removed from there and +// placed in default-saves.cpp, where I cannot call it. +// FIXME: Does it even make sense to change the "savepath" on the NDS? Considering +// that nothing sets a default value for the "savepath" either, wouldn't it better +// to return a fixed path here? +static Common::String getSavePath() { + // Try to use game specific savepath from config + return ConfMan.get("savepath"); } - ////////////////////////// // GBAMP Save File Manager ////////////////////////// -GBAMPSaveFileManager::GBAMPSaveFileManager() { - +Common::OutSaveFile *GBAMPSaveFileManager::openForSaving(const Common::String &filename) { + Common::String fileSpec = getSavePath(); + if (fileSpec.lastChar() != '/') + fileSpec += '/'; + fileSpec += filename; + +// consolePrintf("Opening the file: %s\n", fileSpec.c_str()); + + Common::WriteStream *stream = DS::DSFileStream::makeFromPath(fileSpec, true); + // Use a write buffer + stream = Common::wrapBufferedWriteStream(stream, SAVE_BUFFER_SIZE); + return stream; } -GBAMPSaveFileManager::~GBAMPSaveFileManager() { +Common::InSaveFile *GBAMPSaveFileManager::openForLoading(const Common::String &filename) { + Common::String fileSpec = getSavePath(); + if (fileSpec.lastChar() != '/') + fileSpec += '/'; + fileSpec += filename; +// consolePrintf("Opening the file: %s\n", fileSpec.c_str()); + + return DS::DSFileStream::makeFromPath(fileSpec, false); } -GBAMPSaveFile *GBAMPSaveFileManager::openSavefile(const char *name, bool saveOrLoad) { - char fileSpec[128]; - - strcpy(fileSpec, getSavePath()); - - if (fileSpec[strlen(fileSpec) - 1] == '/') { - sprintf(fileSpec, "%s%s", getSavePath(), name); - } else { - sprintf(fileSpec, "%s/%s", getSavePath(), name); - } -// consolePrintf("Opening the file: %s\n", fileSpec); - GBAMPSaveFile *sf = new GBAMPSaveFile(fileSpec, saveOrLoad); - if (sf->isOpen()) { -// consolePrintf("Ok"); - return sf; - } else { -// consolePrintf("Fail"); - delete sf; - return NULL; - } +bool GBAMPSaveFileManager::removeSavefile(const Common::String &filename) { + return false; // TODO: Implement this } -// This method copied from an old version of the savefile.cpp, since it's been removed from there and -// placed in default-saves.cpp, where I cannot call it. -// FIXME: Does it even make sense to change the "savepath" on the NDS? Considering -// that nothing sets a default value for the "savepath" either, wouldn't it better -// to return a fixed path here? -const char *GBAMPSaveFileManager::getSavePath() const { - // Try to use game specific savepath from config - const char *dir = ConfMan.get("savepath").c_str(); - assert(dir); - - return dir; -} Common::StringArray GBAMPSaveFileManager::listSavefiles(const Common::String &pattern) { @@ -190,7 +86,7 @@ Common::StringArray GBAMPSaveFileManager::listSavefiles(const Common::String &pa { char dir[128]; - strcpy(dir, getSavePath()); + strcpy(dir, getSavePath().c_str()); char *realName = dir; if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) { diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h index ad929236cd..caac0c0b28 100644 --- a/backends/platform/ds/arm9/source/gbampsave.h +++ b/backends/platform/ds/arm9/source/gbampsave.h @@ -26,60 +26,15 @@ #ifndef _GBAMPSAVE_H_ #define _GBAMPSAVE_H_ -#include "common/system.h" #include "common/savefile.h" -#include "backends/fs/ds/ds-fs.h" - -#define SAVE_BUFFER_SIZE 100000 - -class GBAMPSaveFile : public Common::InSaveFile, public Common::OutSaveFile { - DS::fileHandle *handle; - char buffer[SAVE_BUFFER_SIZE]; - int bufferPos; - int saveSize; - int flushed; - -public: - GBAMPSaveFile(char *name, bool saveOrLoad); - virtual ~GBAMPSaveFile(); - - virtual uint32 read(void *buf, uint32 size); - virtual uint32 write(const void *buf, uint32 size); - - virtual bool eos() const; - virtual bool skip(uint32 bytes); - - virtual int32 pos() const; - virtual int32 size() const; - virtual bool seek(int32 pos, int whence); - - void flushSaveBuffer(); - - virtual bool isOpen() const { - return handle != 0; - } -}; - class GBAMPSaveFileManager : public Common::SaveFileManager { public: - GBAMPSaveFileManager(); - ~GBAMPSaveFileManager(); - -// static GBAMPSaveFileManager *instance() { return instancePtr; } + virtual Common::OutSaveFile *openForSaving(const Common::String &filename); + virtual Common::InSaveFile *openForLoading(const Common::String &filename); - GBAMPSaveFile *openSavefile(const char *filename, bool saveOrLoad); - - virtual Common::OutSaveFile *openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); } - virtual Common::InSaveFile *openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); } - - virtual bool removeSavefile(const Common::String &filename) { return false; } // TODO: Implement this + virtual bool removeSavefile(const Common::String &filename); virtual Common::StringArray listSavefiles(const Common::String &pattern); - - void deleteFile(const Common::String &name); - void listFiles(); - - const char *getSavePath() const; }; #endif diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index c4ff241de0..55e3be6cca 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -700,6 +700,10 @@ void OSystem_DS::unlockMutex(MutexRef mutex) { void OSystem_DS::deleteMutex(MutexRef mutex) { } +// FIXME/TODO: The CD API as follows is *obsolete* +// and should be replaced by an AudioCDManager subclass, +// see backends/audiocd/ and common/system.h + bool OSystem_DS::openCD(int drive) { return DS::CD::checkCD(); } diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 65ac3f4f7e..50a4353e18 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -124,9 +124,12 @@ public: virtual void unlockMutex(MutexRef mutex); virtual void deleteMutex(MutexRef mutex); + + // FIXME/TODO: The CD API as follows is *obsolete* + // and should be replaced by an AudioCDManager subclass, + // see backends/audiocd/ and common/system.h virtual bool openCD(int drive); virtual bool pollCD(); - virtual void playCD(int track, int num_loops, int start_frame, int duration); virtual void stopCD(); virtual void updateCD(); diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp index 43a16486c5..a4fc2aed77 100644 --- a/backends/platform/ds/arm9/source/wordcompletion.cpp +++ b/backends/platform/ds/arm9/source/wordcompletion.cpp @@ -30,11 +30,11 @@ #ifdef ENABLE_AGI namespace DS { -// Default dictionary is about 64Kb, so 128Kb should be enough for future expansion -#define WORD_BUFFER_SIZE (128 * 1024) +// Default dictionary is about 64Kb, so 96Kb should be enough for future expansion +#define WORD_BUFFER_SIZE (96 * 1024) // Default dictionary has ~8000 words -#define MAX_WORD_COUNT 16000 +#define MAX_WORD_COUNT 12000 char wordBuffer[WORD_BUFFER_SIZE]; int wordBufferPos = 0; diff --git a/backends/platform/ds/build-ds.sh b/backends/platform/ds/build-ds.sh new file mode 100755 index 0000000000..d56af5a092 --- /dev/null +++ b/backends/platform/ds/build-ds.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# +# build-ds.sh -- script for building a ds build with every usable dynamic engine plugin + +make clean + +#Set up a static build with only engines usable by DS enabled +./configure --host=ds --disable-debug --disable-all-engines --enable-scumm --enable-sky --enable-queen --enable-agos --enable-gob --enable-cine --enable-agi --enable-kyra --enable-lure --enable-parallaction --enable-made --enable-cruise + +make clean + +make + +#Dump all symbols used in this garbage-collected static build into a file +rm -f ds.syms +arm-eabi-objdump -t scummvm.elf > ds.syms + +make clean + +#Set up a dynamic build with only engines usable by the DS enabled +./configure --host=ds --enable-plugins --default-dynamic --disable-debug --disable-all-engines --enable-scumm --enable-sky --enable-queen --enable-gob --enable-cine --enable-agos --enable-agi --enable-kyra --enable-lure --enable-parallaction --enable-made --enable-cruise + +make clean + +#Make this final build, which is selectively stripped with the assistance of the ds.syms file that was generated earlier +make diff --git a/backends/platform/gp2x/build/README-GP2X b/backends/platform/gp2x/build/README-GP2X index dc93a9f1c9..3c6591d369 100644 --- a/backends/platform/gp2x/build/README-GP2X +++ b/backends/platform/gp2x/build/README-GP2X @@ -1,19 +1,10 @@ -ScummVM - GP2X SPECIFIC README - HEAD SVN +ScummVM - GP2X SPECIFIC README ------------------------------------------------------------------------ Contents: * About the backend/port <#About_the_backendport> - * Game compatability <#Game_compatibility> - * Included engines <#Included_engines> * Supported audio options <#Supported_audio_options> - * Supported cut-scene options <#Supported_cut-scene_options> - * Recent changes <#Recent_changes> - * How to save <#How_to_save> - * Controller mappings <#Controller_mappings> - * Know issues <#Know_issues> - * TODO's <#Major_TODOs> - * Additional resources/links <#Additional_resourceslinks> * Credits <#Credits> ------------------------------------------------------------------------ @@ -26,47 +17,24 @@ WiKi: <http://wiki.scummvm.org/index.php/GP2X> for the most current information on the port and any updates to this documentation. +The wiki includes detailed instructions on how to use the port and +control information. + ------------------------------------------------------------------------ About the backend/port -This is the readme for the offficial GP2X ScummVM backend (also known as +This is the readme for the official GP2X ScummVM backend (also known as the GP2X port). This is an SVN test release of ScummVM for the GP2X, it would be appreciated if this SVN test distribution was not mirrored and that -people be directed to http://www.distant-earth.com/scummvm instead for +people be directed to http://scummvm.distant-earth.com/ instead for updated SVN builds. Full supported official releases of the GP2X ScummVM backend are made in line with main official releases and are avalalble from the ScummVM downloads page <http://www.scummvm.org/downloads.php>. -This build is in an active state of development and as such no -?expected? behavior can be guaranteed ;). - -SVN builds are quickly tested with firmware 2.0.0 for reference. - -Please refer to the GP2X ScummVM forum -<http://forums.scummvm.org/viewforum.php?f=14> and WiKi -<http://wiki.scummvm.org/index.php/GP2X> for the latest information on -the port. - ------------------------------------------------------------------------- -Game compatibility - -For information on the compatability of a specific game please refer to -the GP2X compatability section of the ScummVM WiKi -<http://wiki.scummvm.org/index.php/GP2X#Compatibility_List>. - -Please note the version and date of the ScummVM build you are running -when reviewing the above list. - ------------------------------------------------------------------------- -Included engines - -Just because an engine is included does not mean any/all of its games -are supported. Please check game compatability for more infomation. - ------------------------------------------------------------------------ Supported audio options @@ -79,106 +47,6 @@ FLAC audio is currently unsupported. For best results use uncompressed audio in games. ------------------------------------------------------------------------ -Supported cut-scene options - -No cut scene compression options are currently supported. - -DXA video support will be added as soon as it is stable. - ------------------------------------------------------------------------- -Recent changes - -Refined audio hacks to reduce audio delay a little more. -Enabled hardware scalar code. -Now built using SDL 1.2.9 for the parts of the port that use SDL (some -parts now hit the hardware directly). -Enabled new launcher - (Ensure defaulttheme.zip is in the same folder as -the executable). -Aspect Ratio Correction can now be disabled ?per game?. When adding a -game you can find this option on the GFX tab. -Note: This will cause the game to run with a black border at the bottom -as it will be rendered to a 320*200 frame. - ------------------------------------------------------------------------- -How to save - -NOTE: Everything is saved to the SD card, saves are stored in the saves -folder under your main ScummVM executable unless you set another save -location. - -The configiration file for ScummVM (.scummvmrc) is stored in the same -place as the ScummVM executable. - -The save process below is for Scumm engine games but the principle is -the same for all. - -In Game. - -1. Right Trigger -2. Select SAVE with B -3. Select a position with B -4. Right trigger puts ? in the name box for some text. -5. Press B to save - -Basically the emulated keys you can use are equivelent to the values -buttons are mapped to, - -I have a virtual keyboard like the GP32 one (left/right on the stick to -pick chars) to add in at some point ;-) - ------------------------------------------------------------------------- -Controller mappings - -Mouse emulation: - -Stick: Move Pointer -Stick Click: ?light? Left Click -B: Left click -X: Right click - -Keyboard emulation: - -Start: Return -Select: Escape -Y: Space Bar (Pause) -Right Trigger: Game Menu (Save, Load, Quit etc.) -Volume Buttons: Increase and Decrease volume (5% per press) - -Fancy button combos: - -NOTE: To use button combos press and hold the Left Trigger then... - -Y: Toggle "zoom" mode - Try it in larger games like Broken Sword. -Volume Buttons: Increase and Decrease subtitle speed (In SCUMM games) -Right Trigger: 0 (For skipping the copy protection in Monkey Island 2) -Select: Exit ScummVM completely (and gracefully) - ------------------------------------------------------------------------- -Know issues - -Possible random crash (well SegFault). I have had this happen twice and -have not tracked down the cause. -It happens very infrequently, both times it was in the DOTT CD intro. -Saving often is never a bad idea anyhow. - ------------------------------------------------------------------------- -TODO's - -Fix save support when using the Sky engine (Beneath a Steel Sky) - You -CAN'T save at the moment but auto save works. - ------------------------------------------------------------------------- -Additional resources/links - - * ScummVM WiKi GP2X page <http://wiki.scummvm.org/index.php/GP2X> - * ScummVM forums GP2X forum - <http://forums.scummvm.org/viewforum.php?f=14> - * My own ScummVM page <http://scummvm.distant-earth.com/> (for - SVN/test builds) - * Main ScummVM site <http://www.scummvm.org> (for official supported - release builds) - ------------------------------------------------------------------------- Credits Core ScummVM code (c) The ScummVM Team diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gp2x/build/config.sh index 2bc49564f7..e0a1bf1209 100755 --- a/backends/platform/gp2x/build/config.sh +++ b/backends/platform/gp2x/build/config.sh @@ -18,6 +18,7 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. ./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd -#--enable-plugins --default-dynamic +# --disable-release --enable-debug +# --enable-plugins --default-dynamic echo Generating config for GP2X complete. Check for errors. diff --git a/backends/platform/gp2x/build/scummvm.gpe b/backends/platform/gp2x/build/scummvm.gpe index 1e69c149b9..c6b051831c 100755 --- a/backends/platform/gp2x/build/scummvm.gpe +++ b/backends/platform/gp2x/build/scummvm.gpe @@ -4,7 +4,7 @@ mount -o sync,remount /dev/mmcsd/disc0/part1 /mnt/sd/ # Run ScummVM, important this bit. -./scummvm.gp2x +./scummvm.gph # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gp2x/gp2x-hw.cpp b/backends/platform/gp2x/gp2x-hw.cpp index 75e4ca6471..8818ff9fe9 100644 --- a/backends/platform/gp2x/gp2x-hw.cpp +++ b/backends/platform/gp2x/gp2x-hw.cpp @@ -30,6 +30,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "gp2x-common.h" #include "gp2x-hw.h" @@ -48,6 +51,10 @@ #include <sys/time.h> #include <unistd.h> +extern "C" { +static unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0};//, gp2x_ticks_per_second; +} + namespace GP2X_HW { enum { diff --git a/backends/platform/gp2x/gp2x-mem.cpp b/backends/platform/gp2x/gp2x-mem.cpp index 97a34ffb6a..0968087cfd 100644 --- a/backends/platform/gp2x/gp2x-mem.cpp +++ b/backends/platform/gp2x/gp2x-mem.cpp @@ -28,6 +28,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include <stdio.h> #include <signal.h> #include <setjmp.h> @@ -39,8 +42,11 @@ #include "backends/platform/gp2x/gp2x-mem.h" -void SetClock (unsigned c) -{ +extern "C" { +static volatile unsigned short *gp2x_memregs; +} + +void SetClock (unsigned c) { unsigned v; unsigned mdiv,pdiv=3,scale=0; @@ -54,8 +60,7 @@ void SetClock (unsigned c) gp2x_memregs[0x910>>1] = v; } -void patchMMU (void) -{ +void patchMMU (void) { //volatile unsigned int *secbuf = (unsigned int *)malloc (204800); printf ("Reconfiguring cached memory regions...\n"); @@ -68,19 +73,15 @@ void patchMMU (void) int mmufd = open("/dev/mmuhack", O_RDWR); - if(mmufd < 0) - { + if(mmufd < 0) { printf ("Upper memory uncached (attempt failed, access to upper memory will be slower)...\n"); - } - else - { + } else { printf ("Upper memory cached...\n"); close(mmufd); } } -void unpatchMMU (void) -{ +void unpatchMMU (void) { printf ("Restoreing cached memory regions...\n"); system("/sbin/rmmod mmuhack"); } diff --git a/backends/platform/gp2x/gp2x-mem.h b/backends/platform/gp2x/gp2x-mem.h index 24b2a3f569..aa49444164 100644 --- a/backends/platform/gp2x/gp2x-mem.h +++ b/backends/platform/gp2x/gp2x-mem.h @@ -47,9 +47,6 @@ extern void unpatchMMU (void); #define SYS_CLK_FREQ 7372800 -static unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0};//, gp2x_ticks_per_second; -static volatile unsigned short *gp2x_ram, *gp2x_memregs; - #ifdef __cplusplus } #endif diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index c297a45833..3a6d1a27f9 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -23,6 +23,14 @@ * */ +/* + * GP2X: Main backend. + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/gp2x/gp2x-common.h" #include "backends/platform/gp2x/gp2x-hw.h" #include "backends/platform/gp2x/gp2x-mem.h" diff --git a/backends/platform/gph/build/README-GP2XWIZ b/backends/platform/gph/build/README-GP2XWIZ deleted file mode 100644 index 269fa901c9..0000000000 --- a/backends/platform/gph/build/README-GP2XWIZ +++ /dev/null @@ -1,140 +0,0 @@ -ScummVM - GP2X WIZ SPECIFIC README - HEAD SVN ------------------------------------------------------------------------- - -Contents: - - * About the backend/port <#About_the_backendport> - * Game compatability <#Game_compatibility> - * Included engines <#Included_engines> - * Supported audio options <#Supported_audio_options> - * Supported cut-scene options <#Supported_cut-scene_options> - * Recent changes <#Recent_changes> - * How to save <#How_to_save> - * Controller mappings <#Controller_mappings> - * Known issues <#Knonw_issues> - * Additional resources/links <#Additional_resourceslinks> - * Credits <#Credits> - ------------------------------------------------------------------------- - -Please refer to the: - -GP2X/GP2XWiz ScummVM Forum: <http://forums.scummvm.org/viewforum.php?f=14> -WiKi: <http://wiki.scummvm.org/index.php/GP2XWiz> - -for the most current information on the port and any updates to this -documentation. - ------------------------------------------------------------------------- -About the backend/port - -This is the readme for the official GP2XWiz ScummVM backend (also known as -the GP2XWiz port). - -This is an SVN test release of ScummVM for the GP2XWiz, it would be -appreciated if this SVN test distribution was not mirrored and that -people be directed to http://scummvm.distant-earth.com/ instead for -updated SVN builds. - -Full supported official releases of the GP2X WIZ ScummVM backend are made in -line with main official releases and are avalalble from the ScummVM -downloads page <http://www.scummvm.org/downloads.php>. - -This build is in an active state of development and as such no -"expected" behavior can be guaranteed ;). - ------------------------------------------------------------------------- -Game compatibility - -For information on the compatability of a specific game please refer to -the GP2XWiz compatability section of the ScummVM WiKi -<http://wiki.scummvm.org/index.php/GP2XWiz#Compatibility_List>. - -Please note the version and date of the ScummVM build you are running -when reviewing the above list. - ------------------------------------------------------------------------- -Supported audio options - -Raw audio. -MP3 audio. -OGG Vorbis audio. - -FLAC audio is currently unsupported. - -For best results use uncompressed audio in games. - ------------------------------------------------------------------------- -How to save - -NOTE: Everything is saved to the SD card, saves are stored in the saves -folder under your main ScummVM executable unless you set another save -location. - -The configiration file for ScummVM (.scummvmrc) is stored in the same -place as the ScummVM executable. - -The save process below is for Scumm engine games but the principle is -the same for all. - -In Game. - -1. Menu Button -2. Select SAVE with B -3. Select a position with B -4. Right trigger puts 0 in the name box for some text. -5. Press B to save - -Basically the emulated keys you can use are equivelent to the values -buttons are mapped to, - ------------------------------------------------------------------------- -Controller mappings - -Touch screen: -Touch: Move Pointer and Left click - -Mouse emulation: - -dPad: Move Pointer -B: Left click -X: Right click - -Keyboard emulation: - -Right Trigger: Return -Select: Escape -Y: Space Bar (Pause) -Menu: Game Menu (Save, Load, Quit etc.) -Volume Buttons: Increase and Decrease volume - -Fancy button combos: - -NOTE: To use button combos press and hold the Left Trigger then... - -Right Trigger: Display Virtual Keyboard -Menu: Bring up the Global main menu for ScummVM -Select: Exit ScummVM completely (and gracefully) - ------------------------------------------------------------------------- -Known issues - -No major known issues - ------------------------------------------------------------------------- -Additional resources/links - - * ScummVM WiKi GP2X page <http://wiki.scummvm.org/index.php/GP2X> - * ScummVM forums GP2X forum - <http://forums.scummvm.org/viewforum.php?f=14> - * My own ScummVM page <http://scummvm.distant-earth.com/> (for - SVN/test builds) - * Main ScummVM site <http://www.scummvm.org> (for official supported - release builds) - ------------------------------------------------------------------------- -Credits - -Core ScummVM code (c) The ScummVM Team -GP2X Wiz backend (c) John Willis -Detailed (c) information can be found within the source code diff --git a/backends/platform/gph/build/README-GPH b/backends/platform/gph/build/README-GPH new file mode 100644 index 0000000000..64b9fcb76b --- /dev/null +++ b/backends/platform/gph/build/README-GPH @@ -0,0 +1,60 @@ +ScummVM - GPH SPECIFIC README +------------------------------------------------------------------------ + +Contents: + + * About the backend/port <#About_the_backendport> + * Supported audio options <#Supported_audio_options> + * Credits <#Credits> + +------------------------------------------------------------------------ + +Please refer to the: + +GPH ScummVM Forum: <http://forums.scummvm.org/viewforum.php?f=14> + +WiKi: (Select your device) + +<http://wiki.scummvm.org/index.php/GP2X> +<http://wiki.scummvm.org/index.php/GP2XWiz> +<http://wiki.scummvm.org/index.php/Caanoo> + +for the most current information on the port and any updates to this +documentation. + +The wiki includes detailed instructions on how to use the port and +control information. + +------------------------------------------------------------------------ +About the backend/port + +This is the readme for the official GPH ScummVM backend (also known as +the GP2X port/GP2XWiz port and Caanoo port). + +This is an SVN test release of ScummVM for GPH devices, it would be +appreciated if this SVN test distribution was not mirrored and that +people be directed to http://scummvm.distant-earth.com/ instead for +updated SVN builds. + +Fully supported official releases of the GPH ScummVM backend are made in +line with main official releases and are avalalble from the ScummVM +downloads page <http://www.scummvm.org/downloads.php> for the GP2X, +GP2XWiz and Caanoo. + +------------------------------------------------------------------------ +Supported audio options + +Raw audio. +MP3 audio. +OGG Vorbis audio. + +FLAC audio is currently unsupported. + +For best results use uncompressed audio in games. + +------------------------------------------------------------------------ +Credits + +Core ScummVM code (c) The ScummVM Team +Portions of the GPH backend (c) John Willis +Detailed (c) information can be found within the source code diff --git a/backends/platform/gph/build/config-alleng.sh b/backends/platform/gph/build/config-alleng.sh index cfed463edf..9ec8a09cd2 100755 --- a/backends/platform/gph/build/config-alleng.sh +++ b/backends/platform/gph/build/config-alleng.sh @@ -13,10 +13,15 @@ export CXX=arm-open2x-linux-g++ export CXXFLAGS="-mcpu=arm926ej-s -mtune=arm926ej-s" export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib -export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic +./configure --backend=gph --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers \ + --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-png --with-png-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-vkeybd --enable-all-engines --enable-plugins --default-dynamic echo Generating config for GP2X Wiz complete. Check for errors. diff --git a/backends/platform/gph/build/config.sh b/backends/platform/gph/build/config.sh index 25c3a83da0..ac7c34ad12 100755 --- a/backends/platform/gph/build/config.sh +++ b/backends/platform/gph/build/config.sh @@ -13,10 +13,15 @@ export CXX=arm-open2x-linux-g++ export CXXFLAGS="-mcpu=arm926ej-s -mtune=arm926ej-s" export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib -export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2xwiz --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-vkeybd --enable-plugins --default-dynamic +./configure --backend=gph --disable-mt32emu --host=gp2xwiz --disable-flac --disable-nasm --disable-hq-scalers \ + --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-png --with-png-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 \ + --enable-vkeybd --enable-plugins --default-dynamic echo Generating config for GP2X Wiz complete. Check for errors. diff --git a/backends/platform/gph/build/scummvm-gdb.gpe b/backends/platform/gph/build/scummvm-gdb.gpe index f486c288ee..63ce193ca8 100755 --- a/backends/platform/gph/build/scummvm-gdb.gpe +++ b/backends/platform/gph/build/scummvm-gdb.gpe @@ -6,7 +6,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM via GDB (so make sure you have a terminal open or serial). # Oh, and GDB installed of course ;) -gdb --args ./scummvm.wiz --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +gdb --args ./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gph/build/scummvm.gpe b/backends/platform/gph/build/scummvm.gpe index 2866825e91..59ff562aeb 100755 --- a/backends/platform/gph/build/scummvm.gpe +++ b/backends/platform/gph/build/scummvm.gpe @@ -5,7 +5,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM, important this bit. -./scummvm.wiz --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gph/caanoo-bundle.mk b/backends/platform/gph/caanoo-bundle.mk index c411310688..b7b3c9e188 100755 --- a/backends/platform/gph/caanoo-bundle.mk +++ b/backends/platform/gph/caanoo-bundle.mk @@ -17,7 +17,7 @@ caanoo-bundle: $(EXECUTABLE) $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm.gpe $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GP2XWIZ $(bundle_name)/scummvm/README-CAANOO + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ @@ -48,7 +48,7 @@ caanoo-bundle-debug: $(EXECUTABLE) $(CP) $(srcdir)/backends/platform/gph/caanoo/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GP2XWIZ $(bundle_name)/scummvm/README-CAANOO + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ diff --git a/backends/platform/gph/caanoo/config-alleng.sh b/backends/platform/gph/caanoo/config-alleng.sh index 7a097c268b..97fed942fa 100755 --- a/backends/platform/gph/caanoo/config-alleng.sh +++ b/backends/platform/gph/caanoo/config-alleng.sh @@ -3,14 +3,19 @@ echo Quick script to make running configure all the time less painful echo and let all the build work be done from the backend/build folder. -# Assume Caanoo toolchain/build env. +# Assume Caanoo toolchain/build env and source it. . /opt/arm-caanoo/environment-setup -# Export the tool names for cross-compiling -export DEFINES=-DNDEBUG - # Edit the configure line to suit. cd ../../../.. -./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac --disable-nasm --disable-vorbis --disable-hq-scalers --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic +./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac \ + --disable-nasm --disable-vorbis --disable-hq-scalers \ + --with-sdl-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-tremor --with-tremor-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-all-engines --enable-vkeybd --enable-plugins --default-dynamic -echo Generating config for GP2X Caanoo complete. Check for errors. +echo Generating config for Caanoo complete. Check for errors. diff --git a/backends/platform/gph/caanoo/config.sh b/backends/platform/gph/caanoo/config.sh index 82e3774dbf..11d597481a 100755 --- a/backends/platform/gph/caanoo/config.sh +++ b/backends/platform/gph/caanoo/config.sh @@ -6,11 +6,16 @@ echo and let all the build work be done from the backend/build folder. # Assume Caanoo toolchain/build env. . /opt/arm-caanoo/environment-setup -# Export the tool names for cross-compiling -export DEFINES=-DNDEBUG - # Edit the configure line to suit. cd ../../../.. -./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac --disable-nasm --disable-vorbis --disable-hq-scalers --with-sdl-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr/bin --with-mpeg2-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-tremor --with-tremor-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-zlib --with-zlib-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr --enable-vkeybd --enable-plugins --default-dynamic +./configure --backend=caanoo --disable-mt32emu --host=caanoo --disable-alsa --disable-flac \ + --disable-nasm --disable-vorbis --disable-hq-scalers \ + --with-sdl-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-tremor --with-tremor-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/opt/arm-caanoo/arm-none-linux-gnueabi/usr \ + --enable-vkeybd --enable-plugins --default-dynamic echo Generating config for GP2X Caanoo complete. Check for errors. diff --git a/backends/platform/gph/caanoo/scummvm-gdb.gpe b/backends/platform/gph/caanoo/scummvm-gdb.gpe index 2d776f1bc3..63ce193ca8 100755 --- a/backends/platform/gph/caanoo/scummvm-gdb.gpe +++ b/backends/platform/gph/caanoo/scummvm-gdb.gpe @@ -6,7 +6,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM via GDB (so make sure you have a terminal open or serial). # Oh, and GDB installed of course ;) -gdb --args ./scummvm.caanoo --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +gdb --args ./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gph/caanoo/scummvm.gpe b/backends/platform/gph/caanoo/scummvm.gpe index 52bb7a98cd..37d0f65d18 100755 --- a/backends/platform/gph/caanoo/scummvm.gpe +++ b/backends/platform/gph/caanoo/scummvm.gpe @@ -5,7 +5,7 @@ export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH # Run ScummVM, important this bit. -./scummvm.caanoo --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc +./scummvm.gph --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc # Sync the SD card to check that everything is written. sync diff --git a/backends/platform/gph/gp2xwiz-bundle.mk b/backends/platform/gph/gp2xwiz-bundle.mk index 5ca6c0a9c7..df4cae7f4f 100755 --- a/backends/platform/gph/gp2xwiz-bundle.mk +++ b/backends/platform/gph/gp2xwiz-bundle.mk @@ -17,7 +17,7 @@ gp2xwiz-bundle: $(EXECUTABLE) $(CP) $(srcdir)/backends/platform/gph/build/scummvm.gpe $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GP2XWIZ $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ @@ -51,7 +51,7 @@ gp2xwiz-bundle-debug: $(EXECUTABLE) $(CP) $(srcdir)/backends/platform/gph/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe $(CP) $(srcdir)/backends/platform/gph/build/scummvm.png $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvmb.png $(bundle_name)/scummvm/ - $(CP) $(srcdir)/backends/platform/gph/build/README-GP2XWIZ $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gph/build/README-GPH $(bundle_name)/scummvm/ $(CP) $(srcdir)/backends/platform/gph/build/scummvm.ini $(bundle_name)/ $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ diff --git a/backends/platform/gph/gph-events.cpp b/backends/platform/gph/gph-events.cpp index 91ea30bdc9..2a6237c794 100644 --- a/backends/platform/gph/gph-events.cpp +++ b/backends/platform/gph/gph-events.cpp @@ -253,7 +253,6 @@ bool OSystem_GPH::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) { event.type = Common::EVENT_MOUSEMOVE; else event.type = Common::EVENT_LBUTTONUP; /* For normal mice etc. */ - } else if (ev.button.button == SDL_BUTTON_RIGHT) event.type = Common::EVENT_RBUTTONUP; diff --git a/backends/platform/gph/gph-hw.cpp b/backends/platform/gph/gph-hw.cpp index b43324b547..fa52526f01 100644 --- a/backends/platform/gph/gph-hw.cpp +++ b/backends/platform/gph/gph-hw.cpp @@ -28,6 +28,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/gph/gph-hw.h" #include <fcntl.h> diff --git a/backends/platform/gph/gph-main.cpp b/backends/platform/gph/gph-main.cpp index 727d599cc8..8144bffb8f 100644 --- a/backends/platform/gph/gph-main.cpp +++ b/backends/platform/gph/gph-main.cpp @@ -23,9 +23,13 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include <SDL/SDL.h> +// #include "backends/platform/gph/gph-options.h" #include "backends/platform/gph/gph-sdl.h" #include "backends/platform/gph/gph-hw.h" #include "backends/plugins/posix/posix-provider.h" @@ -158,6 +162,9 @@ void OSystem_GPH::initBackend() { /* Make sure SDL knows that we have a joystick we want to use. */ ConfMan.setInt("joystick_num", 0); + /* Now setup any device specific user options (Left handed mode, that sort of thing). */ + // GPH::setOptions(); + printf("%s\n", "Passing to OSystem::SDL initBackend."); /* Pass to SDL backend to do the heavy lifting */ diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp index 22f529dfac..c30e34dd05 100644 --- a/backends/platform/iphone/osys_events.cpp +++ b/backends/platform/iphone/osys_events.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "gui/message.h" #include "common/translation.h" diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp index a1fb8f0d5e..9dc4e202c4 100644 --- a/backends/platform/iphone/osys_main.cpp +++ b/backends/platform/iphone/osys_main.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include <unistd.h> #include <pthread.h> diff --git a/backends/platform/iphone/osys_sound.cpp b/backends/platform/iphone/osys_sound.cpp index 55892580f6..cd364f57ac 100644 --- a/backends/platform/iphone/osys_sound.cpp +++ b/backends/platform/iphone/osys_sound.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "osys_main.h" void OSystem_IPHONE::AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB) { diff --git a/backends/platform/iphone/osys_video.cpp b/backends/platform/iphone/osys_video.cpp index d30a412a9f..88368a0eec 100644 --- a/backends/platform/iphone/osys_video.cpp +++ b/backends/platform/iphone/osys_video.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "osys_main.h" const OSystem::GraphicsMode* OSystem_IPHONE::getSupportedGraphicsModes() const { diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp index d888e632d6..9b2b2ca78e 100644 --- a/backends/platform/null/null.cpp +++ b/backends/platform/null/null.cpp @@ -53,7 +53,7 @@ public: virtual bool pollEvent(Common::Event &event); virtual uint32 getMillis(); - virtual void delayMillis(uint msecs) {} + virtual void delayMillis(uint msecs); virtual void getTimeAndDate(TimeDate &t) const {} virtual Common::SeekableReadStream *createConfigReadStream(); @@ -83,7 +83,7 @@ void OSystem_NULL::initBackend() { _graphicsManager = (GraphicsManager *)new NullGraphicsManager(); _audiocdManager = (AudioCDManager *)new DefaultAudioCDManager(); _mixer = new Audio::MixerImpl(this, 22050); - + ((Audio::MixerImpl *)_mixer)->setReady(false); // Note that both the mixer and the timer manager are useless @@ -101,17 +101,10 @@ uint32 OSystem_NULL::getMillis() { return 0; } -#if defined(UNIX) -#if defined(SAMSUNGTV) -#define DEFAULT_CONFIG_FILE "/dtv/usb/sda1/.scummvmrc" -#else -#define DEFAULT_CONFIG_FILE ".scummvmrc" -#endif -#endif +void OSystem_NULL::delayMillis(uint msecs) { +} -#if !defined(UNIX) #define DEFAULT_CONFIG_FILE "scummvm.ini" -#endif Common::SeekableReadStream *OSystem_NULL::createConfigReadStream() { Common::FSNode file(DEFAULT_CONFIG_FILE); @@ -119,12 +112,8 @@ Common::SeekableReadStream *OSystem_NULL::createConfigReadStream() { } Common::WriteStream *OSystem_NULL::createConfigWriteStream() { -#ifdef __DC__ - return 0; -#else Common::FSNode file(DEFAULT_CONFIG_FILE); return file.createWriteStream(); -#endif } OSystem *OSystem_NULL_create() { diff --git a/backends/platform/openpandora/build/README-OPENPANDORA b/backends/platform/openpandora/build/README-OPENPANDORA index c3aa5e8ea9..c8aabcbb7a 100755 --- a/backends/platform/openpandora/build/README-OPENPANDORA +++ b/backends/platform/openpandora/build/README-OPENPANDORA @@ -1,4 +1,4 @@ -ScummVM - OPENPANDORA SPECIFIC README - HEAD SVN +ScummVM - OPENPANDORA SPECIFIC README ------------------------------------------------------------------------ Please refer to the: diff --git a/backends/platform/openpandora/build/config-alleng.sh b/backends/platform/openpandora/build/config-alleng.sh index cd9a17ef40..f3fa1a0f94 100755 --- a/backends/platform/openpandora/build/config-alleng.sh +++ b/backends/platform/openpandora/build/config-alleng.sh @@ -17,6 +17,13 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=openpandora --host=openpandora --disable-nasm --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --disable-vorbis --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-mad --with-mad-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-all-engines --enable-plugins --default-dynamic +./configure --backend=openpandora --host=openpandora --disable-nasm \ + --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --disable-vorbis --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-all-engines --enable-plugins --default-dynamic echo Generating config for OpenPandora complete. Check for errors. diff --git a/backends/platform/openpandora/build/config.sh b/backends/platform/openpandora/build/config.sh index 8be16f1317..9bc52a9bc4 100755 --- a/backends/platform/openpandora/build/config.sh +++ b/backends/platform/openpandora/build/config.sh @@ -17,6 +17,13 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=openpandora --host=openpandora --disable-nasm --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --disable-vorbis --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-mad --with-mad-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr --enable-plugins --default-dynamic +./configure --backend=openpandora --host=openpandora --disable-nasm \ + --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin \ + --with-mpeg2-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --disable-vorbis --enable-tremor --with-tremor-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-zlib --with-zlib-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-mad --with-mad-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-png --with-png-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr \ + --enable-plugins --default-dynamic echo Generating config for OpenPandora complete. Check for errors. diff --git a/backends/platform/openpandora/op-main.cpp b/backends/platform/openpandora/op-main.cpp index 4febd404c3..3f4208a95a 100755 --- a/backends/platform/openpandora/op-main.cpp +++ b/backends/platform/openpandora/op-main.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include <SDL/SDL.h> diff --git a/backends/platform/ps2/fileio.cpp b/backends/platform/ps2/fileio.cpp index 8c10156aaf..1919d0f743 100644 --- a/backends/platform/ps2/fileio.cpp +++ b/backends/platform/ps2/fileio.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/ps2/fileio.h" #include <tamtypes.h> @@ -410,7 +413,9 @@ uint32 Ps2File::read(void *dest, uint32 len) { } } cacheReadAhead(); +#ifdef __PS2_FILE_SEMA__ SignalSema(_sema); +#endif return destBuf - (uint8*)dest; } diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 7659d5194d..1b3ae6ba47 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -23,6 +23,12 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include <kernel.h> #include <stdio.h> #include <stdlib.h> @@ -59,6 +65,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" @@ -105,7 +113,6 @@ extern "C" int scummvm_main(int argc, char *argv[]); extern "C" int main(int argc, char *argv[]) { SifInitRpc(0); - ee_thread_t thisThread; int tid = GetThreadId(); ReferThreadStatus(tid, &thisThread); @@ -130,8 +137,11 @@ extern "C" int main(int argc, char *argv[]) { sioprintf("Creating system\n"); g_system = g_systemPs2 = new OSystem_PS2(argv[0]); - g_systemPs2->init(); +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new PS2PluginProvider()); +#endif + g_systemPs2->init(); 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 7f9ae153eb..dab3c34b51 100644 --- a/backends/platform/psp/Makefile +++ b/backends/platform/psp/Makefile @@ -67,7 +67,7 @@ endif # Variables for common Scummvm makefile CXX = psp-g++ CXXFLAGS = -O3 -Wall -Wno-multichar -fno-exceptions -fno-rtti -DEFINES = -D__PSP__ -DNONSTANDARD_PORT -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_ZLIB -DDISABLE_DOSBOX_OPL -DUSE_RGB_COLOR +DEFINES = -D__PSP__ -DNONSTANDARD_PORT -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DUSE_ZLIB -DDISABLE_DOSBOX_OPL -DUSE_RGB_COLOR -DUSE_ELF_LOADER -DMIPS_TARGET LDFLAGS := INCDIR := $(srcdir) . $(srcdir)/engines/ $(PSPSDK)/include @@ -87,8 +87,8 @@ CXX_UPDATE_DEP_FLAG = -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP # Variables for dynamic plugin building PLUGIN_PREFIX = PLUGIN_SUFFIX = .plg -PLUGIN_EXTRA_DEPS = plugin.syms scummvm-psp.elf -PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,--just-symbols=scummvm-psp.org.elf,-Tplugin.ld,--retain-symbols-file,plugin.syms -lstdc++ -lc +PLUGIN_EXTRA_DEPS = $(srcdir)/backends/plugins/elf/plugin.syms scummvm-psp.elf +PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,--just-symbols=scummvm-psp.org.elf,-T$(srcdir)/backends/plugins/psp/plugin.ld,--retain-symbols-file,$(srcdir)/backends/plugins/elf/plugin.syms -lstdc++ -lc # PSP-specific variables STRIP = psp-strip @@ -126,7 +126,8 @@ endif # PSP LIBS PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \ -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \ - -lpspkernel + -lpspkernel -lpspnet_inet + # Add in PSPSDK includes and libraries. LIBS += -lpng -lz -lstdc++ -lc -lm $(PSPLIBS) @@ -142,14 +143,16 @@ OBJS := powerman.o \ input.o \ cursor.o \ trace.o \ - psploader.o \ pspkeyboard.o \ audio.o \ thread.o \ rtc.o \ mp3.o \ png_loader.o \ - tests.o + image_viewer.o \ + tests.o \ + dummy.o + BACKEND := psp @@ -167,7 +170,7 @@ PSP_EBOOT_PIC1 = pic1.png PSP_EBOOT_SND0 = NULL PSP_EBOOT_PSAR = NULL -LDFLAGS += -Wl,-Tmain_prog.ld +LDFLAGS += -Wl,-T../../plugins/psp/main_prog.ld all: $(PSP_EBOOT) diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP index 0849d68c78..7a3cce2b75 100644 --- a/backends/platform/psp/README.PSP +++ b/backends/platform/psp/README.PSP @@ -6,36 +6,66 @@ Installation - Copy the relevant game datafiles to your memory stick (location doesn't matter). - Install ScummVM like any other homebrew. - Run ScummVM and use the launcher to add games and run them. + - Press Start to return to the launcher and play another game. Controls ======== -Right trigger - Modifier key (see below for uses) -Left trigger - ESC (Usually skips cutscenes. Depends on game) -Analog - Mouse movement -Right trigger + Analog - Fine mouse movement -D-Pad - Arrow keys (useful mostly in SCI and AGI games) -D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) -Triangle - Enter (useful for some dialogs) -Cross - Left Mouse Button (usually the main button) -Circle - Right Mouse Button (secondary button in some games) -Square - '.' (skip dialogue in some games e.g. Scumm) -Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) -Start - Global Menu. Allows you to 'Return To Launcher' to play another game -Right trigger + Start - F5 (Main Menu in some games) -Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). +Right trigger - Modifier key (see below for uses) +Left trigger - ESC (Usually skips cutscenes. Depends on game) +Analog - Mouse movement +Right trigger + Analog - Fine mouse movement +D-Pad - Arrow keys (useful mostly in SCI and AGI games) +D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) +Triangle - Enter (useful for some dialogs) +Cross - Left Mouse Button (usually the main button) +Circle - Right Mouse Button (secondary button in some games) +Square - '.' (skip dialogue in some games e.g. Scumm) +Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) +Right trigger + Start - F5 (Main Menu in some games) +Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). +Right trigger + Select - Show Image Viewer (see below) +Start - Global Menu. Allows you to 'Return To Launcher' to play another game Virtual Keyboard Mode ===================== -Start - Enter key. Also exits virtual keyboard mode -Select - Exit the virtual keyboard mode -Right trigger - Input letters: lowercase/uppercase (press to toggle) -Left trigger - Input numbers/symbols (press to toggle) -D-Pad - Select square of characters (up, down, left or right) -Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen - by the button in the corresponding position. The 2 top characters are chosen by the - triggers. -Analog - Moves in a direction (left/right/up/down) (Useful to keep moving - while typing in AGI games among other things) +Start - Enter key. Also exits virtual keyboard mode +Select - Exit the virtual keyboard mode +Right trigger - Input letters: lowercase/uppercase (press to toggle) +Left trigger - Input numbers/symbols (press to toggle) +D-Pad - Select square of characters (up, down, left or right) +Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen + by the button in the corresponding position. The 2 top characters are chosen by the + triggers. +Analog - Moves in a direction (left/right/up/down) (Useful to keep moving + while typing in AGI games among other things) + + +Image Viewer +============ +For your convenience, I've included a simple image viewer in the PSP port. +You can view anything you want while playing a game. +There are a few simple rules to follow: + +- Images must be of PNG format. If you have images in another format, many + graphics utilities will convert them for you. +- Images must be named psp_image1.png, psp_image2.png etc. This is to make + sure there's no possible conflict between image files and game files. +- Images must be placed in the game directories. When using the image viewer, + only the images of the particular game being played will be available for viewing. +- Don't place any images in the ScummVM directory, or you won't be able to see + the images in the game directories. +- There's no guarantee that you'll be able to view your image. This is because + big images take a lot of memory (more than the size of the image on disk). If there + isn't enough memory left to show the image, ScummVM will tell you so. Try to make the + image smaller by either shrinking it or reducing the colors to 256 color palette mode. + +Image Viewer Controls: +===================== +Left/Right - previous/next image (e.g. go from psp_image1.png to psp_image2.png) +Up/down - zoom in/out +Analog - move around the image +Triggers, Start: - exit image viewer + 1st Person Game Mode (Can be ignored by most users) ==================== @@ -45,11 +75,12 @@ safely ignore this mode. To enter or leave this mode, use the combo: Right Trigger + Left Trigger + Square Some buttons have been switched around to make these games more playable: -Square - Is the modifier key instead of Right Trigger. -Left/Right Trigger - Strafe left/right -D-Pad Left/Right - Turn left/right -Square + D-Pad - F1/F2/F3/F4 -Square + Start - Esc (shows game menu) +Square - Is the modifier key instead of Right Trigger. +Left/Right Trigger - Strafe left/right +D-Pad Left/Right - Turn left/right +Square + D-Pad - F1/F2/F3/F4 +Square + Select - Image Viewer +Square + Start - Esc (shows game menu) Notes @@ -86,12 +117,12 @@ Q: Can I run game X with this? A: You can find the list of supported games on the compatibility page at http://www.scummvm.org Note that ScummVM is NOT an emulator. The supported games engines have been painstakingly rewritten. - It's not easy to add support for a game you want that currently isn't supported. + It's not easy to add support for a game you want that currently isn't supported. Q: My Monkey Island 1 doesn't have any music, what gives? A: If your version of Monkey Island came on a CD then it has the music as CD Audio tracks. You need to rip those to MP3/Ogg (MP3 is preferred), naming them track1.mp3 track2.mp3 - etc. and copy them to the same directory as the game datafiles for music to work. + etc. and copy them to the same directory as the game datafiles for music to work. Q: Game X crashes, or feature Y doesn't work. Can you fix this? A: Possibly. @@ -111,19 +142,19 @@ To build ScummVM for PSP you need: - ScummVM source code (svn co https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk) -- PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) +- PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) -- PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) - Note: This usually gets installed by the PSP toolchain, - so you don't have to do it manually. +- PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) + Note: This usually gets installed by the PSP toolchain, + so you don't have to do it manually. -- zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) +- zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) -- libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng) +- libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng) -- libmad(*) (svn co svn://svn.pspdev.org/psp/trunk/libmad) +- libmad(*) (svn co svn://svn.pspdev.org/psp/trunk/libmad) -- libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) +- libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) (*) = optional diff --git a/backends/platform/psp/README.PSP.in b/backends/platform/psp/README.PSP.in index 57058abd85..978f8a60bd 100644 --- a/backends/platform/psp/README.PSP.in +++ b/backends/platform/psp/README.PSP.in @@ -6,36 +6,66 @@ Installation - Copy the relevant game datafiles to your memory stick (location doesn't matter). - Install ScummVM like any other homebrew. - Run ScummVM and use the launcher to add games and run them. + - Press Start to return to the launcher and play another game. Controls ======== -Right trigger - Modifier key (see below for uses) -Left trigger - ESC (Usually skips cutscenes. Depends on game) -Analog - Mouse movement -Right trigger + Analog - Fine mouse movement -D-Pad - Arrow keys (useful mostly in SCI and AGI games) -D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) -Triangle - Enter (useful for some dialogs) -Cross - Left Mouse Button (usually the main button) -Circle - Right Mouse Button (secondary button in some games) -Square - '.' (skip dialogue in some games e.g. Scumm) -Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) -Start - Global Menu. Allows you to 'Return To Launcher' to play another game -Right trigger + Start - F5 (Main Menu in some games) -Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). +Right trigger - Modifier key (see below for uses) +Left trigger - ESC (Usually skips cutscenes. Depends on game) +Analog - Mouse movement +Right trigger + Analog - Fine mouse movement +D-Pad - Arrow keys (useful mostly in SCI and AGI games) +D-Pad + Right Trigger - Diagonal arrow keys (it's hard to input diagonals on some PSPs) +Triangle - Enter (useful for some dialogs) +Cross - Left Mouse Button (usually the main button) +Circle - Right Mouse Button (secondary button in some games) +Square - '.' (skip dialogue in some games e.g. Scumm) +Right trigger + Square - Spacebar (useful in Gobli*ns and SCI games) +Right trigger + Start - F5 (Main Menu in some games) +Select - Show/Hide Virtual Keyboard. Hold down to move keyboard onscreen (with D-Pad). +Right trigger + Select - Show Image Viewer (see below) +Start - Global Menu. Allows you to 'Return To Launcher' to play another game Virtual Keyboard Mode ===================== -Start - Enter key. Also exits virtual keyboard mode -Select - Exit the virtual keyboard mode -Right trigger - Input letters: lowercase/uppercase (press to toggle) -Left trigger - Input numbers/symbols (press to toggle) -D-Pad - Select square of characters (up, down, left or right) -Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen - by the button in the corresponding position. The 2 top characters are chosen by the - triggers. -Analog - Moves in a direction (left/right/up/down) (Useful to keep moving - while typing in AGI games among other things) +Start - Enter key. Also exits virtual keyboard mode +Select - Exit the virtual keyboard mode +Right trigger - Input letters: lowercase/uppercase (press to toggle) +Left trigger - Input numbers/symbols (press to toggle) +D-Pad - Select square of characters (up, down, left or right) +Buttons/Triggers - Choose a specific character in the square. The four center characters are chosen + by the button in the corresponding position. The 2 top characters are chosen by the + triggers. +Analog - Moves in a direction (left/right/up/down) (Useful to keep moving + while typing in AGI games among other things) + + +Image Viewer +============ +For your convenience, I've included a simple image viewer in the PSP port. +You can view anything you want while playing a game. +There are a few simple rules to follow: + +- Images must be of PNG format. If you have images in another format, many + graphics utilities will convert them for you. +- Images must be named psp_image1.png, psp_image2.png etc. This is to make + sure there's no possible conflict between image files and game files. +- Images must be placed in the game directories. When using the image viewer, + only the images of the particular game being played will be available for viewing. +- Don't place any images in the ScummVM directory, or you won't be able to see + the images in the game directories. +- There's no guarantee that you'll be able to view your image. This is because + big images take a lot of memory (more than the size of the image on disk). If there + isn't enough memory left to show the image, ScummVM will tell you so. Try to make the + image smaller by either shrinking it or reducing the colors to 256 color palette mode. + +Image Viewer Controls: +===================== +Left/Right - previous/next image (e.g. go from psp_image1.png to psp_image2.png) +Up/down - zoom in/out +Analog - move around the image +Triggers, Start: - exit image viewer + 1st Person Game Mode (Can be ignored by most users) ==================== @@ -45,11 +75,12 @@ safely ignore this mode. To enter or leave this mode, use the combo: Right Trigger + Left Trigger + Square Some buttons have been switched around to make these games more playable: -Square - Is the modifier key instead of Right Trigger. -Left/Right Trigger - Strafe left/right -D-Pad Left/Right - Turn left/right -Square + D-Pad - F1/F2/F3/F4 -Square + Start - Esc (shows game menu) +Square - Is the modifier key instead of Right Trigger. +Left/Right Trigger - Strafe left/right +D-Pad Left/Right - Turn left/right +Square + D-Pad - F1/F2/F3/F4 +Square + Select - Image Viewer +Square + Start - Esc (shows game menu) Notes @@ -86,12 +117,12 @@ Q: Can I run game X with this? A: You can find the list of supported games on the compatibility page at http://www.scummvm.org Note that ScummVM is NOT an emulator. The supported games engines have been painstakingly rewritten. - It's not easy to add support for a game you want that currently isn't supported. + It's not easy to add support for a game you want that currently isn't supported. Q: My Monkey Island 1 doesn't have any music, what gives? A: If your version of Monkey Island came on a CD then it has the music as CD Audio tracks. You need to rip those to MP3/Ogg (MP3 is preferred), naming them track1.mp3 track2.mp3 - etc. and copy them to the same directory as the game datafiles for music to work. + etc. and copy them to the same directory as the game datafiles for music to work. Q: Game X crashes, or feature Y doesn't work. Can you fix this? A: Possibly. @@ -111,19 +142,19 @@ To build ScummVM for PSP you need: - ScummVM source code (svn co https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk) -- PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) +- PSP toolchain (svn co svn://svn.pspdev.org/psp/trunk/psptoolchain) -- PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) - Note: This usually gets installed by the PSP toolchain, - so you don't have to do it manually. +- PSPSDK (svn co svn://svn.pspdev.org/psp/trunk/pspsdk) + Note: This usually gets installed by the PSP toolchain, + so you don't have to do it manually. -- zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) +- zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) -- libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng) +- libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng) -- libmad(*) (svn co svn://svn.pspdev.org/psp/trunk/libmad) +- libmad(*) (svn co svn://svn.pspdev.org/psp/trunk/libmad) -- libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) +- libTremor(*) (svn co svn://svn.pspdev.org/psp/trunk/libTremor) (*) = optional diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp index 916b6c1aae..630b486988 100644 --- a/backends/platform/psp/display_client.cpp +++ b/backends/platform/psp/display_client.cpp @@ -347,7 +347,6 @@ void Buffer::copyFromRect(const byte *buf, uint32 pitch, int destX, int destY, u PspMemory::fastCopy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth)); } else { do { - //memcpy(dst, buf, recWidthInBytes); if (_pixelFormat.swapRB) PspMemorySwap::fastSwap(dst, buf, recWidthInBytes, _pixelFormat); else @@ -379,45 +378,45 @@ void Buffer::copyToArray(byte *dst, int pitch) { } while (--h); } -/* We can size the buffer either by texture size (multiple of 2^n) or source size. The GU can - really handle both, but is supposed to get only 2^n size buffers */ void Buffer::setSize(uint32 width, uint32 height, HowToSize textureOrSource/*=kSizeByTextureSize*/) { DEBUG_ENTER_FUNC(); - PSP_DEBUG_PRINT("w[%u], h[%u], %s\n", width, height, textureOrSource ? "size by source" : "size by texture"); - + + // We can size the buffer either by texture size (multiple of 2^n) or source size. + // At higher sizes, increasing the texture size to 2^n is a waste of space. At these sizes kSizeBySourceSize should be used. + _sourceSize.width = width; _sourceSize.height = height; - _textureSize.width = scaleUpToPowerOfTwo(width); + _textureSize.width = scaleUpToPowerOfTwo(width); // can only scale up to 512 _textureSize.height = scaleUpToPowerOfTwo(height); - + if (textureOrSource == kSizeByTextureSize) { _width = _textureSize.width; _height = _textureSize.height; - } else { /* kSizeBySourceSize */ - _width = _sourceSize.width; + } else { // sizeBySourceSize + _width = _sourceSize.width; _height = _sourceSize.height; + + // adjust allocated width to be divisible by 32. + // The GU can only handle multiples of 16 bytes. A 4 bit image x 32 will give us 16 bytes + // We don't necessarily know the depth of the pixels here. So just make it divisible by 32. + uint32 checkDiv = _width & 31; + if (checkDiv) + _width += 32 - checkDiv; } + + PSP_DEBUG_PRINT("width[%u], height[%u], texW[%u], texH[%u], sourceW[%d], sourceH[%d] %s\n", _width, _height, _textureSize.width, _textureSize.height, _sourceSize.width, _sourceSize.height, textureOrSource ? "size by source" : "size by texture"); } -/* Scale a dimension (width/height) up to power of 2 for the texture */ +// Scale a dimension (width/height) up to power of 2 for the texture +// Will only go up to 512 since that's the maximum PSP texture size uint32 Buffer::scaleUpToPowerOfTwo(uint32 size) { - uint32 textureDimension = 0; - if (size <= 16) - textureDimension = 16; - else if (size <= 32) - textureDimension = 32; - else if (size <= 64) - textureDimension = 64; - else if (size <= 128) - textureDimension = 128; - else if (size <= 256) - textureDimension = 256; - else - textureDimension = 512; + uint32 textureDimension = 16; + while (size > textureDimension && textureDimension < 512) + textureDimension <<= 1; - PSP_DEBUG_PRINT("power of 2 = %u\n", textureDimension); + PSP_DEBUG_PRINT("size[%u]. power of 2[%u]\n", size, textureDimension); return textureDimension; } @@ -540,51 +539,41 @@ void GuRenderer::render() { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT("Buffer[%p] Palette[%p]\n", _buffer->getPixels(), _palette->getRawValues()); - setMaxTextureOffsetByIndex(0, 0); - guProgramDrawBehavior(); if (_buffer->hasPalette()) guLoadPalette(); guProgramTextureFormat(); - guLoadTexture(); - - Vertex *vertices = guGetVertices(); - fillVertices(vertices); - - guDrawVertices(vertices); - - if (_buffer->getSourceWidth() > 512) { - setMaxTextureOffsetByIndex(1, 0); - guLoadTexture(); - - vertices = guGetVertices(); - fillVertices(vertices); - - guDrawVertices(vertices); + // Loop over patches of 512x512 pixel textures and draw them + for (uint32 j = 0; j < _buffer->getSourceHeight(); j += 512) { + _textureLoadOffset.y = j; + + for (uint32 i = 0; i < _buffer->getSourceWidth(); i += 512) { + _textureLoadOffset.x = i; + + guLoadTexture(); + Vertex *vertices = guGetVertices(); + fillVertices(vertices); + + guDrawVertices(vertices); + } } } -inline void GuRenderer::setMaxTextureOffsetByIndex(uint32 x, uint32 y) { - DEBUG_ENTER_FUNC(); - const uint32 maxTextureSizeShift = 9; /* corresponds to 512 = max texture size*/ - - _maxTextureOffset.x = x << maxTextureSizeShift; /* x times 512 */ - _maxTextureOffset.y = y << maxTextureSizeShift; /* y times 512 */ -} - inline void GuRenderer::guProgramDrawBehavior() { DEBUG_ENTER_FUNC(); - PSP_DEBUG_PRINT("blending[%s] colorTest[%s] reverseAlpha[%s] keyColor[%u]\n", _blending ? "on" : "off", _colorTest ? "on" : "off", _alphaReverse ? "on" : "off", _keyColor); + PSP_DEBUG_PRINT("blending[%s] colorTest[%s] reverseAlpha[%s] keyColor[%u]\n", + _blending ? "on" : "off", _colorTest ? "on" : "off", + _alphaReverse ? "on" : "off", _keyColor); if (_blending) { sceGuEnable(GU_BLEND); - if (_alphaReverse) // Reverse the alpha value (0 is 1) + if (_alphaReverse) // Reverse the alpha value (ie. 0 is 1) easier to do in some cases sceGuBlendFunc(GU_ADD, GU_ONE_MINUS_SRC_ALPHA, GU_SRC_ALPHA, 0, 0); - else // Normal alpha values + else // Normal alpha values sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); } else @@ -592,7 +581,9 @@ inline void GuRenderer::guProgramDrawBehavior() { if (_colorTest) { sceGuEnable(GU_COLOR_TEST); - sceGuColorFunc(GU_NOTEQUAL, _keyColor, 0x00ffffff); + sceGuColorFunc(GU_NOTEQUAL, // show only colors not equal to this color + _keyColor, + 0x00ffffff); // match everything but alpha } else sceGuDisable(GU_COLOR_TEST); } @@ -613,7 +604,8 @@ inline void GuRenderer::guLoadPalette() { PSP_DEBUG_PRINT("bpp[%d], pixelformat[%d], mask[%x]\n", _buffer->getBitsPerPixel(), _palette->getPixelFormat(), mask); sceGuClutMode(convertToGuPixelFormat(_palette->getPixelFormat()), 0, mask, 0); - sceGuClutLoad(_palette->getNumOfEntries() >> 3, _palette->getRawValues()); + sceGuClutLoad(_palette->getNumOfEntries() >> 3, // it's in batches of 8 for some reason + _palette->getRawValues()); } inline void GuRenderer::guProgramTextureFormat() { @@ -659,7 +651,17 @@ inline uint32 GuRenderer::convertToGuPixelFormat(PSPPixelFormat::Type format) { inline void GuRenderer::guLoadTexture() { DEBUG_ENTER_FUNC(); - sceGuTexImage(0, _buffer->getTextureWidth(), _buffer->getTextureHeight(), _buffer->getWidth(), _buffer->getPixels() + _buffer->_pixelFormat.pixelsToBytes(_maxTextureOffset.x)); + byte *startPoint = _buffer->getPixels(); + if (_textureLoadOffset.x) + startPoint += _buffer->_pixelFormat.pixelsToBytes(_textureLoadOffset.x); + if (_textureLoadOffset.y) + startPoint += _buffer->getWidthInBytes() * _textureLoadOffset.y; + + sceGuTexImage(0, + _buffer->getTextureWidth(), // texture width (must be power of 2) + _buffer->getTextureHeight(), // texture height (must be power of 2) + _buffer->getWidth(), // width of a line of the image (to get to the next line) + startPoint); // where to start reading } inline Vertex *GuRenderer::guGetVertices() { @@ -677,41 +679,41 @@ void GuRenderer::fillVertices(Vertex *vertices) { uint32 outputWidth = _displayManager->getOutputWidth(); uint32 outputHeight = _displayManager->getOutputHeight(); - float textureStartX, textureStartY, textureEndX, textureEndY; - // Texture adjustments for eliminating half-pixel artifacts from scaling // Not necessary if we don't scale - float textureAdjustment = 0.0f; + float textureFix = 0.0f; if (_useGlobalScaler && - (_displayManager->getScaleX() != 1.0f || _displayManager->getScaleX() != 1.0f)) - textureAdjustment = 0.5f; - - textureStartX = textureAdjustment + _offsetInBuffer.x; //debug - textureStartY = textureAdjustment + _offsetInBuffer.y; - // We subtract maxTextureOffset because our shifted texture starts at 512 and will go to 640 - textureEndX = _offsetInBuffer.x + _drawSize.width - textureAdjustment - _maxTextureOffset.x; - textureEndY = _offsetInBuffer.y + _drawSize.height - textureAdjustment; - + (_displayManager->getScaleX() != 1.0f || _displayManager->getScaleY() != 1.0f)) + textureFix = 0.5f; + + // These coordinates describe an area within the texture. ie. we already loaded a square of texture, + // now the coordinates within it are 0 to the edge of the area of the texture we want to draw + float textureStartX = textureFix + _offsetInBuffer.x; + float textureStartY = textureFix + _offsetInBuffer.y; + + int textureLeftX = _drawSize.width - _textureLoadOffset.x; + if (textureLeftX > 512) + textureLeftX = 512; + int textureLeftY = _drawSize.height - _textureLoadOffset.y; + if (textureLeftY > 512) + textureLeftY = 512; + float textureEndX = -textureFix + _offsetInBuffer.x + textureLeftX; + float textureEndY = -textureFix + _offsetInBuffer.y + textureLeftY; // For scaling to the final image size, calculate the gaps on both sides 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 scaledOffsetOnScreenX = scaleSourceToOutput(true, _offsetOnScreen.x); + float scaledOffsetOnScreenY = scaleSourceToOutput(false, _offsetOnScreen.y); - float imageStartX, imageStartY, imageEndX, imageEndY; + float imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutput(true, stretch(true, _textureLoadOffset.x))); + float imageStartY = gapY + scaledOffsetOnScreenY + (scaleSourceToOutput(false, stretch(false, _textureLoadOffset.y))); - imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutputX(_maxTextureOffset.x)); - imageStartY = gapY + scaledOffsetOnScreenY; - - if (_fullScreen) { // shortcut - imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX; - imageEndY = PSP_SCREEN_HEIGHT - gapY + scaledOffsetOnScreenY; // needed for screen shake - } else { /* !fullScreen */ - imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width); - imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height); - } + float imageEndX, imageEndY; + + imageEndX = imageStartX + scaleSourceToOutput(true, stretch(true, textureLeftX)); + imageEndY = imageStartY + scaleSourceToOutput(false, stretch(false, textureLeftY)); vertices[0].u = textureStartX; vertices[0].v = textureStartY; @@ -729,8 +731,8 @@ void GuRenderer::fillVertices(Vertex *vertices) { PSP_DEBUG_PRINT("ImageStart: X[%f] Y[%f] ImageEnd: X[%.1f] Y[%.1f]\n", imageStartX, imageStartY, imageEndX, imageEndY); } -/* Scale the input X offset to appear in proper position on the screen */ -inline float GuRenderer::scaleSourceToOutputX(float offset) { +/* Scale the input X/Y offset to appear in proper position on the screen */ +inline float GuRenderer::scaleSourceToOutput(bool x, float offset) { float result; if (!_useGlobalScaler) @@ -738,28 +740,22 @@ inline float GuRenderer::scaleSourceToOutputX(float offset) { else if (!offset) result = 0.0f; else - result = offset * _displayManager->getScaleX(); + result = x ? offset * _displayManager->getScaleX() : offset * _displayManager->getScaleY(); return result; } -/* Scale the input Y offset to appear in proper position on the screen */ -inline float GuRenderer::scaleSourceToOutputY(float offset) { - float result; - - if (!_useGlobalScaler) - result = offset; - else if (!offset) - result = 0.0f; - else - result = offset * _displayManager->getScaleY(); - - return result; +/* Scale the input X/Y offset to appear in proper position on the screen */ +inline float GuRenderer::stretch(bool x, float size) { + if (!_stretch) + return size; + return (x ? size * _stretchX : size * _stretchY); } inline void GuRenderer::guDrawVertices(Vertex *vertices) { DEBUG_ENTER_FUNC(); + // This function shouldn't need changing. The '32' here refers to floating point vertices. sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2, 0, vertices); } diff --git a/backends/platform/psp/display_client.h b/backends/platform/psp/display_client.h index feec477282..005fc76c7c 100644 --- a/backends/platform/psp/display_client.h +++ b/backends/platform/psp/display_client.h @@ -174,8 +174,13 @@ protected: class GuRenderer { public: // Constructors - GuRenderer() : _useGlobalScaler(false), _buffer(0), _palette(0), _blending(false), _alphaReverse(false), _colorTest(false), _keyColor(0), _fullScreen(false) {} - GuRenderer(Buffer *buffer, Palette *palette) : _useGlobalScaler(false), _buffer(buffer), _palette(palette), _blending(false), _alphaReverse(false), _colorTest(false), _keyColor(0), _fullScreen(false) {} + GuRenderer() : _useGlobalScaler(false), _buffer(0), _palette(0), + _blending(false), _alphaReverse(false), _colorTest(false), + _keyColor(0), _fullScreen(false), _stretch(false), _stretchX(1.0f), _stretchY(1.0f) {} + GuRenderer(Buffer *buffer, Palette *palette) : + _useGlobalScaler(false), _buffer(buffer), _palette(palette), + _blending(false), _alphaReverse(false), _colorTest(false), + _keyColor(0), _fullScreen(false), _stretch(false), _stretchX(1.0f), _stretchY(1.0f) {} static void setDisplayManager(DisplayManager *dm) { _displayManager = dm; } // Called by the Display Manager // Setters @@ -190,8 +195,7 @@ public: } void setBuffer(Buffer *buffer) { _buffer = buffer; } void setPalette(Palette *palette) { _palette = palette; } - void setMaxTextureOffsetByIndex(uint32 x, uint32 y); // For drawing multiple textures - void setOffsetOnScreen(uint32 x, uint32 y) { _offsetOnScreen.x = x; _offsetOnScreen.y = y; } + void setOffsetOnScreen(int x, int y) { _offsetOnScreen.x = x; _offsetOnScreen.y = y; } void setOffsetInBuffer(uint32 x, uint32 y) { _offsetInBuffer.x = x; _offsetInBuffer.y = y; } void setColorTest(bool value) { _colorTest = value; } void setKeyColor(uint32 value) { _keyColor = _buffer->_pixelFormat.convertTo32BitColor(value); } @@ -199,6 +203,8 @@ public: void setAlphaReverse(bool value) { _alphaReverse = value; } void setFullScreen(bool value) { _fullScreen = value; } // Shortcut for rendering void setUseGlobalScaler(bool value) { _useGlobalScaler = value; } // Scale to screen + void setStretch(bool active) { _stretch = active; } + void setStretchXY(float x, float y) { _stretchX = x; _stretchY = y; } static void cacheInvalidate(void *pointer, uint32 size); @@ -216,11 +222,11 @@ protected: void guDrawVertices(Vertex *vertices); uint32 convertToGuPixelFormat(PSPPixelFormat::Type format); - float scaleSourceToOutputX(float offset); - float scaleSourceToOutputY(float offset); + float scaleSourceToOutput(bool x, float offset); + float stretch(bool x, float size); friend class MasterGuRenderer; - Point _maxTextureOffset; ///> For rendering textures > 512 pixels + Point _textureLoadOffset; ///> For rendering textures > 512 pixels Point _offsetOnScreen; ///> Where on screen to draw Point _offsetInBuffer; ///> Where in the texture to draw bool _useGlobalScaler; ///> Scale to the output size on screen @@ -233,6 +239,8 @@ protected: bool _colorTest; uint32 _keyColor; ///> Color to test against for color test. in 32 bits. bool _fullScreen; ///> Speeds up for fullscreen rendering + bool _stretch; ///> Whether zooming is activated + float _stretchX, _stretchY; }; #endif /* PSP_SCREEN_H */ diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp index 5d75ac531e..63bfe8bd24 100644 --- a/backends/platform/psp/display_manager.cpp +++ b/backends/platform/psp/display_manager.cpp @@ -34,6 +34,7 @@ #include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/cursor.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/image_viewer.h" #define USE_DISPLAY_CALLBACK // to use callback for finishing the render #include "backends/platform/psp/display_manager.h" @@ -62,7 +63,7 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = { // Class VramAllocator ----------------------------------- -DECLARE_SINGLETON(VramAllocator) +DECLARE_SINGLETON(VramAllocator); //#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ //#define __PSP_DEBUG_PRINT__ @@ -282,13 +283,17 @@ void DisplayManager::init() { _masterGuRenderer.setupCallbackThread(); #endif + // Init overlay since we never change the size + _overlay->deallocate(); + _overlay->setBytesPerPixel(sizeof(OverlayColor)); + _overlay->setSize(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); + _overlay->allocate(); } void DisplayManager::setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); PSP_DEBUG_PRINT("w[%u], h[%u], pformat[%p]\n", width, height, format); - _overlay->deallocate(); _screen->deallocate(); _screen->setScummvmPixelFormat(format); @@ -297,10 +302,6 @@ void DisplayManager::setSizeAndPixelFormat(uint width, uint height, const Graphi _cursor->setScreenPaletteScummvmPixelFormat(format); - _overlay->setBytesPerPixel(sizeof(OverlayColor)); - _overlay->setSize(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT); - _overlay->allocate(); - _displayParams.screenSource.width = width; _displayParams.screenSource.height = height; calculateScaleParams(); @@ -385,10 +386,12 @@ bool DisplayManager::renderAll() { #endif /* USE_DISPLAY_CALLBACK */ // This is cheaper than checking time, so we do it first + // Any one of these being dirty causes everything to draw if (!_screen->isDirty() && - (!_overlay->isDirty()) && - (!_cursor->isDirty()) && - (!_keyboard->isDirty())) { + !_overlay->isDirty() && + !_cursor->isDirty() && + !_keyboard->isDirty() && + !_imageViewer->isDirty()) { PSP_DEBUG_PRINT("Nothing dirty\n"); return true; // nothing to render } @@ -396,34 +399,35 @@ bool DisplayManager::renderAll() { if (!isTimeToUpdate()) return false; // didn't render - PSP_DEBUG_PRINT("screen[%s], overlay[%s], cursor[%s], keyboard[%s]\n", + PSP_DEBUG_PRINT("dirty: screen[%s], overlay[%s], cursor[%s], keyboard[%s], imageViewer[%s]\n", _screen->isDirty() ? "true" : "false", _overlay->isDirty() ? "true" : "false", _cursor->isDirty() ? "true" : "false", - _keyboard->isDirty() ? "true" : "false" + _keyboard->isDirty() ? "true" : "false", + _imageViewer->isDirty() ? "true" : "false", ); _masterGuRenderer.guPreRender(); // Set up rendering _screen->render(); - _screen->setClean(); // clean out dirty bit + + if (_imageViewer->isVisible()) + _imageViewer->render(); + _imageViewer->setClean(); if (_overlay->isVisible()) - _overlay->render(); - + _overlay->render(); _overlay->setClean(); if (_cursor->isVisible()) _cursor->render(); - _cursor->setClean(); if (_keyboard->isVisible()) _keyboard->render(); - _keyboard->setClean(); - + _masterGuRenderer.guPostRender(); return true; // rendered successfully diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h index 00d3851243..4537af0096 100644 --- a/backends/platform/psp/display_manager.h +++ b/backends/platform/psp/display_manager.h @@ -96,6 +96,7 @@ class Screen; class Overlay; class Cursor; class PSPKeyboard; +class ImageViewer; /** * Class that manages all display clients @@ -107,7 +108,8 @@ public: KEEP_ASPECT_RATIO, STRETCHED_FULL_SCREEN }; - DisplayManager() : _screen(0), _cursor(0), _overlay(0), _keyboard(0), _lastUpdateTime(0), _graphicsMode(0) {} + DisplayManager() : _screen(0), _cursor(0), _overlay(0), _keyboard(0), + _imageViewer(0), _lastUpdateTime(0), _graphicsMode(0) {} ~DisplayManager(); void init(); @@ -118,11 +120,13 @@ public: uint32 getDefaultGraphicsMode() const { return STRETCHED_FULL_SCREEN; } const OSystem::GraphicsMode* getSupportedGraphicsModes() const { return _supportedModes; } - // Setters + // Setters for pointers void setScreen(Screen *screen) { _screen = screen; } void setCursor(Cursor *cursor) { _cursor = cursor; } void setOverlay(Overlay *overlay) { _overlay = overlay; } void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } + void setImageViewer(ImageViewer *imageViewer) { _imageViewer = imageViewer; } + void setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format); // Getters @@ -148,6 +152,7 @@ private: Cursor *_cursor; Overlay *_overlay; PSPKeyboard *_keyboard; + ImageViewer *_imageViewer; MasterGuRenderer _masterGuRenderer; uint32 _lastUpdateTime; // For limiting FPS diff --git a/backends/platform/psp/dummy.cpp b/backends/platform/psp/dummy.cpp new file mode 100644 index 0000000000..4236734d4b --- /dev/null +++ b/backends/platform/psp/dummy.cpp @@ -0,0 +1,59 @@ +/* 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 "common/scummsys.h" + #include <time.h> + #include <stdlib.h> + #include <stdio.h> + #include <png.h> + #include <sys/socket.h> + +//void userWriteFn(png_structp png_ptr, png_bytep data, png_size_t length) { +//} + +//void userFlushFn(png_structp png_ptr) { +//} + + // Dummy functions are pulled in so that we don't need to build the plugins with certain libs + + int dummyFunc() { + + // For Broken Sword 2.5 + volatile int i; + i = clock(); + rename("dummyA", "dummyB"); + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_set_write_fn(png_ptr, NULL, NULL, NULL); + png_infop info_ptr; + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + png_destroy_write_struct(&png_ptr, &info_ptr); + + // For lua's usage of libc: very heavy usage so it pulls in sockets? + setsockopt(0, 0, 0, NULL, 0); + getsockopt(0, 0, 0, NULL, NULL); + + return i; +}
\ No newline at end of file diff --git a/backends/platform/psp/elf32.h b/backends/platform/psp/elf32.h deleted file mode 100644 index 616cc4b4d2..0000000000 --- a/backends/platform/psp/elf32.h +++ /dev/null @@ -1,209 +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 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/psp/image_viewer.cpp b/backends/platform/psp/image_viewer.cpp new file mode 100644 index 0000000000..26b7f31c97 --- /dev/null +++ b/backends/platform/psp/image_viewer.cpp @@ -0,0 +1,327 @@ +/* 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 $ + * + */ + +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "common/scummsys.h" +#include "common/str.h" +#include "common/stream.h" +#include "common/archive.h" +#include "common/events.h" +#include "common/ptr.h" +#include "gui/message.h" +#include "engines/engine.h" +#include "backends/platform/psp/input.h" +#include "backends/platform/psp/display_manager.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/image_viewer.h" +#include "backends/platform/psp/png_loader.h" +#include "backends/platform/psp/thread.h" + +static const char *imageName = "psp_image"; +#define PSP_SCREEN_HEIGHT 272 +#define PSP_SCREEN_WIDTH 480 + +bool ImageViewer::load(int imageNum) { + if (_init) + unload(); + + // build string + char number[8]; + sprintf(number, "%d", imageNum); + Common::String imageNameStr(imageName); + Common::String specificImageName = imageNameStr + Common::String(number) + Common::String(".png"); + + // search for image file + if (!SearchMan.hasFile(specificImageName)) { + PSP_ERROR("file %s not found\n", specificImageName.c_str()); + return false; + } + + Common::ScopedPtr<Common::SeekableReadStream> file(SearchMan.createReadStreamForMember(specificImageName)); + + _buffer = new Buffer(); + _palette = new Palette(); + _renderer = new GuRenderer(); + + assert(_buffer); + assert(_palette); + assert(_renderer); + + // Load a PNG into our buffer and palette. Size it by the actual size of the image + PngLoader image(file, *_buffer, *_palette, Buffer::kSizeBySourceSize); + + PngLoader::Status status = image.allocate(); // allocate the buffers for the file + + char error[100]; + if (status == PngLoader::BAD_FILE) { + sprintf(error, "Cannot display %s. Not a proper PNG file", specificImageName.c_str()); + GUI::TimedMessageDialog dialog(error, 4000); + dialog.runModal(); + return false; + } else if (status == PngLoader::OUT_OF_MEMORY) { + sprintf(error, "Out of memory loading %s. Try making the image smaller", specificImageName.c_str()); + GUI::TimedMessageDialog dialog(error, 4000); + dialog.runModal(); + return false; + } + // try to load the image file + if (!image.load()) { + sprintf(error, "Cannot display %s. Not a proper PNG file", specificImageName.c_str()); + GUI::TimedMessageDialog dialog(error, 4000); + dialog.runModal(); + return false; + } + + setConstantRendererOptions(); + setFullScreenImageParams(); // prepare renderer for full screen view + + _imageNum = imageNum; // now we can say we displayed this image + _init = true; + + return true; +} + +void ImageViewer::setConstantRendererOptions() { + _renderer->setBuffer(_buffer); + _renderer->setPalette(_palette); + + _renderer->setAlphaBlending(false); + _renderer->setColorTest(false); + _renderer->setUseGlobalScaler(false); + _renderer->setStretch(true); + _renderer->setOffsetInBuffer(0, 0); + _renderer->setDrawWholeBuffer(); +} + +void ImageViewer::unload() { + _init = false; + delete _buffer; + delete _palette; + delete _renderer; + _buffer = 0; + _palette = 0; + _renderer = 0; +} + +void ImageViewer::resetOnEngineDone() { + _imageNum = 0; +} + +void ImageViewer::setVisible(bool visible) { + DEBUG_ENTER_FUNC(); + + if (_visible == visible) + return; + + // from here on, we're making the loader visible + if (visible && g_engine) { // we can only run the image viewer when there's an engine + g_engine->pauseEngine(true); + + load(_imageNum ? _imageNum : 1); // load the 1st image or the current + } + + if (visible && _init) { // we managed to load + _visible = true; + setViewerButtons(true); + + { // so dialog goes out of scope, destroying all allocations + GUI::TimedMessageDialog dialog("Image Viewer", 1000); + dialog.runModal(); + } + + runLoop(); // only listen to viewer events + } else { // we were asked to make invisible or failed to load + _visible = false; + unload(); + setViewerButtons(false); + + if (g_engine && g_engine->isPaused()) + g_engine->pauseEngine(false); + } + setDirty(); +} + +// This is the only way we can truly pause the games +// Sad but true. +void ImageViewer::runLoop() { + while (_visible) { + Common::Event event; + PspThread::delayMillis(30); + _inputHandler->getAllInputs(event); + _displayManager->renderAll(); + } +} + +void ImageViewer::setViewerButtons(bool active) { + _inputHandler->setImageViewerMode(active); +} + +void ImageViewer::loadNextImage() { + if (!load(_imageNum+1)) { // try to load the next image + if (!load(_imageNum)) // we failed, so reload the current image + setVisible(false); // just hide + } + setDirty(); +} + +void ImageViewer::loadLastImage() { + if (_imageNum - 1 > 0) { + if (!load(_imageNum-1)) + if (!load(_imageNum)) + setVisible(false); // we can't even show the old image so hide + } + setDirty(); +} + +void ImageViewer::setFullScreenImageParams() { + // we try to fit the image fullscreen at least in one dimension + uint32 width = _buffer->getSourceWidth(); + uint32 height = _buffer->getSourceHeight(); + + _centerX = PSP_SCREEN_WIDTH / 2.0f; + _centerY = PSP_SCREEN_HEIGHT / 2.0f; + + // see if we fit width wise + if (PSP_SCREEN_HEIGHT >= (int)((height * PSP_SCREEN_WIDTH) / (float)width)) { + setZoom(PSP_SCREEN_WIDTH / (float)width); + } else { + setZoom(PSP_SCREEN_HEIGHT / (float)height); + } +} + +void ImageViewer::render() { + if (_init) { + assert(_buffer); + assert(_renderer); + + // move the image slightly. Note that we count on the renderer's timing + switch (_movement) { + case EVENT_MOVE_LEFT: + moveImageX(-_visibleWidth / 100.0f); + break; + case EVENT_MOVE_UP: + moveImageY(-_visibleHeight / 100.0f); + break; + case EVENT_MOVE_RIGHT: + moveImageX(_visibleWidth / 100.0f); + break; + case EVENT_MOVE_DOWN: + moveImageY(_visibleHeight / 100.0f); + break; + default: + break; + } + _renderer->render(); + } +} + +void ImageViewer::modifyZoom(bool up) { + float factor = _zoomFactor; + if (up) + factor += 0.1f; + else // down + factor -= 0.1f; + + setZoom(factor); +} + +void ImageViewer::setZoom(float value) { + if (value <= 0.0f) // don't want 0 or negative zoom + return; + + _zoomFactor = value; + _renderer->setStretchXY(value, value); + setOffsetParams(); +} + +void ImageViewer::moveImageX(float val) { + float newVal = _centerX + val; + + if (newVal - (_visibleWidth / 2) > PSP_SCREEN_WIDTH - 4 || newVal + (_visibleWidth / 2) < 4) + return; + _centerX = newVal; + setOffsetParams(); +} + +void ImageViewer::moveImageY(float val) { + float newVal = _centerY + val; + + if (newVal - (_visibleHeight / 2) > PSP_SCREEN_HEIGHT - 4 || newVal + (_visibleHeight / 2) < 4) + return; + _centerY = newVal; + setOffsetParams(); +} + +// Set the renderer with the proper offset on the screen +// +void ImageViewer::setOffsetParams() { + _visibleWidth = _zoomFactor * _buffer->getSourceWidth(); + _visibleHeight = _zoomFactor * _buffer->getSourceHeight(); + + int offsetX = _centerX - (int)(_visibleWidth * 0.5f); + int offsetY = _centerY - (int)(_visibleHeight * 0.5f); + + _renderer->setOffsetOnScreen(offsetX, offsetY); + setDirty(); +} + +// Handler events coming in from the inputHandler +// +void ImageViewer::handleEvent(uint32 event) { + DEBUG_ENTER_FUNC(); + + switch (event) { + case EVENT_HIDE: + setVisible(false); + break; + case EVENT_SHOW: + setVisible(true); + break; + case EVENT_ZOOM_IN: + modifyZoom(true); + break; + case EVENT_ZOOM_OUT: + modifyZoom(false); + break; + case EVENT_MOVE_LEFT: + case EVENT_MOVE_UP: + case EVENT_MOVE_RIGHT: + case EVENT_MOVE_DOWN: + case EVENT_MOVE_STOP: + _movement = (Event)event; + break; + case EVENT_NEXT_IMAGE: + loadNextImage(); + break; + case EVENT_LAST_IMAGE: + loadLastImage(); + break; + default: + PSP_ERROR("Unknown event %d\n", event); + break; + } +}
\ No newline at end of file diff --git a/backends/platform/psp/image_viewer.h b/backends/platform/psp/image_viewer.h new file mode 100644 index 0000000000..ef8b196dbe --- /dev/null +++ b/backends/platform/psp/image_viewer.h @@ -0,0 +1,105 @@ +/* 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_IMAGE_VIEWER_H +#define PSP_IMAGE_VIEWER_H + +class InputHandler; + +class ImageViewer : public DisplayClient { +public: + enum Event { + EVENT_NONE = -1, + EVENT_HIDE = 0, + EVENT_SHOW = 1, + EVENT_ZOOM_IN, + EVENT_ZOOM_OUT, + EVENT_MOVE_LEFT, + EVENT_MOVE_UP, + EVENT_MOVE_RIGHT, + EVENT_MOVE_DOWN, + EVENT_MOVE_STOP, + EVENT_NEXT_IMAGE, + EVENT_LAST_IMAGE, + }; + +private: + Buffer *_buffer; + Palette *_palette; + GuRenderer *_renderer; + bool _visible; + bool _dirty; + bool _init; + uint32 _imageNum; // current image number + float _zoomFactor; // how much we're zooming in/out on the image + float _visibleHeight, _visibleWidth; + float _centerX, _centerY; + Event _movement; + + InputHandler *_inputHandler; + DisplayManager *_displayManager; + + void setFullScreenImageParams(); + void loadNextImage(); + void loadLastImage(); + void setViewerButtons(bool active); + void setConstantRendererOptions(); + void moveImageX(float val); + void moveImageY(float val); + bool load(int imageNum); + void unload(); + void runLoop(); // to get total pausing we have to do our own loop + + void setZoom(float value); + void setOffsetParams(); + void modifyZoom(bool up); // up or down + void setVisible(bool visible); + +public: + + ImageViewer() : _buffer(0), _palette(0), _visible(false), + _dirty(false), _init(false), _imageNum(0), + _zoomFactor(0.0f), _visibleHeight(0.0f), _visibleWidth(0.0f), + _centerX(0.0f), _centerY(0.0f), _movement(EVENT_MOVE_STOP), + _inputHandler(0), _displayManager(0) {} + ~ImageViewer() { unload(); } // deallocate images + bool load(); + void render(); + bool isVisible() { return _visible; } + bool isDirty() { return _dirty; } + void setDirty() { _dirty = true; } + void setClean() { if (!_visible) // otherwise we want to keep rendering + _dirty = false; + } + void resetOnEngineDone(); + + void handleEvent(uint32 event); + + // pointer setters + void setInputHandler(InputHandler *inputHandler) { _inputHandler = inputHandler; } + void setDisplayManager(DisplayManager *displayManager) { _displayManager = displayManager; } +}; + +#endif /* PSP_IMAGE_VIEWER_H */
\ No newline at end of file diff --git a/backends/platform/psp/input.cpp b/backends/platform/psp/input.cpp index ed868ef375..0dad31e5ae 100644 --- a/backends/platform/psp/input.cpp +++ b/backends/platform/psp/input.cpp @@ -95,7 +95,7 @@ const uint32 ButtonPad::_buttonMap[] = { }; ButtonPad::ButtonPad() : _prevButtonState(0), _shifted(UNSHIFTED), _padMode(PAD_MODE_NORMAL), - _comboMode(false) { + _comboMode(false), _combosEnabled(true) { for (int i = UNSHIFTED; i < SHIFTED_MODE_LAST; i++) _buttonsChanged[i] = 0; clearButtons(); @@ -154,6 +154,7 @@ void ButtonPad::initButtonsNormalMode() { _button[BTN_START][SHIFTED].setKey(Common::KEYCODE_F5, Common::ASCII_F5); _button[BTN_START][UNSHIFTED].setKey(Common::KEYCODE_F5, Common::ASCII_F5, Common::KBD_CTRL); _button[BTN_SELECT][UNSHIFTED].setPspEvent(PSP_EVENT_SHOW_VIRTUAL_KB, true, PSP_EVENT_NONE, 0); + _button[BTN_SELECT][SHIFTED].setPspEvent(PSP_EVENT_IMAGE_VIEWER, true, PSP_EVENT_NONE, 0); } void ButtonPad::initButtonsLolMode() { @@ -199,7 +200,8 @@ bool ButtonPad::getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData & uint32 curButtonState = PSP_ALL_BUTTONS & pad.Buttons; // we only care about these - modifyButtonsForCombos(pad); // change buttons for combos + if (_combosEnabled) + modifyButtonsForCombos(pad); // change buttons for combos return getEventFromButtonState(event, pspEvent, curButtonState); } @@ -369,6 +371,7 @@ void InputHandler::init() { sceCtrlSetSamplingMode(1); // analog _buttonPad.initButtons(); + _nub.init(); } bool InputHandler::getAllInputs(Common::Event &event) { @@ -460,6 +463,12 @@ bool InputHandler::handlePspEvent(Common::Event &event, PspEvent &pspEvent) { /*case PSP_EVENT_CHANGE_SPEED: handleSpeedChange(pspEvent.data); break;*/ + case PSP_EVENT_IMAGE_VIEWER: + _imageViewer->handleEvent(pspEvent.data); + break; + case PSP_EVENT_IMAGE_VIEWER_SET_BUTTONS: + setImageViewerMode(pspEvent.data); + break; default: PSP_ERROR("Unhandled PSP Event[%d]\n", pspEvent.type); break; @@ -509,3 +518,56 @@ void InputHandler::handleSpeedChange(bool up) { GUI::TimedMessageDialog dialog(_padModeText[_padMode], 1500); dialog.runModal(); }*/ + +void InputHandler::setImageViewerMode(bool active) { + if (_buttonPad.isButtonDown() || _nub.isButtonDown()) { // can't switch yet + PSP_DEBUG_PRINT("postponing image viewer on event\n"); + _pendingPspEvent.type = PSP_EVENT_IMAGE_VIEWER_SET_BUTTONS; // queue it to be done later + _pendingPspEvent.data = active; + } else if (active) { + _nub.setDpadMode(true); + _buttonPad.enableCombos(false); // disable combos + setButtonsForImageViewer(); + } else { // deactivate + _nub.setDpadMode(false); + _nub.init(); + _buttonPad.enableCombos(true); // re-enable combos + _buttonPad.initButtons(); + } +} + +void InputHandler::setButtonsForImageViewer() { + DEBUG_ENTER_FUNC(); + + // Dpad + _buttonPad.clearButtons(); + _buttonPad.getButton(ButtonPad::BTN_UP, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_ZOOM_IN, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_DOWN, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_ZOOM_OUT, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_LEFT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_LAST_IMAGE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_RIGHT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_NEXT_IMAGE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_LTRIGGER, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_RTRIGGER, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_START, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + _buttonPad.getButton(ButtonPad::BTN_SELECT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_HIDE, + PSP_EVENT_NONE, false); + + //Nub + _nub.getPad().clearButtons(); + _nub.getPad().getButton(ButtonPad::BTN_UP, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_UP, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); + _nub.getPad().getButton(ButtonPad::BTN_DOWN, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_DOWN, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); + _nub.getPad().getButton(ButtonPad::BTN_LEFT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_LEFT, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); + _nub.getPad().getButton(ButtonPad::BTN_RIGHT, UNSHIFTED).setPspEvent(PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_RIGHT, + PSP_EVENT_IMAGE_VIEWER, ImageViewer::EVENT_MOVE_STOP); +} + + diff --git a/backends/platform/psp/input.h b/backends/platform/psp/input.h index acca04f376..9a1ab6faab 100644 --- a/backends/platform/psp/input.h +++ b/backends/platform/psp/input.h @@ -30,6 +30,7 @@ #include "common/events.h" #include "backends/platform/psp/pspkeyboard.h" #include "backends/platform/psp/cursor.h" +#include "backends/platform/psp/image_viewer.h" #include <pspctrl.h> enum PspEventType { @@ -40,10 +41,11 @@ enum PspEventType { PSP_EVENT_RBUTTON, PSP_EVENT_MODE_SWITCH, PSP_EVENT_CHANGE_SPEED, + PSP_EVENT_IMAGE_VIEWER, + PSP_EVENT_IMAGE_VIEWER_SET_BUTTONS, PSP_EVENT_LAST }; - struct PspEvent { PspEventType type; uint32 data; @@ -112,59 +114,77 @@ private: ShiftMode _shifted; PspPadMode _padMode; bool _comboMode; // are we in the middle of combos - static const uint32 _buttonMap[]; // maps the buttons to their values + bool _combosEnabled; // can we do combos + static const uint32 _buttonMap[]; // maps the buttons to their values void initButtonsNormalMode(); void initButtonsLolMode(); void modifyButtonsForCombos(SceCtrlData &pad); - void clearButtons(); public: ButtonPad(); + void initButtons(); // set the buttons to the mode that's selected + void clearButtons(); // empty the buttons of all events + bool getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); bool getEventFromButtonState(Common::Event &event, PspEvent &pspEvent, uint32 buttonState); + void setShifted(ShiftMode shifted) { _shifted = shifted; } void setPadMode(PspPadMode mode) { _padMode = mode; } bool isButtonDown() { return _prevButtonState; } - void initButtons(); + + void enableCombos(bool value) { _combosEnabled = value; } + Button &getButton(ButtonType type, ShiftMode mode) { return _button[type][mode]; } }; class Nub { private: Cursor *_cursor; // to enable changing/getting cursor position - ButtonPad _buttonPad; // private buttonpad for dpad mode ShiftMode _shifted; bool _dpadMode; - + + ButtonPad _buttonPad; // private buttonpad for dpad mode + + int32 modifyNubAxisMotion(int32 input); + void translateToDpadState(int dpadX, int dpadY, uint32 &buttonState); // convert nub data to dpad data public: - Nub() : _shifted(UNSHIFTED), _dpadMode(false) { _buttonPad.initButtons(); } + Nub() : _shifted(UNSHIFTED), _dpadMode(false) { } + void init() { _buttonPad.initButtons(); } void setCursor(Cursor *cursor) { _cursor = cursor; } + + // setters void setDpadMode(bool active) { _dpadMode = active; } void setShifted(ShiftMode shifted) { _shifted = shifted; } - bool isButtonDown(); + // getters + bool isButtonDown(); bool getEvent(Common::Event &event, PspEvent &pspEvent, SceCtrlData &pad); - int32 modifyNubAxisMotion(int32 input); - void translateToDpadState(int dpadX, int dpadY, uint32 &buttonState); // convert nub data to dpad data + ButtonPad &getPad() { return _buttonPad; } }; class InputHandler { public: - InputHandler() : _keyboard(0), _cursor(0), _padMode(PAD_MODE_NORMAL), _lastPadCheckTime(0) {} + InputHandler() : _keyboard(0), _cursor(0), _imageViewer(0), _padMode(PAD_MODE_NORMAL), + _lastPadCheckTime(0) {} + // pointer setters void setKeyboard(PSPKeyboard *keyboard) { _keyboard = keyboard; } void setCursor(Cursor *cursor) { _cursor = cursor; _nub.setCursor(cursor); } + void setImageViewer(ImageViewer *imageViewer) { _imageViewer = imageViewer; } void init(); bool getAllInputs(Common::Event &event); + void setImageViewerMode(bool active); private: + Nub _nub; + ButtonPad _buttonPad; + + // Pointers to relevant other classes PSPKeyboard *_keyboard; Cursor *_cursor; - - Nub _nub; - ButtonPad _buttonPad; + ImageViewer *_imageViewer; PspPadMode _padMode; // whice mode we're in PspEvent _pendingPspEvent; // an event that can't be handled yet @@ -176,6 +196,7 @@ private: void handleMouseEvent(Common::Event &event, Common::EventType type, const char *string); void handleShiftEvent(ShiftMode shifted); void handleModeSwitchEvent(); + void setButtonsForImageViewer(); }; #endif /* PSP_INPUT_H */ diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk index f96c4ef583..e3eac153dd 100644 --- a/backends/platform/psp/module.mk +++ b/backends/platform/psp/module.mk @@ -11,14 +11,15 @@ MODULE_OBJS := powerman.o \ input.o \ cursor.o \ trace.o \ - psploader.o \ pspkeyboard.o \ audio.o \ thread.o \ rtc.o \ mp3.o \ png_loader.o \ - tests.o + image_viewer.o \ + tests.o \ + dummy.o # We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index 047ec1957f..df330b0b00 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -76,12 +76,18 @@ void OSystem_PSP::initBackend() { _displayManager.setScreen(&_screen); _displayManager.setOverlay(&_overlay); _displayManager.setKeyboard(&_keyboard); + _displayManager.setImageViewer(&_imageViewer); _displayManager.init(); // Set pointers for input handler _inputHandler.setCursor(&_cursor); _inputHandler.setKeyboard(&_keyboard); + _inputHandler.setImageViewer(&_imageViewer); _inputHandler.init(); + + // Set pointers for image viewer + _imageViewer.setInputHandler(&_inputHandler); + _imageViewer.setDisplayManager(&_displayManager); _savefile = new PSPSaveFileManager; @@ -97,6 +103,12 @@ void OSystem_PSP::initBackend() { OSystem::initBackend(); } +// Let's us know an engine +void OSystem_PSP::engineDone() { + // for now, all we need is to reset the image number on the viewer + _imageViewer.resetOnEngineDone(); +} + bool OSystem_PSP::hasFeature(Feature f) { return (f == kFeatureOverlaySupportsAlpha || f == kFeatureCursorHasPalette); } @@ -396,6 +408,13 @@ void OSystem_PSP::quit() { sceKernelExitGame(); } +void OSystem_PSP::logMessage(LogMessageType::Type type, const char *message) { + BaseBackend::logMessage(type, message); + + if (type == LogMessageType::kError) + PspDebugTrace(false, "%s", message); // write to file +} + void OSystem_PSP::getTimeAndDate(TimeDate &td) const { time_t curTime = time(0); struct tm t = *localtime(&curTime); diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index 5721296c94..d21c7e78ef 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -32,10 +32,12 @@ #include "sound/mixer_intern.h" #include "backends/base-backend.h" #include "backends/fs/psp/psp-fs-factory.h" + #include "backends/platform/psp/display_client.h" #include "backends/platform/psp/default_display_client.h" #include "backends/platform/psp/cursor.h" #include "backends/platform/psp/pspkeyboard.h" +#include "backends/platform/psp/image_viewer.h" #include "backends/platform/psp/display_manager.h" #include "backends/platform/psp/input.h" #include "backends/platform/psp/audio.h" @@ -60,6 +62,7 @@ private: InputHandler _inputHandler; PspAudio _audio; PspTimer _pspTimer; + ImageViewer _imageViewer; public: OSystem_PSP() : _savefile(0), _mixer(0), _timer(0), _pendingUpdate(false), _pendingUpdateCounter(0) {} @@ -146,9 +149,12 @@ public: Common::SaveFileManager *getSavefileManager() { return _savefile; } FilesystemFactory *getFilesystemFactory() { return &PSPFilesystemFactory::instance(); } void getTimeAndDate(TimeDate &t) const; + virtual void engineDone(); void quit(); + void logMessage(LogMessageType::Type type, const char *message); + Common::SeekableReadStream *createConfigReadStream(); Common::WriteStream *createConfigWriteStream(); diff --git a/backends/platform/psp/png_loader.cpp b/backends/platform/psp/png_loader.cpp index 978db3eaf9..08f370f36d 100644 --- a/backends/platform/psp/png_loader.cpp +++ b/backends/platform/psp/png_loader.cpp @@ -23,32 +23,43 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "common/scummsys.h" #include "common/stream.h" #include "backends/platform/psp/psppixelformat.h" #include "backends/platform/psp/display_client.h" #include "backends/platform/psp/png_loader.h" +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ + +#include "backends/platform/psp/trace.h" + PngLoader::Status PngLoader::allocate() { + DEBUG_ENTER_FUNC(); + if (!findImageDimensions()) { PSP_ERROR("failed to get image dimensions\n"); return BAD_FILE; } - PSP_DEBUG_PRINT("width[%d], height[%d], paletteSize[%d], bitDepth[%d]\n", _width, _height, _paletteSize, _bitDepth); _buffer->setSize(_width, _height, _sizeBy); + uint32 bitsPerPixel = _bitDepth * _channels; + if (_paletteSize) { // 8 or 4-bit image - if (_paletteSize <= 16) { // 4 bit + if (bitsPerPixel == 4) { _buffer->setPixelFormat(PSPPixelFormat::Type_Palette_4bit); _palette->setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_4bit); - _paletteSize = 16; - } else if (_paletteSize <= 256) { // 8-bit image - _paletteSize = 256; + _paletteSize = 16; // round up + } else if (bitsPerPixel == 8) { // 8-bit image _buffer->setPixelFormat(PSPPixelFormat::Type_Palette_8bit); _palette->setPixelFormats(PSPPixelFormat::Type_4444, PSPPixelFormat::Type_Palette_8bit); + _paletteSize = 256; // round up } else { - PSP_ERROR("palette of %d too big!\n", _paletteSize); + PSP_ERROR("too many bits per pixel[%d] for a palette\n", bitsPerPixel); return BAD_FILE; } @@ -60,7 +71,7 @@ PngLoader::Status PngLoader::allocate() { PSP_ERROR("failed to allocate buffer\n"); return OUT_OF_MEMORY; } - if (!_palette->allocate()) { + if (_buffer->hasPalette() && !_palette->allocate()) { PSP_ERROR("failed to allocate palette\n"); return OUT_OF_MEMORY; } @@ -68,6 +79,7 @@ PngLoader::Status PngLoader::allocate() { } bool PngLoader::load() { + DEBUG_ENTER_FUNC(); // Try to load the image _file->seek(0); // Go back to start @@ -98,6 +110,7 @@ void PngLoader::libReadFunc(png_structp pngPtr, png_bytep data, png_size_t lengt } bool PngLoader::basicImageLoad() { + DEBUG_ENTER_FUNC(); _pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!_pngPtr) return false; @@ -119,7 +132,8 @@ bool PngLoader::basicImageLoad() { int interlaceType; png_get_IHDR(_pngPtr, _infoPtr, (png_uint_32 *)&_width, (png_uint_32 *)&_height, &_bitDepth, &_colorType, &interlaceType, int_p_NULL, int_p_NULL); - + _channels = png_get_channels(_pngPtr, _infoPtr); + if (_colorType & PNG_COLOR_MASK_PALETTE) _paletteSize = _infoPtr->num_palette; @@ -130,11 +144,11 @@ bool PngLoader::basicImageLoad() { bool PngLoader::findImageDimensions() { DEBUG_ENTER_FUNC(); - if (!basicImageLoad()) - return false; + bool status = basicImageLoad(); + PSP_DEBUG_PRINT("width[%d], height[%d], paletteSize[%d], bitDepth[%d], channels[%d], rowBytes[%d]\n", _width, _height, _paletteSize, _bitDepth, _channels, _infoPtr->rowbytes); png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); - return true; + return status; } // @@ -143,16 +157,16 @@ bool PngLoader::findImageDimensions() { bool PngLoader::loadImageIntoBuffer() { DEBUG_ENTER_FUNC(); - if (!basicImageLoad()) + if (!basicImageLoad()) { + png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); return false; - - // Strip off 16 bit channels. Not really needed but whatever - png_set_strip_16(_pngPtr); + } + png_set_strip_16(_pngPtr); // Strip off 16 bit channels in case they occur if (_paletteSize) { // Copy the palette png_colorp srcPal = _infoPtr->palette; - for (int i = 0; i < (int)_paletteSize; i++) { + for (int i = 0; i < _infoPtr->num_palette; i++) { unsigned char alphaVal = (i < _infoPtr->num_trans) ? _infoPtr->trans[i] : 0xFF; // Load alpha if it's there _palette->setSingleColorRGBA(i, srcPal->red, srcPal->green, srcPal->blue, alphaVal); srcPal++; @@ -163,10 +177,21 @@ bool PngLoader::loadImageIntoBuffer() { if (png_get_valid(_pngPtr, _infoPtr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(_pngPtr); // Convert trans channel to alpha for 32 bits - png_set_filler(_pngPtr, 0xff, PNG_FILLER_AFTER); // Filler for alpha? + png_set_add_alpha(_pngPtr, 0xff, PNG_FILLER_AFTER); // Filler for alpha if none exists } - unsigned char *line = (unsigned char*) malloc(_infoPtr->rowbytes); + uint32 rowBytes = png_get_rowbytes(_pngPtr, _infoPtr); + + // there seems to be a bug in libpng where it doesn't increase the rowbytes or the + // channel even after we add the alpha channel + if (_channels == 3 && (rowBytes / _width) == 3) { + _channels = 4; + rowBytes = _width * _channels; + } + + PSP_DEBUG_PRINT("rowBytes[%d], channels[%d]\n", rowBytes, _channels); + + unsigned char *line = (unsigned char*) malloc(rowBytes); if (!line) { png_destroy_read_struct(&_pngPtr, png_infopp_NULL, png_infopp_NULL); PSP_ERROR("Couldn't allocate line\n"); @@ -175,11 +200,9 @@ bool PngLoader::loadImageIntoBuffer() { for (size_t y = 0; y < _height; y++) { png_read_row(_pngPtr, line, png_bytep_NULL); - _buffer->copyFromRect(line, _infoPtr->rowbytes, 0, y, _width, 1); // Copy into buffer + _buffer->copyFromRect(line, rowBytes, 0, y, _width, 1); // Copy into buffer } - free(line); - png_read_end(_pngPtr, _infoPtr); png_destroy_read_struct(&_pngPtr, &_infoPtr, png_infopp_NULL); diff --git a/backends/platform/psp/png_loader.h b/backends/platform/psp/png_loader.h index 6b0282621a..4119bfef2b 100644 --- a/backends/platform/psp/png_loader.h +++ b/backends/platform/psp/png_loader.h @@ -44,11 +44,14 @@ private: uint32 _width; uint32 _height; uint32 _paletteSize; - int _bitDepth; Buffer::HowToSize _sizeBy; + + // PNG lib values + int _bitDepth; png_structp _pngPtr; png_infop _infoPtr; int _colorType; + uint32 _channels; public: enum Status { @@ -61,7 +64,8 @@ public: Buffer::HowToSize sizeBy = Buffer::kSizeByTextureSize) : _file(file), _buffer(&buffer), _palette(&palette), _width(0), _height(0), _paletteSize(0), - _bitDepth(0), _sizeBy(sizeBy), _pngPtr(0), _infoPtr(0), _colorType(0) {} + _bitDepth(0), _sizeBy(sizeBy), _pngPtr(0), + _infoPtr(0), _colorType(0), _channels(0) {} PngLoader::Status allocate(); bool load(); diff --git a/backends/platform/psp/powerman.cpp b/backends/platform/psp/powerman.cpp index 869d9b3023..f00a2c0fde 100644 --- a/backends/platform/psp/powerman.cpp +++ b/backends/platform/psp/powerman.cpp @@ -33,7 +33,7 @@ //#define __PSP_DEBUG_PRINT__ #include "backends/platform/psp/trace.h" -DECLARE_SINGLETON(PowerManager) +DECLARE_SINGLETON(PowerManager); // Function to debug the Power Manager (we have no output to screen) inline void PowerManager::debugPM() { diff --git a/backends/platform/psp/psp.spec b/backends/platform/psp/psp.spec index ac325b7fd6..7177413373 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 -lpspaudiocodec -lpspkernel -lpspnet_inet diff --git a/backends/platform/psp/pspkeyboard.cpp b/backends/platform/psp/pspkeyboard.cpp index 3dd5e9789b..f210726692 100644 --- a/backends/platform/psp/pspkeyboard.cpp +++ b/backends/platform/psp/pspkeyboard.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + //#define PSP_KB_SHELL /* Need a hack to properly load the keyboard from the PSP shell */ #ifdef PSP_KB_SHELL @@ -78,9 +81,9 @@ short PSPKeyboard::_modeChar[MODE_COUNT][5][6] = { }, { //numbers { K('1'), K('2'), K('3'), K('4'), K(0), K(0) }, - { C(F5), C(F8), C(F7), C(F6), C(F9), C(F10) }, + { C(F5), C(F6), C(F7), C(F8), C(F9), C(F10) }, { K('5'), K('6'), K('7'), K('8'), K(0), K(0) }, - { C(F1), C(F4), C(F3), C(F2), K(0), K(0) }, + { C(F1), C(F2), C(F3), C(F4), K(0), K(0) }, { K('\b'), K('0'), K(' '), K('9'), K(0), K(0) } }, { //symbols diff --git a/backends/platform/psp/psploader.cpp b/backends/platform/psp/psploader.cpp deleted file mode 100644 index 464e20770c..0000000000 --- a/backends/platform/psp/psploader.cpp +++ /dev/null @@ -1,732 +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$ - * - */ - -#if defined(DYNAMIC_MODULES) && defined(__PSP__) - -#include <string.h> -#include <stdarg.h> -#include <stdio.h> -#include <malloc.h> -#include <unistd.h> -#include <sys/_default_fcntl.h> - -#include <psputils.h> - -#include "backends/platform/psp/psploader.h" -#include "backends/platform/psp/powerman.h" - -//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ -//#define __PSP_DEBUG_PRINT__ - -#include "backends/platform/psp/trace.h" - -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() { - DEBUG_ENTER_FUNC(); - free(_symtab); - free(_strtab); - _symtab = NULL; - _strtab = NULL; - _symbol_cnt = 0; -} - -// Unload all objects from memory -void DLObject::unload() { - DEBUG_ENTER_FUNC(); - 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) { - DEBUG_ENTER_FUNC(); - Elf32_Rel *rel = NULL; // relocation entry - - // Allocate memory for relocation table - if (!(rel = (Elf32_Rel *)malloc(size))) { - PSP_ERROR("Out of memory."); - return false; - } - - // Read in our relocation table - if (lseek(fd, offset, SEEK_SET) < 0 || - read(fd, rel, size) != (ssize_t)size) { - PSP_ERROR("Relocation table load failed."); - free(rel); - return false; - } - - // Treat each relocation entry. Loop over all of them - int cnt = size / sizeof(*rel); - - PSP_DEBUG_PRINT("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); - - PSP_DEBUG_DO(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 - PSP_DEBUG_PRINT("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 - PSP_ERROR("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) - PSP_DEBUG_PRINT("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) - PSP_DEBUG_PRINT("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) - PSP_DEBUG_PRINT("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) - PSP_DEBUG_PRINT("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) - PSP_DEBUG_PRINT("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) - PSP_DEBUG_PRINT("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target); - } - break; - - default: - PSP_ERROR("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i); - free(rel); - return false; - } - } - - PSP_DEBUG_PRINT("Done with relocation. extendedHi16=%d\n\n", extendedHi16); - - free(rel); - return true; -} - -bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) { - DEBUG_ENTER_FUNC(); - // 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 - PSP_ERROR("Invalid file type."); - return false; - } - - PSP_DEBUG_PRINT("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) { - DEBUG_ENTER_FUNC(); - // Read program header - if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 || - read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) { - PSP_ERROR("Program header load failed."); - return false; - } - - // Check program header values - if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) { - PSP_ERROR("Invalid program header."); - return false; - } - - PSP_DEBUG_PRINT("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) { - DEBUG_ENTER_FUNC(); - - 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 - PSP_DEBUG_PRINT("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))) { - PSP_ERROR("Out of memory.\n"); - return false; - } - PSP_DEBUG_PRINT("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(); - PSP_DEBUG_PRINT("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) { - PSP_DEBUG_PRINT("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) { - PSP_ERROR("Segment load failed."); - return false; - } - - return true; -} - - -Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { - DEBUG_ENTER_FUNC(); - - Elf32_Shdr *shdr = NULL; - - // Allocate memory for section headers - if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) { - PSP_ERROR("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))) { - PSP_ERROR("Section headers load failed."); - return NULL; - } - - return shdr; -} - -int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { - DEBUG_ENTER_FUNC(); - - // Loop over sections, looking for symbol table linked to a string table - for (int i = 0; i < ehdr->e_shnum; i++) { - PSP_DEBUG_PRINT("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) { - PSP_ERROR("No symbol table."); - return -1; - } - - PSP_DEBUG_PRINT("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))) { - PSP_ERROR("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) { - PSP_ERROR("Symbol table load failed."); - return -1; - } - - // Set number of symbols - _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym); - PSP_DEBUG_PRINT("Loaded %d symbols.\n", _symbol_cnt); - - return _symtab_sect; - -} - -bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) { - DEBUG_ENTER_FUNC(); - - int string_sect = shdr[_symtab_sect].sh_link; - - // Allocate memory for string table - if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) { - PSP_ERROR("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) { - PSP_ERROR("Symbol table strings load failed."); - return false; - } - return true; -} - -void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) { - DEBUG_ENTER_FUNC(); - - int shortsCount = 0, othersCount = 0; - PSP_DEBUG_PRINT("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) - PSP_ERROR("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)) - PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value); - } - - } - - } - - PSP_DEBUG_PRINT("Relocated %d short symbols, %d others.\n", shortsCount, othersCount); -} - -bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { - DEBUG_ENTER_FUNC(); - - // 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) { - DEBUG_ENTER_FUNC(); - - 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 - PSP_DEBUG_PRINT("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) { - DEBUG_ENTER_FUNC(); - int fd; - void *ctors_start, *ctors_end; - - PSP_DEBUG_PRINT("open(\"%s\")\n", path); - - // Get the address of the global pointer - _gpVal = (unsigned int) & _gp; - PSP_DEBUG_PRINT("_gpVal is %x\n", _gpVal); - - PowerMan.beginCriticalSection(); - - if ((fd = ::open(path, O_RDONLY)) < 0) { - PSP_ERROR("%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) { - PSP_ERROR("Missing ctors/dtors."); - _dtors_start = _dtors_end = NULL; - unload(); - return false; - } - - PSP_DEBUG_PRINT("Calling constructors.\n"); - for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++) - (**f)(); - - PSP_DEBUG_PRINT("%s opened ok.\n", path); - return true; -} - -bool DLObject::close() { - DEBUG_ENTER_FUNC(); - 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) { - DEBUG_ENTER_FUNC(); - PSP_DEBUG_PRINT("symbol(\"%s\")\n", name); - - if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) { - PSP_ERROR("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 - PSP_DEBUG_PRINT("=> %p\n", (void*)s->st_value); - return (void*)s->st_value; - } - } - - PSP_ERROR("Symbol \"%s\" not found.", name); - return NULL; -} - - - -ShortSegmentManager::ShortSegmentManager() { - DEBUG_ENTER_FUNC(); - _shortsStart = &__plugin_hole_start ; - _shortsEnd = &__plugin_hole_end; -} - -ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) { - DEBUG_ENTER_FUNC(); - 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) { - PSP_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); - - PSP_DEBUG_PRINT("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) { - DEBUG_ENTER_FUNC(); - PSP_DEBUG_PRINT("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 && __PSP__ */ diff --git a/backends/platform/psp/psploader.h b/backends/platform/psp/psploader.h deleted file mode 100644 index 13dcf6ef98..0000000000 --- a/backends/platform/psp/psploader.h +++ /dev/null @@ -1,137 +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 PSPLOADER_H -#define PSPLOADER_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 /* PSPLOADER_H */ diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp index f26e5770a6..976a5aa3ec 100644 --- a/backends/platform/psp/rtc.cpp +++ b/backends/platform/psp/rtc.cpp @@ -37,7 +37,7 @@ // Class PspRtc --------------------------------------------------------------- -DECLARE_SINGLETON(PspRtc) +DECLARE_SINGLETON(PspRtc); void PspRtc::init() { // init our starting ticks uint32 ticks[2]; diff --git a/backends/platform/psp/trace.cpp b/backends/platform/psp/trace.cpp index 7bac6534da..74c2f64300 100644 --- a/backends/platform/psp/trace.cpp +++ b/backends/platform/psp/trace.cpp @@ -28,6 +28,8 @@ #include <pspdebug.h> #include <stdarg.h> #include <stdio.h> +#define FORBIDDEN_SYMBOL_ALLOW_ALL +#include "common/scummsys.h" int psp_debug_indent = 0; bool firstWriteToFile = true; @@ -58,3 +60,82 @@ void PspDebugTrace(bool alsoToScreen, const char *format, ...) { if (alsoToScreen) fprintf(stderr, buffer); } + +// Assembly functions to get the Return Address register and the Stack pointer register +#define GET_RET(retAddr) \ + asm volatile ("move %0,$ra\n\t" \ + : "=&r" (retAddr) : ) + +#define GET_SP(stackPtr) \ + asm volatile ("move %0,$sp\n\t" \ + : "=&r" (stackPtr) : ) + +// Function to retrieve a backtrace for the MIPS processor +// This is not trivial since the MIPS doesn't use a frame pointer. +// Takes the number of levels wanted above the calling function (included) and an array of void * +// +void mipsBacktrace(uint32 levels, void **addresses) { + // get the current return address + register byte *retAddr; + register byte *stackPointer; + GET_RET(retAddr); + GET_SP(stackPointer); + char string[100]; + + if (!levels) + return; + + memset(addresses, 0, sizeof(void *) * levels); + + uint32 curLevel = 0; + + const uint32 SP_SUBTRACT = 0x27bd8000; // The instruction to subtract from the SP looks like this + const uint32 SP_SUB_HIGH_MASK = 0xffff8000; // The mask to check for the subtract SP instruction + const uint32 SP_SUB_LOW_MASK = 0x0000ffff; // The mask that gives us how much was subtracted + + // make sure we go out of the stack of this current level + // we already have the return address for this level from the register + if (curLevel < levels) { + void *thisFunc = (void *)mipsBacktrace; + for (uint32 *seekPtr = (uint32 *)thisFunc; ; seekPtr++) { + if ((*seekPtr & SP_SUB_HIGH_MASK) == SP_SUBTRACT) { + // we found the $sp subtraction at the beginning of the function + int16 subAmount = (int16)((*seekPtr) & SP_SUB_LOW_MASK); + //sprintf(string, "found local $sp sub at %p. Data[%x]. Sub amount %d\n", seekPtr, *seekPtr, subAmount); + //fputs(string, stderr); + stackPointer -= subAmount; + byte *testRetAddr = (byte *)*((uint32 *)(stackPointer - 4)); + if (testRetAddr != retAddr) { + sprintf(string, "mismatch in testretAddr.\n"); + fputs(string, stderr); + } + break; + } + } + } + + // keep scanning while more levels are requested + while (curLevel < levels) { + // now scan backwards from the return address to find the size of the stack + for(uint32 *seekPtr = (uint32 *)retAddr; ; seekPtr--) { + if (((*seekPtr) & SP_SUB_HIGH_MASK) == SP_SUBTRACT) { + // we found the $sp subtraction at the beginning of the function + int16 subAmount = (int16)((*seekPtr) & SP_SUB_LOW_MASK); + //sprintf(string, "found $sp sub at %p. Data[%x]. Sub amount %d\n", seekPtr, *seekPtr, subAmount); + //fputs(string, stderr); + stackPointer -= subAmount; + retAddr = (byte *)*((uint32 *)(stackPointer - 4)); + if (retAddr < (byte *)0x8900000 || retAddr > (byte *)0xC900000) { + sprintf(string, "invalid retAddr %p\n", retAddr); + fputs(string, stderr); + return; + } + //sprintf(string, "retAddr[%p]\n", retAddr); + //fputs(string, stderr); + addresses[curLevel++] = retAddr; + break; + } + } + } +} + diff --git a/backends/platform/psp/trace.h b/backends/platform/psp/trace.h index 625aa60772..39b335b16c 100644 --- a/backends/platform/psp/trace.h +++ b/backends/platform/psp/trace.h @@ -55,6 +55,7 @@ __PSP_PRINT__(format, ## __VA_ARGS__); } void PspDebugTrace(bool alsoToScreen, const char *format, ...); +void mipsBacktrace(uint32 levels, void **addresses); extern int psp_debug_indent; diff --git a/backends/platform/samsungtv/main.cpp b/backends/platform/samsungtv/main.cpp index f3d868641b..3beb97165f 100644 --- a/backends/platform/samsungtv/main.cpp +++ b/backends/platform/samsungtv/main.cpp @@ -49,7 +49,7 @@ extern "C" int Game_Main(char *path, char *) { int res = scummvm_main(0, 0); // Free OSystem - delete (OSystem_SDL_SamsungTV *)g_system; + delete g_system; return res; } diff --git a/backends/platform/samsungtv/samsungtv.cpp b/backends/platform/samsungtv/samsungtv.cpp index 1e316aa840..b007d1d594 100644 --- a/backends/platform/samsungtv/samsungtv.cpp +++ b/backends/platform/samsungtv/samsungtv.cpp @@ -26,6 +26,8 @@ #include "backends/platform/samsungtv/samsungtv.h" #include "backends/events/samsungtvsdl/samsungtvsdl-events.h" +#if defined(SAMSUNGTV) + OSystem_SDL_SamsungTV::OSystem_SDL_SamsungTV() : OSystem_POSIX("/dtv/usb/sda1/.scummvmrc") { @@ -65,6 +67,14 @@ bool OSystem_SDL_SamsungTV::getFeatureState(Feature f) { } } +void OSystem_SDL_SamsungTV::fatalError() { + // FIXME + for (;;) {} +} + void OSystem_SDL_SamsungTV::quit() { + // FIXME deinit(); } + +#endif diff --git a/backends/platform/samsungtv/samsungtv.h b/backends/platform/samsungtv/samsungtv.h index 49460a9ddc..c5c8a4f65a 100644 --- a/backends/platform/samsungtv/samsungtv.h +++ b/backends/platform/samsungtv/samsungtv.h @@ -38,6 +38,7 @@ public: virtual void setFeatureState(Feature f, bool enable); virtual bool getFeatureState(Feature f); + virtual void fatalError(); virtual void quit(); }; diff --git a/backends/platform/sdl/macosx/macosx.cpp b/backends/platform/sdl/macosx/macosx.cpp index a36769b417..814badbca4 100644 --- a/backends/platform/sdl/macosx/macosx.cpp +++ b/backends/platform/sdl/macosx/macosx.cpp @@ -25,6 +25,9 @@ #ifdef MACOSX +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/sdl/macosx/macosx.h" #include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h" diff --git a/backends/platform/sdl/main.cpp b/backends/platform/sdl/main.cpp index 00ec0b8185..14cfaaee57 100644 --- a/backends/platform/sdl/main.cpp +++ b/backends/platform/sdl/main.cpp @@ -23,9 +23,20 @@ * */ +#include "common/scummsys.h" + // Several SDL based ports use a custom main, and hence do not want to compile // of this file. The following "#if" ensures that. -#if !defined(UNIX) && !defined(WIN32) && !defined(__MAEMO__) && !defined(__SYMBIAN32__) && !defined(__amigaos4__) && !defined(DINGUX) && !defined(CAANOO) && !defined(OPENPANDORA) +#if !defined(UNIX) && \ + !defined(WIN32) && \ + !defined(__MAEMO__) && \ + !defined(__SYMBIAN32__) && \ + !defined(_WIN32_WCE) && \ + !defined(__amigaos4__) && \ + !defined(DINGUX) && \ + !defined(CAANOO) && \ + !defined(LINUXMOTO) && \ + !defined(OPENPANDORA) #include "backends/platform/sdl/sdl.h" #include "backends/plugins/sdl/sdl-provider.h" diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk index b00bb64718..c7ee32db16 100644 --- a/backends/platform/sdl/module.mk +++ b/backends/platform/sdl/module.mk @@ -25,7 +25,7 @@ MODULE_OBJS += \ amigaos/amigaos.o endif -# We don't use the rules.mk here on purpose +# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS. MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) OBJS := $(MODULE_OBJS) $(OBJS) -MODULE_DIRS += $(sort $(dir $(MODULE_OBJS)))
\ No newline at end of file +MODULE_DIRS += $(sort $(dir $(MODULE_OBJS))) diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index fbfb83fa1d..307cf39a97 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/sdl/sdl.h" #include "common/config-manager.h" #include "common/EventRecorder.h" @@ -39,7 +42,13 @@ #include "icons/scummvm.xpm" -#include <time.h> +#include <time.h> // for getTimeAndDate() + +#ifdef USE_DETECTLANG +#ifndef WIN32 +#include <locale.h> +#endif // !WIN32 +#endif OSystem_SDL::OSystem_SDL() : @@ -51,6 +60,7 @@ OSystem_SDL::OSystem_SDL() #endif _inited(false), _initedSDL(false), + _logger(0), _mixerManager(0), _eventSource(0) { @@ -64,6 +74,16 @@ void OSystem_SDL::init() { // Initialize SDL initSDL(); + if (!_logger) + _logger = new Backends::Log::Log(this); + + if (_logger) { + Common::WriteStream *logFile = createLogFile(); + if (logFile) + _logger->open(logFile); + } + + // Creates the early needed managers, if they don't exist yet // (we check for this to allow subclasses to provide their own). if (_mutexManager == 0) @@ -168,6 +188,36 @@ void OSystem_SDL::initSDL() { } } +void OSystem_SDL::deinit() { + SDL_ShowCursor(SDL_ENABLE); + + delete _savefileManager; + _savefileManager = 0; + delete _graphicsManager; + _graphicsManager = 0; + delete _eventManager; + _eventManager = 0; + delete _eventSource; + _eventSource = 0; + delete _audiocdManager; + _audiocdManager = 0; + delete _mixerManager; + _mixerManager = 0; + delete _timerManager; + _timerManager = 0; + delete _mutexManager; + _mutexManager = 0; + +#ifdef USE_OPENGL + delete[] _graphicsModes; +#endif + + delete _logger; + _logger = 0; + + SDL_Quit(); +} + void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) { #ifdef DATA_PATH @@ -195,6 +245,94 @@ Common::WriteStream *OSystem_SDL::createConfigWriteStream() { return file.createWriteStream(); } +#define DEFAULT_LOG_FILE "scummvm.log" + +Common::WriteStream *OSystem_SDL::createLogFile() { +#if defined(MACOSX) + return 0; +#elif defined(UNIX) + const char *home = getenv("HOME"); + if (home == NULL) + return 0; + + Common::String logFile(home); + logFile += "/.scummvm"; + + struct stat sb; + + // Check whether the dir exists + if (stat(logFile.c_str(), &sb) == -1) { + // The dir does not exist, or stat failed for some other reason. + if (errno != ENOENT) + return 0; + + // If the problem was that the path pointed to nothing, try + // to create the dir. + if (mkdir(logFile.c_str(), 0755) != 0) + return 0; + } else if (!S_ISDIR(sb.st_mode)) { + // Path is no directory. Oops + return 0; + } + + logFile += "/logs"; + + // Check whether the dir exists + if (stat(logFile.c_str(), &sb) == -1) { + // The dir does not exist, or stat failed for some other reason. + if (errno != ENOENT) + return 0; + + // If the problem was that the path pointed to nothing, try + // to create the dir. + if (mkdir(logFile.c_str(), 0755) != 0) + return 0; + } else if (!S_ISDIR(sb.st_mode)) { + // Path is no directory. Oops + return 0; + } + + logFile += "/" DEFAULT_LOG_FILE; + + Common::FSNode file(logFile); + return file.createWriteStream(); +#elif defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) + char logFile[MAXPATHLEN]; + + OSVERSIONINFO win32OsVersion; + ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO)); + win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&win32OsVersion); + // Check for non-9X version of Windows. + if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) { + // Use the Application Data directory of the user profile. + if (win32OsVersion.dwMajorVersion >= 5) { + if (!GetEnvironmentVariable("APPDATA", logFile, sizeof(logFile))) + error("Unable to access application data directory"); + } else { + if (!GetEnvironmentVariable("USERPROFILE", logFile, sizeof(logFile))) + error("Unable to access user profile directory"); + + strcat(logFile, "\\Application Data"); + CreateDirectory(logFile, NULL); + } + + strcat(logFile, "\\ScummVM"); + CreateDirectory(logFile, NULL); + strcat(logFile, "\\Logs"); + CreateDirectory(logFile, NULL); + strcat(logFile, "\\" DEFAULT_LOG_FILE); + + Common::FSNode file(logFile); + return file.createWriteStream(); + } else { + return 0; + } +#else + return 0; +#endif +} + void OSystem_SDL::setWindowCaption(const char *caption) { Common::String cap; byte c; @@ -213,36 +351,96 @@ void OSystem_SDL::setWindowCaption(const char *caption) { SDL_WM_SetCaption(cap.c_str(), cap.c_str()); } -void OSystem_SDL::deinit() { - SDL_ShowCursor(SDL_ENABLE); - - delete _savefileManager; - _savefileManager = 0; - delete _graphicsManager; - _graphicsManager = 0; - delete _eventManager; - _eventManager = 0; - delete _eventSource; - _eventSource = 0; - delete _audiocdManager; - _audiocdManager = 0; - delete _mixerManager; - _mixerManager = 0; - delete _timerManager; - _timerManager = 0; - delete _mutexManager; - _mutexManager = 0; +void OSystem_SDL::quit() { + deinit(); + exit(0); +} -#ifdef USE_OPENGL - delete[] _graphicsModes; +void OSystem_SDL::logMessage(LogMessageType::Type type, const char *message) { + ModularBackend::logMessage(type, message); + if (_logger) + _logger->print(message); + +#if defined( USE_WINDBG ) +#if defined( _WIN32_WCE ) + TCHAR buf_unicode[1024]; + MultiByteToWideChar(CP_ACP, 0, message, strlen(message) + 1, buf_unicode, sizeof(buf_unicode)); + OutputDebugString(buf_unicode); + + if (type == LogMessageType::kError) { +#ifndef DEBUG + drawError(message); +#else + int cmon_break_into_the_debugger_if_you_please = *(int *)(message + 1); // bus error + printf("%d", cmon_break_into_the_debugger_if_you_please); // don't optimize the int out #endif + } - SDL_Quit(); +#else + OutputDebugString(message); +#endif +#endif } -void OSystem_SDL::quit() { - deinit(); - exit(0); +Common::String OSystem_SDL::getSystemLanguage() const { +#ifdef USE_DETECTLANG +#ifdef WIN32 + // We can not use "setlocale" (at least not for MSVC builds), since it + // will return locales like: "English_USA.1252", thus we need a special + // way to determine the locale string for Win32. + char langName[9]; + char ctryName[9]; + + const LCID languageIdentifier = GetThreadLocale(); + + // GetLocalInfo is only supported starting from Windows 2000, according to this: + // http://msdn.microsoft.com/en-us/library/dd318101%28VS.85%29.aspx + // On the other hand the locale constants used, seem to exist on Windows 98 too, + // check this for that: http://msdn.microsoft.com/en-us/library/dd464799%28v=VS.85%29.aspx + // + // I am not exactly sure what is the truth now, it might be very well that this breaks + // support for systems older than Windows 2000.... + // + // TODO: Check whether this (or ScummVM at all ;-) works on a system with Windows 98 for + // example and if it does not and we still want Windows 9x support, we should definitly + // think of another solution. + if (GetLocaleInfo(languageIdentifier, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 && + GetLocaleInfo(languageIdentifier, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) { + Common::String localeName = langName; + localeName += "_"; + localeName += ctryName; + + return localeName; + } else { + return BaseBackend::getSystemLanguage(); + } +#else // WIN32 + // Activating current locale settings + const char *locale = setlocale(LC_ALL, ""); + + // Detect the language from the locale + if (!locale) { + return BaseBackend::getSystemLanguage(); + } else { + int length = 0; + + // Strip out additional information, like + // ".UTF-8" or the like. We do this, since + // our translation languages are usually + // specified without any charset information. + for (int i = 0; locale[i]; ++i, ++length) { + // TODO: Check whether "@" should really be checked + // here. + if (locale[i] == '.' || locale[i] == ' ' || locale[i] == '@') + break; + } + + return Common::String(locale, length); + } +#endif // WIN32 +#else // USE_DETECTLANG + return BaseBackend::getSystemLanguage(); +#endif // USE_DETECTLANG } void OSystem_SDL::setupIcon() { diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 5b1ce8f803..9a69bed691 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -35,6 +35,7 @@ #include "backends/modular-backend.h" #include "backends/mixer/sdl/sdl-mixer.h" #include "backends/events/sdl/sdl-events.h" +#include "backends/log/log.h" /** * Base OSystem class for all SDL ports. @@ -63,6 +64,12 @@ public: virtual Common::HardwareKeySet *getHardwareKeySet(); virtual void quit(); virtual void deinit(); + + // Logging + virtual void logMessage(LogMessageType::Type type, const char *message); + + virtual Common::String getSystemLanguage() const; + virtual void setWindowCaption(const char *caption); virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0); virtual Common::SeekableReadStream *createConfigReadStream(); @@ -109,6 +116,10 @@ protected: */ virtual Common::String getDefaultConfigFileName(); + // Logging + virtual Common::WriteStream *createLogFile(); + Backends::Log::Log *_logger; + #ifdef USE_OPENGL OSystem::GraphicsMode *_graphicsModes; int _graphicsMode; diff --git a/backends/platform/sdl/win32/win32.cpp b/backends/platform/sdl/win32/win32.cpp index 05005dee6f..68047fdde1 100644 --- a/backends/platform/sdl/win32/win32.cpp +++ b/backends/platform/sdl/win32/win32.cpp @@ -34,7 +34,46 @@ #define DEFAULT_CONFIG_FILE "scummvm.ini" +//#define HIDE_CONSOLE + +#ifdef HIDE_CONSOLE +struct SdlConsoleHidingWin32 { + DWORD myPid; + DWORD myTid; + HWND consoleHandle; +}; + +// console hiding for win32 +static BOOL CALLBACK initBackendFindConsoleWin32Proc(HWND hWnd, LPARAM lParam) { + DWORD pid, tid; + SdlConsoleHidingWin32 *variables = (SdlConsoleHidingWin32 *)lParam; + tid = GetWindowThreadProcessId(hWnd, &pid); + if ((tid == variables->myTid) && (pid == variables->myPid)) { + variables->consoleHandle = hWnd; + return FALSE; + } + return TRUE; +} + +#endif + void OSystem_Win32::init() { +#ifdef HIDE_CONSOLE + // console hiding for win32 + SdlConsoleHidingWin32 consoleHidingWin32; + consoleHidingWin32.consoleHandle = 0; + consoleHidingWin32.myPid = GetCurrentProcessId(); + consoleHidingWin32.myTid = GetCurrentThreadId(); + EnumWindows (initBackendFindConsoleWin32Proc, (LPARAM)&consoleHidingWin32); + + if (!ConfMan.getBool("show_console")) { + if (consoleHidingWin32.consoleHandle) { + // We won't find a window with our TID/PID in case we were started from command-line + ShowWindow(consoleHidingWin32.consoleHandle, SW_HIDE); + } + } +#endif + // Initialze File System Factory _fsFactory = new WindowsFilesystemFactory(); diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl index 8e97f469f9..8786ecff32 100644 --- a/backends/platform/symbian/AdaptAllMMPs.pl +++ b/backends/platform/symbian/AdaptAllMMPs.pl @@ -34,6 +34,7 @@ chdir("../../../"); "mmp/scummvm_teenagent.mmp", "mmp/scummvm_mohawk.mmp", "mmp/scummvm_hugo.mmp", + "mmp/scummvm_toon.mmp", # Target Platform Project Files "S60/ScummVM_S60.mmp", "S60v3/ScummVM_S60v3.mmp", @@ -92,6 +93,9 @@ my @excludes_graphics = ( "iff.cpp" ); +my @excludes_gui = ( +); + # the USE_ARM_* defines not parsed correctly, exclude manually: my @excludes_scumm = ( ".*ARM.*", # the *ARM.s files are added in .mpp files based on WINS/ARM build! @@ -104,7 +108,7 @@ my @excludes_scumm = ( #arseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray]) ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, these never change anyways... ParseModule("_base", "common", \@section_empty); -ParseModule("_base", "gui", \@section_empty); +ParseModule("_base", "gui", \@section_empty, \@excludes_gui); ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics); ParseModule("_base", "sound", \@section_empty, \@excludes_snd); @@ -135,6 +139,7 @@ ParseModule("_draci", "draci", \@section_empty); ParseModule("_teenagent","teenagent", \@section_empty); ParseModule("_mohawk" ,"mohawk", \@section_empty); ParseModule("_hugo" ,"hugo", \@section_empty); +ParseModule("_toon" ,"toon", \@section_empty); print " ======================================================================================= Done. Enjoy :P diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl index a0ec338ca0..bf80c36a0e 100644 --- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl +++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl @@ -4,7 +4,7 @@ @WorkingEngines = qw( scumm agos sky queen gob groovie saga drascula kyra lure agi touche parallaction cine - cruise made m4 tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo + cruise made m4 tinsel tucker sword1 sword2 draci sci teenagent mohawk hugo toon ); @WorkingEngines_1st = qw( @@ -16,7 +16,7 @@ @WorkingEngines_2nd = qw( agos sky gob kyra lure agi tinsel - sword1 sword2 draci sci teenagent hugo + sword1 sword2 draci sci teenagent hugo toon ); @TestingEngines = qw( @@ -302,8 +302,8 @@ # the first one includes all SDKs & release-ready engines $VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines"; - $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines"; - $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines"; +# $VariationSets{'ALL'}{'1St'} = "$DefaultFeatures @WorkingEngines_1st @EnablableSubEngines"; +# $VariationSets{'ALL'}{'2nd'} = "$DefaultFeatures @WorkingEngines_2nd @EnablableSubEngines"; # now one for each ready-for-release engine if (0) { diff --git a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in index 12193a8781..0abd2d48c8 100644 --- a/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_A0000658_S60v3.mmp.in @@ -117,6 +117,8 @@ SOURCEPATH ..\..\..\.. // backend EPOC/SDL/ESDL specific includes SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp +SOURCE backends\audiocd\sdl\sdl-audiocd.cpp +SOURCE backends\audiocd\default\default-audiocd.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp @@ -143,3 +145,4 @@ LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib library avkon.lib bafl.lib CAPABILITY LocalServices ReadUserData +MACRO SDL_BACKEND diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in index 31c98b90f1..44b8d34feb 100644 --- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in @@ -117,6 +117,8 @@ SOURCEPATH ..\..\..\.. // backend EPOC/SDL/ESDL specific includes SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp +SOURCE backends\audiocd\sdl\sdl-audiocd.cpp +SOURCE backends\audiocd\default\default-audiocd.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp @@ -143,3 +145,4 @@ LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib library avkon.lib bafl.lib CAPABILITY LocalServices ReadUserData +MACRO SDL_BACKEND diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg index 3f0fbbc5f1..a5457fca0e 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg @@ -36,7 +36,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM S60v3"},(0xA0000657),1,13,0 +#{"ScummVM S60v3"},(0xA0000657),1,30,0 ;Supports Series 60 v 3.0 [0x101F7961], 0, 0, 0, {"Series60ProductID"} diff --git a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in index 2e50c12cc3..6e3e612925 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_A0000658_UIQ3.mmp.in @@ -36,6 +36,7 @@ TARGET ScummVM_A0000658.exe TARGETPATH sys\bin TARGETTYPE exe + OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char UID 0x100039ce 0xA0000658 @@ -113,8 +114,9 @@ SOURCEPATH ..\..\..\.. // backend EPOC/SDL/ESDL specific includes SOURCE backends\platform\sdl\hardwarekeys.cpp -SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp +SOURCE backends\audiocd\sdl\sdl-audiocd.cpp +SOURCE backends\audiocd\default\default-audiocd.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp @@ -140,3 +142,4 @@ LIBRARY gdi.lib hal.lib bitgdi.lib LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib LIBRARY qikctl.lib library qikcore.lib bafl.lib eikcoctl.lib +MACRO SDL_BACKEND diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in index b00c848667..dd8fc7effe 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in @@ -114,8 +114,9 @@ SOURCEPATH ..\..\..\.. // backend EPOC/SDL/ESDL specific includes SOURCE backends\platform\sdl\hardwarekeys.cpp -SOURCE backends\platform\sdl\hardwarekeys.cpp SOURCE backends\platform\sdl\sdl.cpp +SOURCE backends\audiocd\sdl\sdl-audiocd.cpp +SOURCE backends\audiocd\default\default-audiocd.cpp SOURCE backends\fs\symbian\symbian-fs-factory.cpp SOURCE backends\platform\symbian\src\SymbianOS.cpp SOURCE backends\platform\symbian\src\SymbianActions.cpp @@ -141,3 +142,4 @@ LIBRARY gdi.lib hal.lib bitgdi.lib LIBRARY mediaclientaudiostream.lib efsrv.lib ws32.lib LIBRARY qikctl.lib library qikcore.lib bafl.lib eikcoctl.lib +MACRO SDL_BACKEND diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg index a55f4b6e37..4323c4e5ac 100644 --- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg +++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg @@ -35,7 +35,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM UIQ3"},(0xA0000657),1,13,0 +#{"ScummVM UIQ3"},(0xA0000657),1,30,0 ; ProductID for UIQ 3.0 ; Product/platform version UID, Major, Minor, Build, Product ID diff --git a/backends/platform/symbian/mmp/scummvm_toon.mmp.in b/backends/platform/symbian/mmp/scummvm_toon.mmp.in new file mode 100644 index 0000000000..7b907fd92f --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_toon.mmp.in @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL + * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System + * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer + * Copyright (C) 2005-2010 The ScummVM project + * + * 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$ + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_toon.lib +TARGETTYPE lib +OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp +OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings +OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char +ALWAYS_BUILD_AS_ARM + +//START_AUTO_MACROS_SLAVE// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_MACROS_SLAVE// + +// *** SOURCE files + +SOURCEPATH ..\..\..\..\engines\toon + +//START_AUTO_OBJECTS_TOON_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_TOON_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +SYSTEMINCLUDE \epoc32\include\ZLIB // before \epoc32\include because symbian already has older version +SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/src/Symbianmain.cpp b/backends/platform/symbian/src/SymbianMain.cpp index 4aaa05926f..9e300a3068 100644 --- a/backends/platform/symbian/src/Symbianmain.cpp +++ b/backends/platform/symbian/src/SymbianMain.cpp @@ -18,8 +18,8 @@ * 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$ + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2010-opengl/backends/platform/symbian/src/Symbianmain.cpp $ + * $Id: Symbianmain.cpp 51588 2010-08-01 19:51:23Z anotherguest $ * */ @@ -96,4 +96,3 @@ int main(int argc, char *argv[]) { return res; } - diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index d86adbf354..faced0c2c4 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -22,14 +22,18 @@ * $Id$ */ -#include <eikenv.h> // for CEikonEnv::Static() @ Symbian::FatalError() #include <sdlapp.h> // for CSDLApp::GetExecutablePathCStr() @ Symbian::GetExecutablePath() #include <bautils.h> +#include <eikenv.h> // for CEikonEnv::Static() +#define FORBIDDEN_SYMBOL_EXCEPTION_fclose +#define FORBIDDEN_SYMBOL_EXCEPTION_fopen #include "backends/platform/symbian/src/SymbianOS.h" #include "backends/platform/symbian/src/SymbianActions.h" #include "common/config-manager.h" #include "common/scummsys.h" +#include "common/translation.h" + #include "gui/message.h" #include "backends/fs/symbian/symbian-fs-factory.h" @@ -44,18 +48,6 @@ ////////// extern "C" /////////////////////////////////////////////////// namespace Symbian { -// Show a simple Symbian Info win with Msg & exit -void FatalError(const char *msg) { - TPtrC8 msgPtr((const TUint8 *)msg); - TBuf<512> msg16Bit; - msg16Bit.Copy(msgPtr); -#ifndef S60 - CEikonEnv::Static()->InfoWinL(_L("ScummVM Fatal Error"), msg16Bit); -#endif - if (g_system) - g_system->quit(); -} - // make this easily available everywhere char *GetExecutablePath() { return CSDLApp::GetExecutablePathCStr(); @@ -168,6 +160,7 @@ void OSystem_SDL_Symbian::checkMappings() { GUI::Actions::Instance()->initInstanceGame(); } +// make sure we always go to normal, even if the string might be set wrong! bool OSystem_SDL_Symbian::setGraphicsMode(const char * /*name*/) { return _graphicsManager->setGraphicsMode(0); } diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h index 2a26771a0a..c45bac4933 100644 --- a/backends/platform/symbian/src/portdefs.h +++ b/backends/platform/symbian/src/portdefs.h @@ -44,10 +44,6 @@ // hack in some tricks to work around not having these fcns for Symbian // and we _really_ don't wanna link with any other windows LIBC library! #if defined(__GCC32__) - - #define snprintf(buf,len,args...) sprintf(buf,args) - #define vsnprintf(buf,len,format,valist) vsprintf(buf,format,valist) - // taken from public domain http://www.opensource.apple.com/darwinsource/WWDC2004/gcc_legacy-939/gcc/floatlib.c #define SIGNBIT 0x80000000 #define HIDDEN (1 << 23) @@ -134,10 +130,10 @@ // Symbian bsearch implementation is flawed void *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); #define bsearch scumm_bsearch +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE // we cannot include SymbianOS.h everywhere, but this works too (functions code is in SymbianOS.cpp) namespace Symbian { -extern void FatalError(const char *msg); extern char* GetExecutablePath(); } #endif diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp index 7f141f2339..aa688534fc 100644 --- a/backends/platform/wii/main.cpp +++ b/backends/platform/wii/main.cpp @@ -25,6 +25,7 @@ #include <unistd.h> #include "osystem.h" +#include "backends/plugins/wii/wii-provider.h" #include <ogc/machine/processor.h> #include <fat.h> @@ -210,6 +211,10 @@ int main(int argc, char *argv[]) { g_system = new OSystem_Wii(); assert(g_system); +#ifdef DYNAMIC_MODULES + PluginManager::instance().addPluginProvider(new WiiPluginProvider()); +#endif + res = scummvm_main(argc, argv); g_system->quit(); diff --git a/backends/platform/wii/options.cpp b/backends/platform/wii/options.cpp index 2a47958e3b..ffabc5ae97 100644 --- a/backends/platform/wii/options.cpp +++ b/backends/platform/wii/options.cpp @@ -183,7 +183,7 @@ void WiiOptionsDialog::handleTickle() { break; default: - label = String::printf(_("Network not initialised (%d)"), status); + label = String::format(_("Network not initialised (%d)"), status); break; } diff --git a/backends/platform/wii/options.h b/backends/platform/wii/options.h index b126bde88f..00d42bc2ef 100644 --- a/backends/platform/wii/options.h +++ b/backends/platform/wii/options.h @@ -25,8 +25,8 @@ #include "common/str.h" #include "gui/dialog.h" -#include "gui/TabWidget.h" -#include "gui/EditTextWidget.h" +#include "gui/widgets/tab.h" +#include "gui/widgets/edittext.h" using namespace GUI; diff --git a/backends/platform/wii/wii.mk b/backends/platform/wii/wii.mk index c1512551d7..28066df8d4 100644 --- a/backends/platform/wii/wii.mk +++ b/backends/platform/wii/wii.mk @@ -32,6 +32,10 @@ else $(CP) $(srcdir)/dists/wii/icon.png wiidist/scummvm/ sed "s/@REVISION@/$(VER_SVNREV)/;s/@TIMESTAMP@/`date +%Y%m%d%H%M%S`/" < $(srcdir)/dists/wii/meta.xml > wiidist/scummvm/meta.xml endif +ifeq ($(DYNAMIC_MODULES),1) + $(MKDIR) wiidist/scummvm/plugins + for i in $(PLUGINS); do $(STRIP) --strip-debug $$i -o wiidist/scummvm/plugins/`basename $$i`; done +endif sed 's/$$/\r/' < $(srcdir)/dists/wii/READMII > wiidist/scummvm/READMII.txt for i in $(DIST_FILES_DOCS); do sed 's/$$/\r/' < $$i > wiidist/scummvm/`basename $$i`.txt; done $(CP) $(DIST_FILES_THEMES) wiidist/scummvm/ diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp index 64abd0be3e..99d0be2bdc 100644 --- a/backends/platform/wince/CEActionsPocket.cpp +++ b/backends/platform/wince/CEActionsPocket.cpp @@ -23,21 +23,25 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/platform/wince/wince-sdl.h" #include "CEActionsPocket.h" #include "EventsBuffer.h" #include "gui/message.h" -#include "scumm/scumm.h" #include "common/config-manager.h" #include "gui/KeysDialog.h" #include "common/translation.h" + #ifdef _WIN32_WCE #define KEY_ALL_SKIP 3457 #endif -const String pocketActionNames[] = { +const Common::String pocketActionNames[] = { _s("Pause"), _s("Save"), _s("Quit"), @@ -64,7 +68,7 @@ void CEActionsPocket::init() { } -String CEActionsPocket::actionName(GUI::ActionType action) { +Common::String CEActionsPocket::actionName(GUI::ActionType action) { return _(pocketActionNames[action]); } @@ -72,7 +76,7 @@ int CEActionsPocket::size() { return POCKET_ACTION_LAST; } -String CEActionsPocket::domain() { +Common::String CEActionsPocket::domain() { return ConfMan.kApplicationDomain; } @@ -81,8 +85,7 @@ int CEActionsPocket::version() { } CEActionsPocket::CEActionsPocket(const Common::String &gameid) : -GUI::Actions() -{ +GUI::Actions() { int i; _right_click_needed = false; @@ -114,7 +117,7 @@ void CEActionsPocket::initInstanceMain(OSystem *mainSystem) { } void CEActionsPocket::initInstanceGame() { - String gameid(ConfMan.get("gameid")); + Common::String gameid(ConfMan.get("gameid")); bool is_simon = (strncmp(gameid.c_str(), "simon", 5) == 0); bool is_sword1 = (gameid == "sword1"); bool is_sword2 = (strcmp(gameid.c_str(), "sword2") == 0); diff --git a/backends/platform/wince/CEActionsPocket.h b/backends/platform/wince/CEActionsPocket.h index 0fe29a9e86..72a2064fbf 100644 --- a/backends/platform/wince/CEActionsPocket.h +++ b/backends/platform/wince/CEActionsPocket.h @@ -28,7 +28,7 @@ #include "common/scummsys.h" #include "common/system.h" -#include "wince-sdl.h" +#include "common/str.h" #include "gui/Key.h" #include "gui/Actions.h" @@ -58,33 +58,35 @@ enum pocketActionType { POCKET_ACTION_LAST }; +class OSystem_WINCE3; + class CEActionsPocket : public GUI::Actions { - public: - // Actions - bool perform(GUI::ActionType action, bool pushed = true); - String actionName(GUI::ActionType action); - int size(); +public: + // Actions + bool perform(GUI::ActionType action, bool pushed = true); + Common::String actionName(GUI::ActionType action); + int size(); - static void init(); - void initInstanceMain(OSystem *mainSystem); - void initInstanceGame(); + static void init(); + void initInstanceMain(OSystem *mainSystem); + void initInstanceGame(); - // Action domain - String domain(); - int version(); + // Action domain + Common::String domain(); + int version(); - // Utility - bool needsRightClickMapping(); - bool needsHideToolbarMapping(); - bool needsZoomMapping(); + // Utility + bool needsRightClickMapping(); + bool needsHideToolbarMapping(); + bool needsZoomMapping(); - ~CEActionsPocket(); - private: - CEActionsPocket(const Common::String &gameid); - bool _right_click_needed; - bool _hide_toolbar_needed; - bool _zoom_needed; - OSystem_WINCE3 *_CESystem; - }; + ~CEActionsPocket(); +private: + CEActionsPocket(const Common::String &gameid); + bool _right_click_needed; + bool _hide_toolbar_needed; + bool _zoom_needed; + OSystem_WINCE3 *_CESystem; +}; #endif diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp index af80bd2908..5c7feb4950 100644 --- a/backends/platform/wince/CEActionsSmartphone.cpp +++ b/backends/platform/wince/CEActionsSmartphone.cpp @@ -23,10 +23,14 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "backends/platform/wince/wince-sdl.h" + #include "CEActionsSmartphone.h" #include "EventsBuffer.h" #include "gui/message.h" -#include "scumm/scumm.h" #include "common/config-manager.h" #include "gui/KeysDialog.h" diff --git a/backends/platform/wince/CEActionsSmartphone.h b/backends/platform/wince/CEActionsSmartphone.h index 36797cd2c8..29156bb152 100644 --- a/backends/platform/wince/CEActionsSmartphone.h +++ b/backends/platform/wince/CEActionsSmartphone.h @@ -28,7 +28,7 @@ #include "common/scummsys.h" #include "common/system.h" -#include "wince-sdl.h" +#include "common/str.h" #include "gui/Key.h" #include "gui/Actions.h" @@ -55,24 +55,24 @@ enum smartphoneActionType { class CEActionsSmartphone : public GUI::Actions { - public: - // Actions - bool perform(GUI::ActionType action, bool pushed = true); - String actionName(GUI::ActionType action); - int size(); - static void init(); - void initInstanceMain(OSystem *mainSystem); - void initInstanceGame(); +public: + // Actions + bool perform(GUI::ActionType action, bool pushed = true); + Common::String actionName(GUI::ActionType action); + int size(); + static void init(); + void initInstanceMain(OSystem *mainSystem); + void initInstanceGame(); - // Action domain - String domain(); - int version(); + // Action domain + Common::String domain(); + int version(); - ~CEActionsSmartphone(); - private: - CEActionsSmartphone(); - bool _right_click_needed; - OSystem_WINCE3 *_CESystem; - }; + ~CEActionsSmartphone(); +private: + CEActionsSmartphone(); + bool _right_click_needed; + OSystem_WINCE3 *_CESystem; +}; #endif diff --git a/backends/platform/wince/CEDevice.cpp b/backends/platform/wince/CEDevice.cpp index 98a8fb95f6..08acbbbfcd 100644 --- a/backends/platform/wince/CEDevice.cpp +++ b/backends/platform/wince/CEDevice.cpp @@ -23,11 +23,14 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "CEDevice.h" #include <SDL.h> -#include "wince-sdl.h" +#include "backends/platform/wince/wince-sdl.h" static void (WINAPI* _SHIdleTimerReset)(void) = NULL; static HANDLE (WINAPI* _SetPowerRequirement)(PVOID,int,ULONG,PVOID,ULONG) = NULL; diff --git a/backends/platform/wince/CEDevice.h b/backends/platform/wince/CEDevice.h index ca2f908c6d..b2b20d05ce 100644 --- a/backends/platform/wince/CEDevice.h +++ b/backends/platform/wince/CEDevice.h @@ -31,20 +31,20 @@ #include "common/str.h" class CEDevice { - public: - static void init(); - static void end(); - static void wakeUp(); - static bool hasPocketPCResolution(); - static bool hasSquareQVGAResolution(); - static bool hasDesktopResolution(); - static bool hasWideResolution(); - static bool hasSmartphoneResolution(); - static bool isSmartphone(); +public: + static void init(); + static void end(); + static void wakeUp(); + static bool hasPocketPCResolution(); + static bool hasSquareQVGAResolution(); + static bool hasDesktopResolution(); + static bool hasWideResolution(); + static bool hasSmartphoneResolution(); + static bool isSmartphone(); - private: - static DWORD reg_access(TCHAR *key, TCHAR *val, DWORD data); - static void backlight_xchg(); +private: + static DWORD reg_access(TCHAR *key, TCHAR *val, DWORD data); + static void backlight_xchg(); }; #endif diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp index 11e4900c2d..de1bb2f1f6 100644 --- a/backends/platform/wince/CELauncherDialog.cpp +++ b/backends/platform/wince/CELauncherDialog.cpp @@ -23,14 +23,16 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL -#include "wince-sdl.h" +#include "backends/platform/wince/wince-sdl.h" #include "CELauncherDialog.h" #include "engines/metaengine.h" -#include "gui/GuiManager.h" +#include "gui/gui-manager.h" #include "gui/widget.h" #include "gui/browser.h" #include "gui/message.h" diff --git a/backends/platform/wince/CEScaler.cpp b/backends/platform/wince/CEScaler.cpp index fd47635e05..182a7e0c94 100644 --- a/backends/platform/wince/CEScaler.cpp +++ b/backends/platform/wince/CEScaler.cpp @@ -22,6 +22,7 @@ * $Id$ * */ + #include "graphics/scaler/intern.h" #include "CEScaler.h" diff --git a/backends/platform/wince/CEgui/GUIElement.cpp b/backends/platform/wince/CEgui/GUIElement.cpp index 23e7843de1..7689837e3d 100644 --- a/backends/platform/wince/CEgui/GUIElement.cpp +++ b/backends/platform/wince/CEgui/GUIElement.cpp @@ -23,104 +23,108 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include <SDL.h> + #include "Toolbar.h" #include "SDL_ImageResource.h" namespace CEGUI { - GUIElement::GUIElement(int x, int y, int width, int height) : - _background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) - { - } +GUIElement::GUIElement(int x, int y, int width, int height) : +_background(0), _drawn(false), _visible(true), _x(x), _y(y), _width(width), _height(height) { +} - bool GUIElement::setBackground(WORD backgroundReference) { - _background = new SDL_ImageResource(); - if (!_background->load(backgroundReference)) { - delete _background; - _background = NULL; - return false; - } - if (!_height && !_width) { - _height = _background->height(); - _width = _background->width(); - } - else - if (_background->height() != _height || _background->width() != _width) { - delete _background; - _background = NULL; - return false; - } - return true; +bool GUIElement::setBackground(WORD backgroundReference) { + _background = new SDL_ImageResource(); + if (!_background->load(backgroundReference)) { + delete _background; + _background = NULL; + return false; } - - void GUIElement::move(int x, int y) { - _x = x; - _y = y; + if (!_height && !_width) { + _height = _background->height(); + _width = _background->width(); } + else + if (_background->height() != _height || _background->width() != _width) { + delete _background; + _background = NULL; + return false; + } + return true; +} - bool GUIElement::draw(SDL_Surface *surface) { - if (_background && !_drawn && _visible) { - SDL_Rect rect; - - rect.x = _x; - rect.y = _y; - rect.w = _width; - rect.h = _height; +void GUIElement::move(int x, int y) { + _x = x; + _y = y; +} - SDL_BlitSurface(_background->get(), NULL, surface, &rect); +bool GUIElement::draw(SDL_Surface *surface) { + if (_background && !_drawn && _visible) { + SDL_Rect rect; - _drawn = true; + rect.x = _x; + rect.y = _y; + rect.w = _width; + rect.h = _height; - return true; - } - else - return false; - } + SDL_BlitSurface(_background->get(), NULL, surface, &rect); - bool GUIElement::checkInside(int x, int y) { - if (x >= _x && x <= _x + _width && y >= _y && y <= _y + _height) - return true; - else - return false; - } + _drawn = true; - void GUIElement::setVisible(bool visibility) { - if (visibility && !_visible) - _drawn = false; - _visible = visibility; + return true; } + else + return false; +} - bool GUIElement::visible() { - return _visible; - } +bool GUIElement::checkInside(int x, int y) { + if (x >= _x && x <= _x + _width && y >= _y && y <= _y + _height) + return true; + else + return false; +} - void GUIElement::forceRedraw() { +void GUIElement::setVisible(bool visibility) { + if (visibility && !_visible) _drawn = false; - } + _visible = visibility; +} - bool GUIElement::drawn() { - return _drawn; - } +bool GUIElement::visible() { + return _visible; +} - int GUIElement::x() { - return _x; - } +void GUIElement::forceRedraw() { + _drawn = false; +} - int GUIElement::y() { - return _y; - } +bool GUIElement::drawn() { + return _drawn; +} - int GUIElement::width() { - return _width; - } +int GUIElement::x() { + return _x; +} - int GUIElement::height() { - return _height; - } +int GUIElement::y() { + return _y; +} - GUIElement::~GUIElement() { - delete _background; - } +int GUIElement::width() { + return _width; +} + +int GUIElement::height() { + return _height; +} +GUIElement::~GUIElement() { + delete _background; } + +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/GUIElement.h b/backends/platform/wince/CEgui/GUIElement.h index 7e4572d377..c599ebe9b5 100644 --- a/backends/platform/wince/CEgui/GUIElement.h +++ b/backends/platform/wince/CEgui/GUIElement.h @@ -29,39 +29,40 @@ #include "common/scummsys.h" #include "common/system.h" -#include "SDL.h" - -#include "SDL_ImageResource.h" +struct SDL_Surface; namespace CEGUI { - class GUIElement { - public: - bool setBackground(WORD backgroundReference); - void setVisible(bool visibility); - virtual void forceRedraw(); - virtual bool draw(SDL_Surface *surface); - virtual ~GUIElement(); - void move(int x, int y); - int width(); - int height(); - int x(); - int y(); - virtual bool action(int x, int y, bool pushed) = 0; - bool visible(); - bool drawn(); - protected: - GUIElement(int x = 0, int y = 0, int width = 0, int height = 0); - bool checkInside(int x, int y); - bool _visible; - SDL_ImageResource *_background; - int _x; - int _y; - bool _drawn; - private: - int _width; - int _height; - }; -} +class SDL_ImageResource; + +class GUIElement { +public: + bool setBackground(WORD backgroundReference); + void setVisible(bool visibility); + virtual void forceRedraw(); + virtual bool draw(SDL_Surface *surface); + virtual ~GUIElement(); + void move(int x, int y); + int width(); + int height(); + int x(); + int y(); + virtual bool action(int x, int y, bool pushed) = 0; + bool visible(); + bool drawn(); +protected: + GUIElement(int x = 0, int y = 0, int width = 0, int height = 0); + bool checkInside(int x, int y); + bool _visible; + SDL_ImageResource *_background; + int _x; + int _y; + bool _drawn; +private: + int _width; + int _height; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/ItemAction.cpp b/backends/platform/wince/CEgui/ItemAction.cpp index 3808622b2e..55805744e6 100644 --- a/backends/platform/wince/CEgui/ItemAction.cpp +++ b/backends/platform/wince/CEgui/ItemAction.cpp @@ -27,25 +27,25 @@ namespace CEGUI { - ItemAction::ItemAction(WORD reference, GUI::ActionType action) : - PanelItem(reference) { - _action = action; - if (!GUI::Actions::Instance()->isEnabled(_action)) - _visible = false; - } - - - ItemAction::~ItemAction() { - } - - bool ItemAction::action(int x, int y, bool pushed) { - - if (checkInside(x, y) && _visible && pushed) { - GUI::Actions::Instance()->perform(_action, true); - GUI::Actions::Instance()->perform(_action, false); - return true; - } - else - return false; - } +ItemAction::ItemAction(WORD reference, GUI::ActionType action) : +PanelItem(reference) { + _action = action; + if (!GUI::Actions::Instance()->isEnabled(_action)) + _visible = false; } + + +ItemAction::~ItemAction() { +} + +bool ItemAction::action(int x, int y, bool pushed) { + + if (checkInside(x, y) && _visible && pushed) { + GUI::Actions::Instance()->perform(_action, true); + GUI::Actions::Instance()->perform(_action, false); + return true; + } else + return false; +} + +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/ItemAction.h b/backends/platform/wince/CEgui/ItemAction.h index 74ed6bec4d..4f35b3090d 100644 --- a/backends/platform/wince/CEgui/ItemAction.h +++ b/backends/platform/wince/CEgui/ItemAction.h @@ -31,16 +31,18 @@ #include "gui/Actions.h" #include "CEgui/PanelItem.h" + namespace CEGUI { - class ItemAction : public PanelItem { - public: - ItemAction(WORD reference, GUI::ActionType action); - virtual ~ItemAction(); - virtual bool action(int x, int y, bool pushed); - private: - GUI::ActionType _action; - }; -} +class ItemAction : public PanelItem { +public: + ItemAction(WORD reference, GUI::ActionType action); + virtual ~ItemAction(); + virtual bool action(int x, int y, bool pushed); +private: + GUI::ActionType _action; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/ItemSwitch.cpp b/backends/platform/wince/CEgui/ItemSwitch.cpp index 8e0121f7c4..d4648f7556 100644 --- a/backends/platform/wince/CEgui/ItemSwitch.cpp +++ b/backends/platform/wince/CEgui/ItemSwitch.cpp @@ -24,71 +24,73 @@ */ #include "ItemSwitch.h" +#include "SDL_ImageResource.h" namespace CEGUI { - void ItemSwitch::init(WORD referenceTrue, WORD referenceFalse) { - _backgroundTrue = _background; - _backgroundFalse = new SDL_ImageResource(); - if (!_backgroundFalse->load(referenceFalse)) { - delete _backgroundFalse; - delete _background; - _background = NULL; - _backgroundFalse = NULL; - } +void ItemSwitch::init(WORD referenceTrue, WORD referenceFalse) { + _backgroundTrue = _background; + _backgroundFalse = new SDL_ImageResource(); + if (!_backgroundFalse->load(referenceFalse)) { + delete _backgroundFalse; + delete _background; + _background = NULL; + _backgroundFalse = NULL; } +} - ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item) : - PanelItem(referenceTrue) { - init(referenceTrue, referenceFalse); - _item = item; - _itemmax = -1; - if (!*_item) - _background = _backgroundFalse; - } +ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item) : +PanelItem(referenceTrue) { + init(referenceTrue, referenceFalse); + _item = item; + _itemmax = -1; + if (!*_item) + _background = _backgroundFalse; +} - ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max) : - PanelItem(referenceTrue) { - init(referenceTrue, referenceFalse); - _itemmultiple = item; - _itemmax = max; - if (!*item) - _background = _backgroundFalse; - } +ItemSwitch::ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max) : +PanelItem(referenceTrue) { + init(referenceTrue, referenceFalse); + _itemmultiple = item; + _itemmax = max; + if (!*item) + _background = _backgroundFalse; +} - ItemSwitch::~ItemSwitch() { - delete _backgroundFalse; - } +ItemSwitch::~ItemSwitch() { + delete _backgroundFalse; +} - bool ItemSwitch::action(int x, int y, bool pushed) { +bool ItemSwitch::action(int x, int y, bool pushed) { - if (checkInside(x, y) && _visible && pushed) { - if (_itemmax <= 0) { - *_item = !*_item; - if (*_item) - _background = _backgroundTrue; - else - _background = _backgroundFalse; + if (checkInside(x, y) && _visible && pushed) { + if (_itemmax <= 0) { + *_item = !*_item; + if (*_item) + _background = _backgroundTrue; + else + _background = _backgroundFalse; - if (_panel) - _panel->forceRedraw(); + if (_panel) + _panel->forceRedraw(); - return true; - } else { - *_itemmultiple = *_itemmultiple + 1; - if (*_itemmultiple > _itemmax) - *_itemmultiple = 0; - if (*_itemmultiple) - _background = _backgroundTrue; - else - _background = _backgroundFalse; + return true; + } else { + *_itemmultiple = *_itemmultiple + 1; + if (*_itemmultiple > _itemmax) + *_itemmultiple = 0; + if (*_itemmultiple) + _background = _backgroundTrue; + else + _background = _backgroundFalse; - if (_panel) - _panel->forceRedraw(); + if (_panel) + _panel->forceRedraw(); - return true; - } - } else - return false; - } + return true; + } + } else + return false; } + +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/ItemSwitch.h b/backends/platform/wince/CEgui/ItemSwitch.h index 8d03ee77cb..1ca6f3c288 100644 --- a/backends/platform/wince/CEgui/ItemSwitch.h +++ b/backends/platform/wince/CEgui/ItemSwitch.h @@ -36,20 +36,23 @@ using GUI::Key; namespace CEGUI { - class ItemSwitch : public PanelItem { - public: - ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item); - ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max); - virtual ~ItemSwitch(); - virtual bool action(int x, int y, bool pushed); - private: - void init(WORD referenceTrue, WORD referenceFalse); - bool *_item; - static bool _itemdummy; - int *_itemmultiple, _itemmax; - SDL_ImageResource *_backgroundTrue; - SDL_ImageResource *_backgroundFalse; - }; -} +class SDL_ImageResource; + +class ItemSwitch : public PanelItem { +public: + ItemSwitch(WORD referenceTrue, WORD referenceFalse, bool *item); + ItemSwitch(WORD referenceTrue, WORD referenceFalse, int *item, int max); + virtual ~ItemSwitch(); + virtual bool action(int x, int y, bool pushed); +private: + void init(WORD referenceTrue, WORD referenceFalse); + bool *_item; + static bool _itemdummy; + int *_itemmultiple, _itemmax; + SDL_ImageResource *_backgroundTrue; + SDL_ImageResource *_backgroundFalse; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/Panel.cpp b/backends/platform/wince/CEgui/Panel.cpp index a2d965ca78..dfdd6526be 100644 --- a/backends/platform/wince/CEgui/Panel.cpp +++ b/backends/platform/wince/CEgui/Panel.cpp @@ -27,59 +27,58 @@ namespace CEGUI { - Panel::Panel(int interleave_first, int interleave) : Toolbar() - { - _interleave = interleave; - _currentItem = interleave_first; - } +Panel::Panel(int interleave_first, int interleave) : Toolbar() { + _interleave = interleave; + _currentItem = interleave_first; +} - bool Panel::add(const String &name, const PanelItem *item) { - _itemsMap[name] = (PanelItem*)item; - _itemsMap[name]->move(_currentItem, _y + 10); - _itemsMap[name]->setPanel(this); - _currentItem += _interleave; +bool Panel::add(const String &name, const PanelItem *item) { + _itemsMap[name] = (PanelItem*)item; + _itemsMap[name]->move(_currentItem, _y + 10); + _itemsMap[name]->setPanel(this); + _currentItem += _interleave; - return true; - } + return true; +} - bool Panel::draw(SDL_Surface *surface) { - ItemMap::const_iterator iterator; - if (!_drawn && _visible) { - GUIElement::draw(surface); - for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) { - ((GUIElement*)(iterator->_value))->draw(surface); - } - return true; +bool Panel::draw(SDL_Surface *surface) { + ItemMap::const_iterator iterator; + if (!_drawn && _visible) { + GUIElement::draw(surface); + for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) { + ((GUIElement*)(iterator->_value))->draw(surface); } - else - return false; + return true; } + else + return false; +} - void Panel::forceRedraw() { - ItemMap::const_iterator iterator; - GUIElement::forceRedraw(); - for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) - ((GUIElement*)(iterator->_value))->forceRedraw(); - } +void Panel::forceRedraw() { + ItemMap::const_iterator iterator; + GUIElement::forceRedraw(); + for (iterator = _itemsMap.begin(); iterator != _itemsMap.end(); ++iterator) + ((GUIElement*)(iterator->_value))->forceRedraw(); +} - bool Panel::action(int x, int y, bool pushed) { - ItemMap::const_iterator iterator; - bool result = false; - if (!_visible || !checkInside(x, y)) - return false; +bool Panel::action(int x, int y, bool pushed) { + ItemMap::const_iterator iterator; + bool result = false; + if (!_visible || !checkInside(x, y)) + return false; - for (iterator = _itemsMap.begin(); !result && iterator != _itemsMap.end(); ++iterator) - result = ((GUIElement*)(iterator->_value))->action(x, y, pushed); - return result; - } + for (iterator = _itemsMap.begin(); !result && iterator != _itemsMap.end(); ++iterator) + result = ((GUIElement*)(iterator->_value))->action(x, y, pushed); + return result; +} - void Panel::clear() { - _itemsMap.clear(); - } +void Panel::clear() { + _itemsMap.clear(); +} - Panel::~Panel() { - _itemsMap.clear(); - } +Panel::~Panel() { + _itemsMap.clear(); } +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/Panel.h b/backends/platform/wince/CEgui/Panel.h index 6626e41866..e6b693360d 100644 --- a/backends/platform/wince/CEgui/Panel.h +++ b/backends/platform/wince/CEgui/Panel.h @@ -40,23 +40,24 @@ using Common::HashMap; namespace CEGUI { - class Panel : public Toolbar { - public: - Panel(int interleave_first, int interleave); - virtual bool draw(SDL_Surface *surface); - virtual ~Panel(); - bool add(const String &name, const PanelItem *item); - void clear(); - virtual void forceRedraw(); - virtual bool action(int x, int y, bool pushed); - private: - - typedef HashMap<String, PanelItem*, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap; - - ItemMap _itemsMap; - int _interleave; - int _currentItem; - }; -} +class Panel : public Toolbar { +public: + Panel(int interleave_first, int interleave); + virtual bool draw(SDL_Surface *surface); + virtual ~Panel(); + bool add(const String &name, const PanelItem *item); + void clear(); + virtual void forceRedraw(); + virtual bool action(int x, int y, bool pushed); +private: + + typedef HashMap<String, PanelItem*, Common::IgnoreCase_Hash , Common::IgnoreCase_EqualTo> ItemMap; + + ItemMap _itemsMap; + int _interleave; + int _currentItem; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/PanelItem.cpp b/backends/platform/wince/CEgui/PanelItem.cpp index 0898839c5d..8c68c79784 100644 --- a/backends/platform/wince/CEgui/PanelItem.cpp +++ b/backends/platform/wince/CEgui/PanelItem.cpp @@ -27,21 +27,21 @@ namespace CEGUI { - PanelItem::PanelItem(WORD reference) : GUIElement() { - setBackground(reference); - _panel = NULL; - } +PanelItem::PanelItem(WORD reference) : GUIElement() { + setBackground(reference); + _panel = NULL; +} - PanelItem::~PanelItem() { - } +PanelItem::~PanelItem() { +} - bool PanelItem::action(int x, int y, bool pushed) { - return false; - } +bool PanelItem::action(int x, int y, bool pushed) { + return false; +} - void PanelItem::setPanel(Panel *panel) { - _panel = panel; - } +void PanelItem::setPanel(Panel *panel) { + _panel = panel; } +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/PanelItem.h b/backends/platform/wince/CEgui/PanelItem.h index 55920c304a..14b62f0f20 100644 --- a/backends/platform/wince/CEgui/PanelItem.h +++ b/backends/platform/wince/CEgui/PanelItem.h @@ -33,18 +33,19 @@ namespace CEGUI { - class Panel; - - class PanelItem : public GUIElement { - friend class Panel; - public: - PanelItem(WORD reference); - virtual ~PanelItem(); - virtual bool action(int x, int y, bool pushed); - protected: - void setPanel(Panel *panel); - Panel *_panel; - }; -} +class Panel; + +class PanelItem : public GUIElement { +friend class Panel; +public: + PanelItem(WORD reference); + virtual ~PanelItem(); + virtual bool action(int x, int y, bool pushed); +protected: + void setPanel(Panel *panel); + Panel *_panel; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/PanelKeyboard.cpp b/backends/platform/wince/CEgui/PanelKeyboard.cpp index 369a75cae1..1b2a478746 100644 --- a/backends/platform/wince/CEgui/PanelKeyboard.cpp +++ b/backends/platform/wince/CEgui/PanelKeyboard.cpp @@ -23,77 +23,81 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include <SDL.h> + #include "PanelKeyboard.h" namespace CEGUI { - const char KEYBOARD_MAPPING_ALPHA[][14] = { {"abcdefghijklm"}, {"nopqrstuvwxyz"} }; - const char KEYBOARD_MAPPING_NUMERIC[][6] = { {"12345"}, {"67890"} }; - const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1,SDLK_ESCAPE}, {224,SDLK_UP}, {32,SDLK_SPACE} }, - { {224,SDLK_LEFT}, {224,SDLK_DOWN}, {224,SDLK_RIGHT} } }; +const char KEYBOARD_MAPPING_ALPHA[][14] = { {"abcdefghijklm"}, {"nopqrstuvwxyz"} }; +const char KEYBOARD_MAPPING_NUMERIC[][6] = { {"12345"}, {"67890"} }; +const int KEYBOARD_MAPPING_SPECIAL[][3][2] = { { {1,SDLK_ESCAPE}, {224,SDLK_UP}, {32,SDLK_SPACE} }, + { {224,SDLK_LEFT}, {224,SDLK_DOWN}, {224,SDLK_RIGHT} } }; - PanelKeyboard::PanelKeyboard(WORD reference) : Toolbar() { - setBackground(reference); - _state = false; - _lastKey.setKey(0); - } - - - PanelKeyboard::~PanelKeyboard() { - } - - bool PanelKeyboard::action(int x, int y, bool pushed) { - Key key; - - if (checkInside(x, y)) { - int keyAscii = 0; - int keyCode = 0; - if (x < 185) { - // Alpha selection - keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y+20][((x + 10) / 14) - 1]; - } else if (x >= 186 && x <= 255) { - // Numeric selection - keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y+20][((x - 187 + 10) / 14) - 1]; - } else if (x >= 258 && x <= 300) { - // Special keys - keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][0]; - keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][1]; - } else if (x >= 302 && x <= 316) { - if (y < _y +20) { - // Backspace - keyAscii = VK_BACK; keyCode = keyAscii; - } else { - // Enter - keyAscii = 13; keyCode = 13; - } - } +PanelKeyboard::PanelKeyboard(WORD reference) : Toolbar() { + setBackground(reference); + _state = false; + _lastKey.setKey(0); +} + + +PanelKeyboard::~PanelKeyboard() { +} - if (keyAscii != 0) { - if (_state && pushed && keyCode != _lastKey.keycode()) // if cursor is still down and off the current key - return false; - else if (_state && !pushed && keyCode != _lastKey.keycode()) { // cursor is up but off the current key - keyAscii = _lastKey.ascii(); - keyCode = _lastKey.keycode(); - } - _state = pushed; - _lastKey.setKey(keyAscii, tolower(keyCode)); - - key.setKey(keyAscii, tolower(keyCode)); - return EventsBuffer::simulateKey(&key, pushed); +bool PanelKeyboard::action(int x, int y, bool pushed) { + Key key; + + if (checkInside(x, y)) { + int keyAscii = 0; + int keyCode = 0; + if (x < 185) { + // Alpha selection + keyCode = keyAscii = KEYBOARD_MAPPING_ALPHA[y >= _y+20][((x + 10) / 14) - 1]; + } else if (x >= 186 && x <= 255) { + // Numeric selection + keyCode = keyAscii = KEYBOARD_MAPPING_NUMERIC[y >= _y+20][((x - 187 + 10) / 14) - 1]; + } else if (x >= 258 && x <= 300) { + // Special keys + keyAscii = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][0]; + keyCode = KEYBOARD_MAPPING_SPECIAL[y >= _y+20][((x - 259 + 10) / 14) - 1][1]; + } else if (x >= 302 && x <= 316) { + if (y < _y +20) { + // Backspace + keyAscii = VK_BACK; keyCode = keyAscii; + } else { + // Enter + keyAscii = 13; keyCode = 13; } - else if (_state && !pushed) { // cursor is in some forbidden region and is up - _state = false; - key = _lastKey; - return EventsBuffer::simulateKey(&key, false); - } else - return false; } - else if (_state && !pushed) { // cursor left the keyboard area and is up + + if (keyAscii != 0) { + if (_state && pushed && keyCode != _lastKey.keycode()) // if cursor is still down and off the current key + return false; + else if (_state && !pushed && keyCode != _lastKey.keycode()) { // cursor is up but off the current key + keyAscii = _lastKey.ascii(); + keyCode = _lastKey.keycode(); + } + _state = pushed; + _lastKey.setKey(keyAscii, tolower(keyCode)); + + key.setKey(keyAscii, tolower(keyCode)); + return EventsBuffer::simulateKey(&key, pushed); + } else if (_state && !pushed) { // cursor is in some forbidden region and is up _state = false; key = _lastKey; return EventsBuffer::simulateKey(&key, false); } else return false; - } + } else if (_state && !pushed) { // cursor left the keyboard area and is up + _state = false; + key = _lastKey; + return EventsBuffer::simulateKey(&key, false); + } else + return false; } +} // End of namespace CEGUI + diff --git a/backends/platform/wince/CEgui/PanelKeyboard.h b/backends/platform/wince/CEgui/PanelKeyboard.h index f441e14771..b98e6ff3a8 100644 --- a/backends/platform/wince/CEgui/PanelKeyboard.h +++ b/backends/platform/wince/CEgui/PanelKeyboard.h @@ -37,15 +37,16 @@ using CEKEYS::EventsBuffer; namespace CEGUI { - class PanelKeyboard : public Toolbar { - public: - PanelKeyboard(WORD reference); - virtual ~PanelKeyboard(); - virtual bool action(int x, int y, bool pushed); - private: - bool _state; - Key _lastKey; - }; -} +class PanelKeyboard : public Toolbar { +public: + PanelKeyboard(WORD reference); + virtual ~PanelKeyboard(); + virtual bool action(int x, int y, bool pushed); +private: + bool _state; + Key _lastKey; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.cpp b/backends/platform/wince/CEgui/SDL_ImageResource.cpp index ce6ebd6382..567013b5ff 100644 --- a/backends/platform/wince/CEgui/SDL_ImageResource.cpp +++ b/backends/platform/wince/CEgui/SDL_ImageResource.cpp @@ -23,63 +23,67 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include "SDL.h" #include "SDL_ImageResource.h" namespace CEGUI { - SDL_ImageResource::SDL_ImageResource() : - _surface(0) - { - } +SDL_ImageResource::SDL_ImageResource() : + _surface(0) { +} - SDL_Surface* SDL_ImageResource::load(WORD resourceID) { - HRSRC resource; - HGLOBAL resourceGlobal; - LPVOID resourcePointer; - DWORD resourceSize; - SDL_RWops *surfaceData; - HMODULE moduleHandle; +SDL_Surface* SDL_ImageResource::load(WORD resourceID) { + HRSRC resource; + HGLOBAL resourceGlobal; + LPVOID resourcePointer; + DWORD resourceSize; + SDL_RWops *surfaceData; + HMODULE moduleHandle; - moduleHandle = GetModuleHandle(NULL); - resource = FindResource(moduleHandle, MAKEINTRESOURCE(resourceID), TEXT("BINARY")); - if (!resource) - return NULL; - resourceSize = SizeofResource(moduleHandle, resource); - if (!resourceSize) - return NULL; - resourceGlobal = LoadResource(moduleHandle, resource); - if (!resourceGlobal) - return NULL; - resourcePointer = LockResource(resourceGlobal); - if (!resourcePointer) - return NULL; + moduleHandle = GetModuleHandle(NULL); + resource = FindResource(moduleHandle, MAKEINTRESOURCE(resourceID), TEXT("BINARY")); + if (!resource) + return NULL; + resourceSize = SizeofResource(moduleHandle, resource); + if (!resourceSize) + return NULL; + resourceGlobal = LoadResource(moduleHandle, resource); + if (!resourceGlobal) + return NULL; + resourcePointer = LockResource(resourceGlobal); + if (!resourcePointer) + return NULL; - surfaceData = SDL_RWFromMem(resourcePointer, resourceSize); - if (!surfaceData) - return NULL; - _surface = SDL_LoadBMP_RW(surfaceData, 1); + surfaceData = SDL_RWFromMem(resourcePointer, resourceSize); + if (!surfaceData) + return NULL; + _surface = SDL_LoadBMP_RW(surfaceData, 1); - return _surface; - } + return _surface; +} - SDL_Surface* SDL_ImageResource::get() { - return _surface; - } +SDL_Surface* SDL_ImageResource::get() { + return _surface; +} - int SDL_ImageResource::height() { - if (_surface) - return _surface->h; - return 0; - } +int SDL_ImageResource::height() { + if (_surface) + return _surface->h; + return 0; +} - int SDL_ImageResource::width() { - if (_surface) - return _surface->w; - return 0; - } +int SDL_ImageResource::width() { + if (_surface) + return _surface->w; + return 0; +} - SDL_ImageResource::~SDL_ImageResource() { - if (_surface) - SDL_FreeSurface(_surface); - } +SDL_ImageResource::~SDL_ImageResource() { + if (_surface) + SDL_FreeSurface(_surface); } + +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/SDL_ImageResource.h b/backends/platform/wince/CEgui/SDL_ImageResource.h index 454237dd15..5affd5c33c 100644 --- a/backends/platform/wince/CEgui/SDL_ImageResource.h +++ b/backends/platform/wince/CEgui/SDL_ImageResource.h @@ -29,20 +29,22 @@ #include "common/scummsys.h" #include "common/system.h" -#include "SDL.h" +struct SDL_Surface; namespace CEGUI { - class SDL_ImageResource { - public: - SDL_ImageResource(); - SDL_Surface* load(WORD resourceID); - SDL_Surface* get(); - int height(); - int width(); - virtual ~SDL_ImageResource(); - private: - SDL_Surface *_surface; - }; -} + +class SDL_ImageResource { +public: + SDL_ImageResource(); + SDL_Surface* load(WORD resourceID); + SDL_Surface* get(); + int height(); + int width(); + virtual ~SDL_ImageResource(); +private: + SDL_Surface *_surface; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/Toolbar.cpp b/backends/platform/wince/CEgui/Toolbar.cpp index 0501249de9..c41a30cb43 100644 --- a/backends/platform/wince/CEgui/Toolbar.cpp +++ b/backends/platform/wince/CEgui/Toolbar.cpp @@ -27,12 +27,12 @@ namespace CEGUI { - // Not to be drawn on game screen ! - Toolbar::Toolbar() : GUIElement(0, 0, 320, 40) - { - } +// Not to be drawn on game screen ! +Toolbar::Toolbar() : GUIElement(0, 0, 320, 40) { +} - Toolbar::~Toolbar() { - } +Toolbar::~Toolbar() { } + +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/Toolbar.h b/backends/platform/wince/CEgui/Toolbar.h index 3c48e6188a..9fdf05ab3f 100644 --- a/backends/platform/wince/CEgui/Toolbar.h +++ b/backends/platform/wince/CEgui/Toolbar.h @@ -27,25 +27,20 @@ #define CEGUI_TOOLBAR_H #include "common/scummsys.h" -#include "common/system.h" - -//#include "common/map.h" -#include "common/str.h" #include "GUIElement.h" - - namespace CEGUI { - class Toolbar : public GUIElement { - public: - virtual ~Toolbar(); - virtual bool action(int x, int y, bool pushed) = 0; - protected: - Toolbar(); +class Toolbar : public GUIElement { +public: + virtual ~Toolbar(); + virtual bool action(int x, int y, bool pushed) = 0; +protected: + Toolbar(); + +}; - }; -} +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEgui/ToolbarHandler.cpp b/backends/platform/wince/CEgui/ToolbarHandler.cpp index 3f93a4720d..f74d24ad25 100644 --- a/backends/platform/wince/CEgui/ToolbarHandler.cpp +++ b/backends/platform/wince/CEgui/ToolbarHandler.cpp @@ -23,106 +23,111 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include <SDL.h> + #include "ToolbarHandler.h" namespace CEGUI { - ToolbarHandler::ToolbarHandler(): - _current(""), _active(NULL) { - } - +ToolbarHandler::ToolbarHandler(): +_current(""), _active(NULL) { +} - bool ToolbarHandler::add(const String &name, const Toolbar &toolbar) { - _toolbarMap[name] = (Toolbar*)&toolbar; - if (!_active) { - _active = &((Toolbar&)toolbar); - _current = name; - } +bool ToolbarHandler::add(const String &name, const Toolbar &toolbar) { + _toolbarMap[name] = (Toolbar*)&toolbar; - return true; + if (!_active) { + _active = &((Toolbar&)toolbar); + _current = name; } - String ToolbarHandler::activeName() { - return _current; - } + return true; +} - bool ToolbarHandler::setActive(const String &name) { - if (!_toolbarMap.contains(name)) - return false; - if (_current == name) - return true; - _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel) - _current = name; - _active = _toolbarMap[name]; - _active->forceRedraw(); +String ToolbarHandler::activeName() { + return _current; +} + +bool ToolbarHandler::setActive(const String &name) { + if (!_toolbarMap.contains(name)) + return false; + if (_current == name) return true; - } + _active->action(0, 0, false); // make sure any items are unpushed when changing toolbars (e.g. forced VK->main panel) + _current = name; + _active = _toolbarMap[name]; + _active->forceRedraw(); + return true; +} - bool ToolbarHandler::action(int x, int y, bool pushed) { - if (_active && _active->visible()) { - // FIXME ! - if (_offset > 240) - return _active->action(x / 2, (y - _offset) / 2, pushed); - else - return _active->action(x, y - _offset, pushed); - } +bool ToolbarHandler::action(int x, int y, bool pushed) { + if (_active && _active->visible()) { + // FIXME ! + if (_offset > 240) + return _active->action(x / 2, (y - _offset) / 2, pushed); else - return false; + return _active->action(x, y - _offset, pushed); } + else + return false; +} - void ToolbarHandler::setVisible(bool visible) { - if (_active) - _active->setVisible(visible); - } +void ToolbarHandler::setVisible(bool visible) { + if (_active) + _active->setVisible(visible); +} - bool ToolbarHandler::visible() { - if (_active) - return _active->visible(); - else - return false; - } +bool ToolbarHandler::visible() { + if (_active) + return _active->visible(); + else + return false; +} - void ToolbarHandler::forceRedraw() { - if (_active) - _active->forceRedraw(); - } +void ToolbarHandler::forceRedraw() { + if (_active) + _active->forceRedraw(); +} - bool ToolbarHandler::drawn() { - if (_active) - return _active->drawn(); - else - return false; - } +bool ToolbarHandler::drawn() { + if (_active) + return _active->drawn(); + else + return false; +} - bool ToolbarHandler::draw(SDL_Surface *surface, SDL_Rect *rect) { - if (_active) { - bool result = _active->draw(surface); - if (result) { - rect->x = _active->x(); - rect->y = _active->y(); - rect->w = _active->width(); - rect->h = _active->height(); - } - return result; +bool ToolbarHandler::draw(SDL_Surface *surface, SDL_Rect *rect) { + if (_active) { + bool result = _active->draw(surface); + if (result) { + rect->x = _active->x(); + rect->y = _active->y(); + rect->w = _active->width(); + rect->h = _active->height(); } - else - return false; - } + return result; + } else + return false; +} - void ToolbarHandler::setOffset(int offset) { - _offset = offset; - } +void ToolbarHandler::setOffset(int offset) { + _offset = offset; +} - int ToolbarHandler::getOffset() { - return _offset; - } +int ToolbarHandler::getOffset() { + return _offset; +} - Toolbar* ToolbarHandler::active() { - return _active; - } +Toolbar* ToolbarHandler::active() { + return _active; +} - ToolbarHandler::~ToolbarHandler() { - _toolbarMap.clear(); - } +ToolbarHandler::~ToolbarHandler() { + _toolbarMap.clear(); } + +} // End of namespace CEGUI diff --git a/backends/platform/wince/CEgui/ToolbarHandler.h b/backends/platform/wince/CEgui/ToolbarHandler.h index 4a79ed1609..e3bf590768 100644 --- a/backends/platform/wince/CEgui/ToolbarHandler.h +++ b/backends/platform/wince/CEgui/ToolbarHandler.h @@ -39,29 +39,30 @@ using Common::HashMap; namespace CEGUI { - class ToolbarHandler { - public: - ToolbarHandler(); - bool add(const String &name, const Toolbar &toolbar); - bool setActive(const String &name); - bool action(int x, int y, bool pushed); - void setVisible(bool visible); - bool visible(); - String activeName(); - void forceRedraw(); - void setOffset(int offset); - int getOffset(); - bool draw(SDL_Surface *surface, SDL_Rect *rect); - bool drawn(); - Toolbar *active(); - virtual ~ToolbarHandler(); - private: +class ToolbarHandler { +public: + ToolbarHandler(); + bool add(const String &name, const Toolbar &toolbar); + bool setActive(const String &name); + bool action(int x, int y, bool pushed); + void setVisible(bool visible); + bool visible(); + String activeName(); + void forceRedraw(); + void setOffset(int offset); + int getOffset(); + bool draw(SDL_Surface *surface, SDL_Rect *rect); + bool drawn(); + Toolbar *active(); + virtual ~ToolbarHandler(); +private: - HashMap<String, Toolbar*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap; - String _current; - Toolbar *_active; - int _offset; - }; -} + HashMap<String, Toolbar*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _toolbarMap; + String _current; + Toolbar *_active; + int _offset; +}; + +} // End of namespace CEGUI #endif diff --git a/backends/platform/wince/CEkeys/EventsBuffer.cpp b/backends/platform/wince/CEkeys/EventsBuffer.cpp index f31a77570f..3cdcb44173 100644 --- a/backends/platform/wince/CEkeys/EventsBuffer.cpp +++ b/backends/platform/wince/CEkeys/EventsBuffer.cpp @@ -23,6 +23,11 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + +#include <SDL.h> + #include "EventsBuffer.h" namespace CEKEYS { diff --git a/backends/platform/wince/CEkeys/EventsBuffer.h b/backends/platform/wince/CEkeys/EventsBuffer.h index 44e1c66e47..22590db03c 100644 --- a/backends/platform/wince/CEkeys/EventsBuffer.h +++ b/backends/platform/wince/CEkeys/EventsBuffer.h @@ -30,8 +30,6 @@ #include "common/system.h" #include "common/list.h" -#include <SDL.h> - #include "gui/Key.h" namespace CEKEYS { diff --git a/backends/platform/wince/missing/assert.h b/backends/platform/wince/missing/assert.h index 0a9dc23bb8..734b8f9482 100644 --- a/backends/platform/wince/missing/assert.h +++ b/backends/platform/wince/missing/assert.h @@ -3,7 +3,7 @@ // defined in common/util.h void CDECL _declspec(noreturn) error(const char *s, ...); -#define assert(e) ((e) ? 0 : (::error("Assertion failed " #e " (%s, %d)", __FILE__, __LINE__))) +#define assert(e) ((e) ? 0 : (::error("Assertion failed %s (%s, %d)", #e, __FILE__, __LINE__))) #define abort() ::error("Abort (%s, %d)", __FILE__, __LINE__) diff --git a/backends/platform/wince/missing/conio.h b/backends/platform/wince/missing/conio.h deleted file mode 100644 index 0cb5c297ea..0000000000 --- a/backends/platform/wince/missing/conio.h +++ /dev/null @@ -1,2 +0,0 @@ -/* Header is not present in Windows CE SDK */ - diff --git a/backends/platform/wince/missing/dir.h b/backends/platform/wince/missing/dir.h deleted file mode 100644 index 7ee9f5e5ba..0000000000 --- a/backends/platform/wince/missing/dir.h +++ /dev/null @@ -1 +0,0 @@ -/* Header is not present in Windows CE SDK */ diff --git a/backends/platform/wince/missing/direct.h b/backends/platform/wince/missing/direct.h deleted file mode 100644 index 7ee9f5e5ba..0000000000 --- a/backends/platform/wince/missing/direct.h +++ /dev/null @@ -1 +0,0 @@ -/* Header is not present in Windows CE SDK */ diff --git a/backends/platform/wince/missing/dirent.h b/backends/platform/wince/missing/dirent.h deleted file mode 100644 index 07e54bbb9d..0000000000 --- a/backends/platform/wince/missing/dirent.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Header is not present in Windows CE SDK */ -/* It would not be a bad idea to take this thing from gcc distro and port - it properly. For now only required part is ported. */ - -struct dirent -{ - long d_ino; /* Always zero. */ - unsigned short d_reclen; /* Always zero. */ - unsigned short d_namlen; /* Length of name in d_name. */ - char* d_name; /* File name. */ - /* NOTE: The name in the dirent structure points to the name in the - * finddata_t structure in the DIR. */ -}; - -/* - * This is an internal data structure. Good programmers will not use it - * except as an argument to one of the functions below. - */ -typedef struct -{ - /* disk transfer area for this dir */ -/* struct _finddata_t dd_dta; */ - - /* dirent struct to return from dir (NOTE: this makes this thread - * safe as long as only one thread uses a particular DIR struct at - * a time) */ - struct dirent dd_dir; - - /* _findnext handle */ - long dd_handle; - - /* - * Status of search: - * 0 = not started yet (next entry to read is first entry) - * -1 = off the end - * positive = 0 based index of next entry - */ - short dd_stat; - - /* given path for dir with search pattern (struct is extended) */ - char dd_name[1]; -} DIR; - - -DIR* opendir (const char*); -struct dirent* readdir (DIR*); -int closedir (DIR*); -/* -void rewinddir (DIR*); -long telldir (DIR*); -void seekdir (DIR*, long); -*/ diff --git a/backends/platform/wince/missing/fcntl.h b/backends/platform/wince/missing/fcntl.h deleted file mode 100644 index 7ee9f5e5ba..0000000000 --- a/backends/platform/wince/missing/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -/* Header is not present in Windows CE SDK */ diff --git a/backends/platform/wince/missing/gcc/assert.h b/backends/platform/wince/missing/gcc/assert.h deleted file mode 100644 index 06742532ac..0000000000 --- a/backends/platform/wince/missing/gcc/assert.h +++ /dev/null @@ -1,9 +0,0 @@ -/* Header is not present in Windows CE SDK */ - -// defined in common/util.h -void CDECL _declspec(noreturn) error(const char *s, ...); - -#define assert(e) ((e) ? (void) 0 : (::error("Assertion failed " #e " (%s, %d)", __FILE__, __LINE__))) - -#define abort() ::error("Abort (%s, %d)", __FILE__, __LINE__) - diff --git a/backends/platform/wince/missing/gcc/direct.h b/backends/platform/wince/missing/gcc/direct.h deleted file mode 100644 index 7ee9f5e5ba..0000000000 --- a/backends/platform/wince/missing/gcc/direct.h +++ /dev/null @@ -1 +0,0 @@ -/* Header is not present in Windows CE SDK */ diff --git a/backends/platform/wince/missing/gcc/errno.h b/backends/platform/wince/missing/gcc/errno.h deleted file mode 100644 index 7ee9f5e5ba..0000000000 --- a/backends/platform/wince/missing/gcc/errno.h +++ /dev/null @@ -1 +0,0 @@ -/* Header is not present in Windows CE SDK */ diff --git a/backends/platform/wince/missing/gcc/sys/stat.h b/backends/platform/wince/missing/gcc/sys/stat.h deleted file mode 100644 index d9eef1318d..0000000000 --- a/backends/platform/wince/missing/gcc/sys/stat.h +++ /dev/null @@ -1,23 +0,0 @@ -/* Header is not present in Windows CE SDK */ - -#include <sys/types.h> - -struct stat { - _dev_t st_dev; - _ino_t st_ino; - unsigned short st_mode; - short st_nlink; - short st_uid; - short st_gid; - _dev_t st_rdev; - _off_t st_size; - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -}; - - -#define _S_IFDIR 0040000 /* directory */ -#define S_IFDIR _S_IFDIR - -int stat(const char *, struct stat *); diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp index 532f1d2e89..92af3e6961 100644 --- a/backends/platform/wince/missing/missing.cpp +++ b/backends/platform/wince/missing/missing.cpp @@ -29,19 +29,14 @@ * by Vasyl Tsvirkunov */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL #include <windows.h> #include <tchar.h> #include <string.h> #include <stdlib.h> -#include "sys/stat.h" -#ifndef __GNUC__ -#include "sys/time.h" -#else #include <stdio.h> -#endif -#include "time.h" -#include "dirent.h" #include "common/debug.h" char *strdup(const char *strSource); @@ -74,44 +69,8 @@ void *bsearch(const void *key, const void *base, size_t nmemb, return NULL; } -static WIN32_FIND_DATA wfd; - -int stat(const char *fname, struct stat *ss) { - TCHAR fnameUnc[MAX_PATH+1]; - HANDLE handle; - int len; - - if (fname == NULL || ss == NULL) - return -1; - - /* Special case (dummy on WinCE) */ - len = strlen(fname); - if (len >= 2 && fname[len-1] == '.' && fname[len-2] == '.' && - (len == 2 || fname[len-3] == '\\')) { - /* That's everything implemented so far */ - memset(ss, 0, sizeof(struct stat)); - ss->st_size = 1024; - ss->st_mode |= S_IFDIR; - return 0; - } - - MultiByteToWideChar(CP_ACP, 0, fname, -1, fnameUnc, MAX_PATH); - handle = FindFirstFile(fnameUnc, &wfd); - FindClose(handle); - if (handle == INVALID_HANDLE_VALUE) - return -1; - else - { - /* That's everything implemented so far */ - memset(ss, 0, sizeof(struct stat)); - ss->st_size = wfd.nFileSizeLow; - if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - ss->st_mode |= S_IFDIR; - } - return 0; -} +static char cwd[MAX_PATH+1] = ""; -char cwd[MAX_PATH+1] = ""; EXT_C char *getcwd(char *buffer, int maxlen) { TCHAR fileUnc[MAX_PATH+1]; char* plast; @@ -226,112 +185,6 @@ int _access(const char *path, int mode) { // evc only functions follow #ifndef __GNUC__ -/* Limited dirent implementation. Used by UI.C and DEVICES.C */ -DIR* opendir(const char* fname) { - DIR* pdir; - char fnameMask[MAX_PATH+1]; - TCHAR fnameUnc[MAX_PATH+1]; - char nameFound[MAX_PATH+1]; - - if (fname == NULL) - return NULL; - - strcpy(fnameMask, fname); - if (!strlen(fnameMask) || fnameMask[strlen(fnameMask)-1] != '\\') - strncat(fnameMask, "\\", MAX_PATH-strlen(fnameMask)-1); - strncat(fnameMask, "*.*", MAX_PATH-strlen(fnameMask)-4); - - pdir = (DIR*)malloc(sizeof(DIR)+strlen(fname)); - pdir->dd_dir.d_ino = 0; - pdir->dd_dir.d_reclen = 0; - pdir->dd_dir.d_name = 0; - pdir->dd_dir.d_namlen = 0; - - pdir->dd_handle = 0; - pdir->dd_stat = 0; - strcpy(pdir->dd_name, fname); /* it has exactly enough space for fname and nul char */ - - MultiByteToWideChar(CP_ACP, 0, fnameMask, -1, fnameUnc, MAX_PATH); - if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE) { - free(pdir); - return NULL; - } else { - WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL); - - pdir->dd_dir.d_name = strdup(nameFound); - pdir->dd_dir.d_namlen = strlen(nameFound); - } - return pdir; -} - -struct dirent* readdir(DIR* dir) { - char nameFound[MAX_PATH+1]; - static struct dirent dummy; - - if (dir->dd_stat == 0) { - dummy.d_name = "."; - dummy.d_namlen = 1; - dir->dd_stat ++; - return &dummy; - } else if (dir->dd_stat == 1) { - dummy.d_name = ".."; - dummy.d_namlen = 2; - dir->dd_stat ++; - return &dummy; - } else if (dir->dd_stat == 2) { - dir->dd_stat++; - return &dir->dd_dir; - } else { - if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0) { - dir->dd_stat = -1; - return NULL; - } - WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL); - - free(dir->dd_dir.d_name); - - dir->dd_dir.d_name = strdup(nameFound); - dir->dd_dir.d_namlen = strlen(nameFound); - - dir->dd_stat ++; - - return &dir->dd_dir; - } -} - -int closedir(DIR* dir) { - if (dir == NULL) - return 0; - - if (dir->dd_handle) - FindClose((HANDLE)dir->dd_handle); - - free(dir->dd_dir.d_name); - free(dir); - return 1; -} - -/* Make directory, Unix style */ -void mkdir(char* dirname, int mode) { - char path[MAX_PATH+1]; - TCHAR pathUnc[MAX_PATH+1]; - char *ptr; - strncpy(path, dirname, MAX_PATH); - if (*path == '/') - *path = '\\'; - /* Run through the string and attempt creating all subdirs on the path */ - for (ptr = path+1; *ptr; ptr ++) { - if (*ptr == '\\' || *ptr == '/') { - *ptr = 0; - MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); - CreateDirectory(pathUnc, 0); - *ptr = '\\'; - } - } - MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH); - CreateDirectory(pathUnc, 0); -} - char *strdup(const char *strSource) { char *buffer; size_z len = strlen(strSource) + 1; diff --git a/backends/platform/wince/missing/signal.h b/backends/platform/wince/missing/signal.h deleted file mode 100644 index 128d6bf1db..0000000000 --- a/backends/platform/wince/missing/signal.h +++ /dev/null @@ -1,3 +0,0 @@ -/* Header is not present in Windows CE SDK */ -/* Functionality is not critical -- Pocket PC devices do not have Ctrl+C */ -#define signal(a,b) diff --git a/backends/platform/wince/missing/sys/stat.h b/backends/platform/wince/missing/sys/stat.h deleted file mode 100644 index 8f5bda59e1..0000000000 --- a/backends/platform/wince/missing/sys/stat.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Header is not present in Windows CE SDK */ - -#include <sys/types.h> - -#ifndef __MINGW32CE__ -struct stat { - _dev_t st_dev; - _ino_t st_ino; - unsigned short st_mode; - short st_nlink; - short st_uid; - short st_gid; - _dev_t st_rdev; - _off_t st_size; - time_t st_atime; - time_t st_mtime; - time_t st_ctime; -}; - -int stat(const char *, struct stat *); - -#endif - -#define _S_IFDIR 0040000 /* directory */ -#define S_IFDIR _S_IFDIR diff --git a/backends/platform/wince/missing/sys/time.h b/backends/platform/wince/missing/sys/time.h deleted file mode 100644 index ded29bb009..0000000000 --- a/backends/platform/wince/missing/sys/time.h +++ /dev/null @@ -1,10 +0,0 @@ -/* Header is not present in Windows CE SDK */ - -struct timeval -{ - int tv_sec; - int tv_usec; -}; - -void gettimeofday(struct timeval* tp, void* dummy); -void usleep(long usec); diff --git a/backends/platform/wince/missing/sys/types.h b/backends/platform/wince/missing/sys/types.h deleted file mode 100644 index b6c05e3958..0000000000 --- a/backends/platform/wince/missing/sys/types.h +++ /dev/null @@ -1,5 +0,0 @@ -/* Header is not present in Windows CE SDK */ - -typedef unsigned short _ino_t; -typedef unsigned int _dev_t; -typedef long _off_t; diff --git a/backends/platform/wince/missing/unistd.h b/backends/platform/wince/missing/unistd.h deleted file mode 100644 index 7ee9f5e5ba..0000000000 --- a/backends/platform/wince/missing/unistd.h +++ /dev/null @@ -1 +0,0 @@ -/* Header is not present in Windows CE SDK */ diff --git a/backends/platform/wince/portdefs.h b/backends/platform/wince/portdefs.h index 4b9c53e707..cbf2006be2 100644 --- a/backends/platform/wince/portdefs.h +++ b/backends/platform/wince/portdefs.h @@ -69,14 +69,10 @@ char *strpbrk(const char *s, const char *accept); #include <string.h> #include <io.h> #include <stdarg.h> -#include <fcntl.h> -#include <conio.h> -#include <malloc.h> #include <assert.h> #include <mmsystem.h> #include <ctype.h> //#include <direct.h> -#include <time.h> #ifdef __MINGW32CE__ void *bsearch(const void *, const void *, size_t, size_t, int (*x) (const void *, const void *)); diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index ac9be5df48..3f64cb7d5d 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -23,6 +23,9 @@ * */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/platform/wince/wince-sdl.h" #include "common/config-manager.h" @@ -970,8 +973,9 @@ bool OSystem_WINCE3::getFeatureState(Feature f) { return false; case kFeatureVirtualKeyboard: return (_panelStateForced); + default: + return OSystem_SDL::getFeatureState(f); } - return OSystem_SDL::getFeatureState(f); } void OSystem_WINCE3::check_mappings() { @@ -2053,7 +2057,7 @@ void OSystem_WINCE3::undrawMouse() { if (SDL_LockSurface(_overlayVisible ? _overlayscreen : _screen) == -1) error("SDL_LockSurface failed: %s", SDL_GetError()); - int x, y; + int y; if (!_overlayVisible) { byte *dst, *bak = _mouseBackupOld; @@ -2242,14 +2246,15 @@ static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) { if (unfilter) { switch (key) { - case SDLK_ESCAPE: - return SDLK_BACKSPACE; - case SDLK_F8: - return SDLK_ASTERISK; - case SDLK_F9: - return SDLK_HASH; + case SDLK_ESCAPE: + return SDLK_BACKSPACE; + case SDLK_F8: + return SDLK_ASTERISK; + case SDLK_F9: + return SDLK_HASH; + default: + return key; } - return key; } if (key >= SDLK_KP0 && key <= SDLK_KP9) { @@ -2265,7 +2270,6 @@ static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) { bool OSystem_WINCE3::pollEvent(Common::Event &event) { SDL_Event ev; ev.type = SDL_NOEVENT; - byte b = 0; DWORD currentTime; bool keyEvent = false; int deltaX, deltaY; diff --git a/backends/plugins/ds/ds-provider.cpp b/backends/plugins/ds/ds-provider.cpp new file mode 100644 index 0000000000..832fd1312c --- /dev/null +++ b/backends/plugins/ds/ds-provider.cpp @@ -0,0 +1,47 @@ +/* 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(__DS__) + +#include <malloc.h> +#include <nds.h> + +#include "backends/plugins/ds/ds-provider.h" +#include "backends/plugins/elf/arm-loader.h" + +class DSDLObject : public ARMDLObject { +protected: + virtual void flushDataCache(void *ptr, uint32 len) const { + DC_FlushRange(ptr, len); + IC_InvalidateRange(ptr, len); + } +}; + +Plugin *DSPluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin<DSDLObject>(node.getPath()); +} + +#endif // defined(DYNAMIC_MODULES) && defined(__DS__) + diff --git a/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h b/backends/plugins/ds/ds-provider.h index 5f0c739379..dcb93c085f 100644 --- a/backends/graphics/gp2xwizsdl/gp2xwizsdl-graphics.h +++ b/backends/plugins/ds/ds-provider.h @@ -23,36 +23,19 @@ * */ -#ifndef BACKENDS_GRAPHICS_SDL_GP2XWIZ_H -#define BACKENDS_GRAPHICS_SDL_GP2XWIZ_H +#if defined(DYNAMIC_MODULES) && defined(__DS__) -#include "backends/graphics/sdl/sdl-graphics.h" +#ifndef BACKENDS_PLUGINS_DS_PROVIDER_H +#define BACKENDS_PLUGINS_DS_PROVIDER_H -// FIXME: For now keep hacks in this header to save polluting the SDL backend. -enum { - GFX_HALF = 12 -}; +#include "backends/plugins/elf/elf-provider.h" -class GP2XWIZSdlGraphicsManager : public SdlGraphicsManager { +class DSPluginProvider : public ELFPluginProvider { public: - virtual void setGraphicsModeIntern(); - virtual bool setGraphicsMode(int mode); - virtual const OSystem::GraphicsMode *getSupportedGraphicsModes() const; - virtual int getDefaultGraphicsMode() const; - - virtual void initSize(uint w, uint h); - - virtual void internUpdateScreen(); - - virtual bool loadGFXMode(); - - virtual void drawMouse(); - virtual void undrawMouse(); + Plugin *createPlugin(const Common::FSNode &node) const; +}; - virtual void showOverlay(); - virtual void hideOverlay(); +#endif // BACKENDS_PLUGINS_DS_PROVIDER_H - virtual void warpMouse(int x, int y); -}; +#endif // defined(DYNAMIC_MODULES) && defined(__DS__) -#endif diff --git a/backends/plugins/ds/plugin.ld b/backends/plugins/ds/plugin.ld new file mode 100644 index 0000000000..04035b0169 --- /dev/null +++ b/backends/plugins/ds/plugin.ld @@ -0,0 +1,217 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) + +/* PHDRS specifies ELF Program Headers (or segments) to the plugin linker */ +PHDRS { + plugin PT_LOAD ; /* Specifies that the plugin segment should be loaded from file */ +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0; + .interp : { *(.interp) } : plugin + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.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.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.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.bss .rel.bss.* .rel.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .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.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } + .rel.plt : + { + *(.rel.plt) + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + __exidx_start = .; + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + __exidx_end = .; + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* 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(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .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)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data : + { + __data_start = . ; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .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. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + __end__ = . ; + _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) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .stack 0x80000 : + { + _stack = .; + *(.stack) + } + .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/backends/plugins/elf/arm-loader.cpp b/backends/plugins/elf/arm-loader.cpp new file mode 100644 index 0000000000..93d3c60f84 --- /dev/null +++ b/backends/plugins/elf/arm-loader.cpp @@ -0,0 +1,133 @@ +/* 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/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET) + +#include "backends/plugins/elf/arm-loader.h" + +#include "common/debug.h" + +bool ARMDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) { + Elf32_Rel *rel = 0; //relocation entry + + // Allocate memory for relocation table + if (!(rel = (Elf32_Rel *)malloc(size))) { + warning("elfloader: Out of memory."); + return false; + } + + // Read in our relocation table + if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) { + warning("elfloader: Relocation table load failed."); + free(rel); + return false; + } + + // Treat each relocation entry. Loop over all of them + uint32 cnt = size / sizeof(*rel); + + debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment); + + int32 a = 0; + uint32 relocation = 0; + + // Loop over relocation entries + for (uint32 i = 0; i < cnt; i++) { + // Get the symbol this relocation entry is referring to + Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info)); + + // Get the target instruction in the code. TODO: repect _segmentVMA + uint32 *target = (uint32 *)((byte *)relSegment + rel[i].r_offset); + + uint32 origTarget = *target; //Save for debugging + + // Act differently based on the type of relocation + switch (REL_TYPE(rel[i].r_info)) { + case R_ARM_ABS32: + if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. + a = *target; // Get full 32 bits of addend + relocation = a + Elf32_Addr(_segment); // Shift by main offset + + *target = relocation; + + debug(8, "elfloader: R_ARM_ABS32: i=%d, a=%x, origTarget=%x, target=%x", i, a, origTarget, *target); + } + break; + + case R_ARM_THM_CALL: + debug(8, "elfloader: R_ARM_THM_CALL: PC-relative jump, ld takes care of necessary relocation work for us."); + break; + + case R_ARM_CALL: + debug(8, "elfloader: R_ARM_CALL: PC-relative jump, ld takes care of necessary relocation work for us."); + break; + + case R_ARM_JUMP24: + debug(8, "elfloader: R_ARM_JUMP24: PC-relative jump, ld takes care of all relocation work for us."); + break; + + case R_ARM_V4BX: + debug(8, "elfloader: R_ARM_V4BX: No relocation calculation necessary."); + break; + + default: + warning("elfloader: Unknown relocation type %d.", REL_TYPE(rel[i].r_info)); + free(rel); + return false; + } + } + + free(rel); + return true; +} + +bool ARMDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + // Loop over sections, finding relocation sections + for (uint32 i = 0; i < ehdr->e_shnum; i++) { + Elf32_Shdr *curShdr = &(shdr[i]); + + if ((curShdr->sh_type == SHT_REL || curShdr->sh_type == SHT_RELA) && // Check for a relocation section + curShdr->sh_entsize == sizeof(Elf32_Rel) && // Check for proper relocation size + int32(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 (curShdr->sh_type == SHT_RELA) { + warning("elfloader: RELA entries not supported yet!"); + return false; + } + + if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment)) + return false; + } + } + + return true; +} + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET) */ + diff --git a/backends/plugins/elf/arm-loader.h b/backends/plugins/elf/arm-loader.h new file mode 100644 index 0000000000..cb4230c1ee --- /dev/null +++ b/backends/plugins/elf/arm-loader.h @@ -0,0 +1,44 @@ +/* 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_PLUGINS_ARM_LOADER_H +#define BACKENDS_PLUGINS_ARM_LOADER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET) + +#include "backends/plugins/elf/elf-loader.h" + +class ARMDLObject : public DLObject { +protected: + virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment); + virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); +}; + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(ARM_TARGET) */ + +#endif /* BACKENDS_PLUGINS_ARM_LOADER_H */ + diff --git a/backends/plugins/elf/elf-loader.cpp b/backends/plugins/elf/elf-loader.cpp new file mode 100644 index 0000000000..f7b151ecee --- /dev/null +++ b/backends/plugins/elf/elf-loader.cpp @@ -0,0 +1,440 @@ +/* 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/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +#include "backends/plugins/elf/elf-loader.h" + +#include "common/debug.h" +#include "common/file.h" +#include "common/fs.h" +#include "common/ptr.h" + +#include <malloc.h> // for memalign() + +DLObject::DLObject() : + _file(0), + _segment(0), + _symtab(0), + _strtab(0), + _segmentSize(0), + _segmentOffset(0), + _segmentVMA(0), + _symbol_cnt(0), + _symtab_sect(-1), + _dtors_start(0), + _dtors_end(0) { +} + +DLObject::~DLObject() { + discardSymtab(); + free(_segment); + _segment = 0; +} + +// Expel the symbol table from memory +void DLObject::discardSymtab() { + free(_symtab); + _symtab = 0; + + free(_strtab); + _strtab = 0; + + _symbol_cnt = 0; +} + +// Unload all objects from memory +void DLObject::unload() { + discardSymtab(); + + free(_segment); + + _segment = 0; + _segmentSize = 0; + _segmentOffset = 0; + _segmentVMA = 0; +} + +bool DLObject::readElfHeader(Elf32_Ehdr *ehdr) { + assert(_file); + + // Start reading the elf header. Check for errors and magic + if (_file->read(ehdr, sizeof(*ehdr)) != sizeof(*ehdr) || + memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { + warning("elfloader: No ELF file."); + return false; + } + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) { + warning("elfloader: Wrong ELF file class."); + return false; + } + + if (ehdr->e_ident[EI_DATA] != +#ifdef SCUMM_BIG_ENDIAN + ELFDATA2MSB +#else + ELFDATA2LSB +#endif + ) { + warning("elfloader: Wrong ELF file endianess."); + return false; + } + + if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) { + warning("elfloader: Wrong ELF file version."); + return false; + } + + if (ehdr->e_type != ET_EXEC) { + warning("elfloader: No executable ELF file."); + return false; + } + + if (ehdr->e_machine != +#ifdef ARM_TARGET + EM_ARM +#endif +#ifdef MIPS_TARGET + EM_MIPS +#endif +#ifdef PPC_TARGET + EM_PPC +#endif + ) { + warning("elfloader: Wrong ELF file architecture."); + return false; + } + + if (ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header + ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header + warning("elfloader: Invalid ELF structure sizes."); + return false; + } + + debug(2, "elfloader: phoff = %d, phentsz = %d, phnum = %d", + ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum); + + return true; +} + +bool DLObject::readProgramHeaders(Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half num) { + assert(_file); + + // Read program header + if (!_file->seek(ehdr->e_phoff + sizeof(*phdr) * num, SEEK_SET) || + _file->read(phdr, sizeof(*phdr)) != sizeof(*phdr)) { + warning("elfloader: Program header load failed."); + return false; + } + + // Check program header values + if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) { + warning("elfloader: Invalid program header."); + return false; + } + + debug(2, "elfloader: offs = %x, filesz = %x, memsz = %x, align = %x", + phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align); + + return true; +} + +bool DLObject::loadSegment(Elf32_Phdr *phdr) { + _segment = (byte *)memalign(phdr->p_align, phdr->p_memsz); + + if (!_segment) { + warning("elfloader: Out of memory."); + return false; + } + + debug(2, "elfloader: Allocated segment @ %p", _segment); + + // Get offset to load segment into + _segmentSize = phdr->p_memsz; + _segmentVMA = phdr->p_vaddr; + + // Set .bss segment to 0 if necessary + if (phdr->p_memsz > phdr->p_filesz) { + debug(2, "elfloader: Setting %p to %p to 0 for bss", + _segment + phdr->p_filesz, _segment + phdr->p_memsz); + memset(_segment + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); + } + + debug(2, "elfloader: Reading the segment into memory"); + + // Read the segment into memory + if (!_file->seek(phdr->p_offset, SEEK_SET) || + _file->read(_segment, phdr->p_filesz) != phdr->p_filesz) { + warning("elfloader: Segment load failed."); + return false; + } + + debug(2, "elfloader: Segment has been read into memory"); + + return true; +} + +Elf32_Shdr * DLObject::loadSectionHeaders(Elf32_Ehdr *ehdr) { + assert(_file); + + Elf32_Shdr *shdr = 0; + + // Allocate memory for section headers + if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) { + warning("elfloader: Out of memory."); + return 0; + } + + // Read from file into section headers + if (!_file->seek(ehdr->e_shoff, SEEK_SET) || + _file->read(shdr, ehdr->e_shnum * sizeof(*shdr)) != + ehdr->e_shnum * sizeof(*shdr)) { + warning("elfloader: Section headers load failed."); + free(shdr); + return 0; + } + + return shdr; +} + +int DLObject::loadSymbolTable(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + assert(_file); + + // Loop over sections, looking for symbol table linked to a string table + for (uint32 i = 0; i < ehdr->e_shnum; i++) { + 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) { + warning("elfloader: No symbol table."); + return -1; + } + + debug(2, "elfloader: Symbol section at section %d, size %x", + _symtab_sect, shdr[_symtab_sect].sh_size); + + // Allocate memory for symbol table + if (!(_symtab = (Elf32_Sym *)malloc(shdr[_symtab_sect].sh_size))) { + warning("elfloader: Out of memory."); + return -1; + } + + // Read symbol table into memory + if (!_file->seek(shdr[_symtab_sect].sh_offset, SEEK_SET) || + _file->read(_symtab, shdr[_symtab_sect].sh_size) != + shdr[_symtab_sect].sh_size) { + warning("elfloader: Symbol table load failed."); + free(_symtab); + _symtab = 0; + return -1; + } + + // Set number of symbols + _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym); + debug(2, "elfloader: Loaded %d symbols.", _symbol_cnt); + + return _symtab_sect; +} + +bool DLObject::loadStringTable(Elf32_Shdr *shdr) { + assert(_file); + + uint32 string_sect = shdr[_symtab_sect].sh_link; + + // Allocate memory for string table + if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) { + warning("elfloader: Out of memory."); + return false; + } + + // Read string table into memory + if (!_file->seek(shdr[string_sect].sh_offset, SEEK_SET) || + _file->read(_strtab, shdr[string_sect].sh_size) != + shdr[string_sect].sh_size) { + warning("elfloader: Symbol table strings load failed."); + free(_strtab); + _strtab = 0; + return false; + } + + return true; +} + +void DLObject::relocateSymbols(ptrdiff_t offset) { + // Loop over symbols, add relocation offset + Elf32_Sym *s = _symtab; + + for (uint32 c = _symbol_cnt; c--; s++) { + // Make sure we don't relocate special valued symbols + if (s->st_shndx < SHN_LOPROC) { + s->st_value += offset; + + if (s->st_value < Elf32_Addr(_segment) || + s->st_value > Elf32_Addr(_segment) + _segmentSize) + warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value); + } + } +} + +bool DLObject::load() { + Elf32_Ehdr ehdr; + Elf32_Phdr phdr; + + if (readElfHeader(&ehdr) == false) + return false; + + for (uint32 i = 0; i < ehdr.e_phnum; i++) { //Load our segments + debug(2, "elfloader: Loading segment %d", i); + + if (readProgramHeaders(&ehdr, &phdr, i) == false) + return false; + + if (!loadSegment(&phdr)) + return false; + } + + Elf32_Shdr *shdr = loadSectionHeaders(&ehdr); + if (!shdr) + return false; + + _symtab_sect = loadSymbolTable(&ehdr, shdr); + if (_symtab_sect < 0) { + free(shdr); + return false; + } + + if (!loadStringTable(shdr)) { + free(shdr); + return false; + } + + // Offset by our segment allocated address + // must use _segmentVMA here for multiple segments (MIPS) + _segmentOffset = ptrdiff_t(_segment) - _segmentVMA; + relocateSymbols(_segmentOffset); + + if (!relocateRels(&ehdr, shdr)) { + free(shdr); + return false; + } + + return true; +} + +bool DLObject::open(const char *path) { + void *ctors_start, *ctors_end; + + debug(2, "elfloader: open(\"%s\")", path); + + _file = Common::FSNode(path).createReadStream(); + + if (!_file) { + warning("elfloader: File %s not found.", path); + return false; + } + + debug(2, "elfloader: %s found!", path); + + /*Try to load and relocate*/ + if (!load()) { + unload(); + return false; + } + + debug(2, "elfloader: Loaded!"); + + delete _file; + _file = 0; + + flushDataCache(_segment, _segmentSize); + + 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 || !ctors_end || !_dtors_start || !_dtors_end) { + warning("elfloader: Missing ctors/dtors."); + _dtors_start = _dtors_end = 0; + unload(); + return false; + } + + debug(2, "elfloader: Calling constructors."); + for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++) + (**f)(); + + debug(2, "elfloader: %s opened ok.", path); + + return true; +} + +bool DLObject::close() { + if (_dtors_start && _dtors_end) + for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++) + (**f)(); + + _dtors_start = _dtors_end = 0; + unload(); + return true; +} + +void *DLObject::symbol(const char *name) { + debug(2, "elfloader: Symbol(\"%s\")", name); + + if (!_symtab || !_strtab || _symbol_cnt < 1) { + warning("elfloader: No symbol table loaded."); + return 0; + } + + Elf32_Sym *s = _symtab; + + for (uint32 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) && + !strcmp(name, _strtab + s->st_name)) { + // We found the symbol + debug(2, "elfloader: => 0x%08x", s->st_value); + return (void*)s->st_value; + } + + // We didn't find the symbol + warning("elfloader: Symbol \"%s\" not found.", name); + return 0; +} + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) */ + diff --git a/backends/plugins/elf/elf-loader.h b/backends/plugins/elf/elf-loader.h new file mode 100644 index 0000000000..2825cc9d8d --- /dev/null +++ b/backends/plugins/elf/elf-loader.h @@ -0,0 +1,102 @@ +/* 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_PLUGINS_ELF_LOADER_H +#define BACKENDS_PLUGINS_ELF_LOADER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +#include <stddef.h> + +#include "backends/plugins/elf/elf32.h" +#include "backends/plugins/dynamic-plugin.h" + +#include "common/stream.h" + +/** + * DLObject + * + * Class that most directly handles operations on a plugin file + * (opening it for reading, loading/unloading it in memory, finding a specific symbol in the file, etc.) + * Subclasses have the same functionality, but implementations specific to different processors/platforms. + */ +class DLObject { +protected: + Common::SeekableReadStream *_file; + + byte *_segment; + Elf32_Sym *_symtab; + char *_strtab; + + uint32 _segmentSize; + ptrdiff_t _segmentOffset; + uint32 _segmentVMA; + + uint32 _symbol_cnt; + int32 _symtab_sect; + void *_dtors_start, *_dtors_end; + + virtual void unload(); + bool load(); + + bool readElfHeader(Elf32_Ehdr *ehdr); + bool readProgramHeaders(Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, Elf32_Half num); + virtual bool loadSegment(Elf32_Phdr *phdr); + Elf32_Shdr *loadSectionHeaders(Elf32_Ehdr *ehdr); + int loadSymbolTable(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); + bool loadStringTable(Elf32_Shdr *shdr); + virtual void relocateSymbols(ptrdiff_t offset); + + // architecture specific + + /** + * Follow the instruction of a relocation section. + * + * @param fileOffset Offset into the File + * @param size Size of relocation section + * @param relSegment Base address of relocated segment in memory (memory offset) + */ + virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) = 0; + virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) = 0; + + // platform specific + virtual void flushDataCache(void *ptr, uint32 len) const = 0; + +public: + DLObject(); + virtual ~DLObject(); + + bool open(const char *path); + bool close(); + void *symbol(const char *name); + void discardSymtab(); +}; + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) */ + +#endif /* BACKENDS_PLUGINS_ELF_LOADER_H */ + diff --git a/backends/plugins/elf/elf-provider.cpp b/backends/plugins/elf/elf-provider.cpp new file mode 100644 index 0000000000..b241379934 --- /dev/null +++ b/backends/plugins/elf/elf-provider.cpp @@ -0,0 +1,177 @@ +/* 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/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +#ifdef ELF_LOADER_CXA_ATEXIT +#include <cxxabi.h> +#endif + +#include "backends/plugins/elf/elf-provider.h" +#include "backends/plugins/dynamic-plugin.h" + +#include "common/debug.h" +#include "common/fs.h" + +/* Note about ELF_LOADER_CXA_ATEXIT: + * + * consider the code: + * + * class Foobar { + * const char *work() { + * static String foo = "bar"; + * return s.c_str(); + * } + * } + * + * When instantiating Foobar and calling work() for the first time the String + * foo will be constructed. GCC automatically registers its destruction via + * either atexit() or __cxa_atexit(). Only the latter will add information + * about which DSO did the construction (Using &__dso_handle). + * + * __cxa_atexit allows plugins to reference C++ ABI symbols in the main + * executable without code duplication (No need to link the plugin against + * libstdc++), since we can distinguish which registered exit functions belong + * to a specific DSO. When unloading a plugin, we just use the C++ ABI call + * __cxa_finalize(&__dso_handle) to call all destructors of only that DSO. + * + * Prerequisites: + * - The used libc needs to support __cxa_atexit + * - -fuse-cxa-atexit in CXXFLAGS + * - Every plugin needs its own hidden __dso_handle symbol + * This is automatically done via REGISTER_PLUGIN_DYNAMIC, see base/plugins.h + * + * When __cxa_atexit can not be used, each plugin needs to link against + * libstdc++ to embed its own set of C++ ABI symbols. When not doing so, + * registered destructors of already unloaded plugins will crash the + * application upon returning from main(). + * + * See "3.3.5 DSO Object Destruction API" of the C++ ABI + */ + +DynamicPlugin::VoidFunc ELFPlugin::findSymbol(const char *symbol) { + void *func = 0; + + if (_dlHandle) + func = _dlHandle->symbol(symbol); + + if (!func) { + if (!_dlHandle) + warning("elfloader: Failed loading symbol '%s' from plugin '%s' (Handle is NULL)", symbol, _filename.c_str()); + else + warning("elfloader: Failed loading symbol '%s' from plugin '%s'", symbol, _filename.c_str()); + } + + // 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; +} + +bool ELFPlugin::loadPlugin() { + assert(!_dlHandle); + + DLObject *obj = makeDLObject(); + if (obj->open(_filename.c_str())) { + _dlHandle = obj; + } else { + delete obj; + _dlHandle = 0; + } + + if (!_dlHandle) { + warning("elfloader: Failed loading plugin '%s'", _filename.c_str()); + return false; + } + + CharFunc buildDateFunc = (CharFunc)findSymbol("PLUGIN_getBuildDate"); + if (!buildDateFunc) { + unloadPlugin(); + warning("elfloader: plugin '%s' is missing symbols", _filename.c_str()); + return false; + } + + if (strncmp(gScummVMPluginBuildDate, buildDateFunc(), strlen(gScummVMPluginBuildDate))) { + unloadPlugin(); + warning("elfloader: plugin '%s' has a different build date", _filename.c_str()); + return false; + } + + bool ret = DynamicPlugin::loadPlugin(); + +#ifdef ELF_LOADER_CXA_ATEXIT + if (ret) { + // FIXME HACK: Reverse HACK of findSymbol() :P + VoidFunc tmp; + tmp = findSymbol("__dso_handle"); + memcpy(&_dso_handle, &tmp, sizeof(VoidFunc)); + debug(2, "elfloader: __dso_handle is %p", _dso_handle); + } +#endif + + _dlHandle->discardSymtab(); + + return ret; +} + +void ELFPlugin::unloadPlugin() { + DynamicPlugin::unloadPlugin(); + + if (_dlHandle) { +#ifdef ELF_LOADER_CXA_ATEXIT + if (_dso_handle) { + debug(2, "elfloader: calling __cxa_finalize"); + __cxxabiv1::__cxa_finalize(_dso_handle); + _dso_handle = 0; + } +#endif + + if (!_dlHandle->close()) + warning("elfloader: Failed unloading plugin '%s'", _filename.c_str()); + + delete _dlHandle; + _dlHandle = 0; + } +} + +bool ELFPluginProvider::isPluginFilename(const Common::FSNode &node) const { + // Check the plugin suffix + Common::String filename = node.getName(); + + if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg") && + !filename.hasSuffix(".PLUGIN") && !filename.hasSuffix(".plugin")) + return false; + + return true; +} + +#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + diff --git a/backends/plugins/elf/elf-provider.h b/backends/plugins/elf/elf-provider.h new file mode 100644 index 0000000000..4d05c0956b --- /dev/null +++ b/backends/plugins/elf/elf-provider.h @@ -0,0 +1,97 @@ +/* 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_PLUGINS_ELF_PROVIDER_H +#define BACKENDS_PLUGINS_ELF_PROVIDER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +#include "backends/plugins/elf/elf-loader.h" + +#include "common/fs.h" + +/** + * ELFPlugin + * + * Objects of this class are returned when the PluginManager calls + * getPlugins() on an ELFPluginProvider. An intermediary class for + * dealing with plugin files, ELFPlugin is responsible for creating/destroying + * a DLObject that handles the opening/loading/unloading of the plugin file whose + * path in the target backend's file system is "_filename". + */ +class ELFPlugin : public DynamicPlugin { +protected: + typedef const char *(*CharFunc)(); + + DLObject *_dlHandle; + Common::String _filename; + void *_dso_handle; + + virtual VoidFunc findSymbol(const char *symbol); + +public: + ELFPlugin(const Common::String &filename) : + _dlHandle(0), + _filename(filename), + _dso_handle(0) { + } + + virtual ~ELFPlugin() { + if (_dlHandle) + unloadPlugin(); + } + + virtual DLObject *makeDLObject() = 0; + + bool loadPlugin(); + void unloadPlugin(); +}; + +template<class T> +class TemplatedELFPlugin : public ELFPlugin { +public: + TemplatedELFPlugin(const Common::String &filename) : + ELFPlugin(filename) { + } + + virtual DLObject *makeDLObject() { + return new T(); + } +}; + + +class ELFPluginProvider : public FilePluginProvider { +protected: + virtual Plugin *createPlugin(const Common::FSNode &node) const = 0; + + bool isPluginFilename(const Common::FSNode &node) const; +}; + +#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +#endif /* BACKENDS_PLUGINS_ELF_PROVIDER_H */ + diff --git a/backends/plugins/elf/elf32.h b/backends/plugins/elf/elf32.h new file mode 100644 index 0000000000..48ebf2e7b2 --- /dev/null +++ b/backends/plugins/elf/elf32.h @@ -0,0 +1,252 @@ +/* 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 + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +/** + * ELF stuff: + * The contents of this file were gathered mainly from the SYSTEM V APPLICATION BINARY INTERFACE. + * Processor-specific things were garnered from processor-specific supplements to the abi. + */ + +typedef uint16 Elf32_Half, Elf32_Section; +typedef uint32 Elf32_Word, Elf32_Addr, Elf32_Off; +typedef int32 Elf32_Sword; +typedef Elf32_Half Elf32_Versym; + +#define EI_NIDENT (16) +#define SELFMAG 4 + +/* ELF File format structures. Look up ELF structure for more details */ + +// ELF header (contains info about the file) +typedef struct { + byte 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" /* ELF Magic number */ + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASS32 1 /* 32-bit objects */ + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ + +#define EI_VERSION 6 +#define EV_CURRENT 1 /* Current version */ + +// 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 +#define EM_PPC 20 +#define EM_ARM 40 +#define EM_SH 42 + +// 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 for MIPS */ +#define PT_ARM_ARCHEXT 0x70000000 /* Platform architecture compatibility info for ARM */ +#define PT_ARM_EXIDX 0x70000001 /* Exception unwind tables for ARM */ + +// 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 for MIPS*/ +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicts btw executables and shared objects for MIPS */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global pointer table for MIPS*/ +#define SHT_ARM_EXIDX 0x70000001 /* Exception Index table for ARM*/ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking pre-emption map for ARM */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility attributes for ARM*/ + +// 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 for MIPS */ + +// 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 */ + byte st_info; /* Symbol type and binding */ + byte 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 with implicit addend (info about how to relocate) +typedef struct { + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +// Relocation entry with explicit addend (info about how to relocate) +typedef struct { + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +// Access macros for the relocation info +#define REL_TYPE(x) ((byte) (x)) /* 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 + +// ARM relocation types +#define R_ARM_NONE 0 +#define R_ARM_ABS32 2 +#define R_ARM_THM_CALL 10 +#define R_ARM_CALL 28 +#define R_ARM_JUMP24 29 +#define R_ARM_TARGET1 38 +#define R_ARM_V4BX 40 + +// PPC relocation types +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_REL24 10 +#define R_PPC_REL32 26 + +#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) + +#endif /* BACKENDS_ELF_H */ + diff --git a/backends/plugins/elf/mips-loader.cpp b/backends/plugins/elf/mips-loader.cpp new file mode 100644 index 0000000000..b25017af98 --- /dev/null +++ b/backends/plugins/elf/mips-loader.cpp @@ -0,0 +1,342 @@ +/* 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/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) + +#include "backends/plugins/elf/mips-loader.h" + +#include "common/debug.h" + +#define DEBUG_NUM 2 + +bool MIPSDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) { + Elf32_Rel *rel = 0; // relocation entry + + // Allocate memory for relocation table + if (!(rel = (Elf32_Rel *)malloc(size))) { + warning("elfloader: Out of memory."); + return false; + } + + // Read in our relocation table + if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) { + warning("elfloader: Relocation table load failed."); + free(rel); + return false; + } + + // Treat each relocation entry. Loop over all of them + uint32 cnt = size / sizeof(*rel); + + debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment); + + Elf32_Addr adjustedMainSegment = Elf32_Addr(_segment) - _segmentVMA; // adjust for VMA offset + + bool seenHi16 = false; // For treating HI/LO16 commands + int32 firstHi16 = -1; // Mark the point of the first hi16 seen + Elf32_Addr ahl = 0; // Calculated addend + int32 a = 0; // Addend: taken from the target + + uint32 *lastTarget = 0; // For processing hi16 when lo16 arrives + uint32 relocation = 0; + uint debugRelocs[10] = { 0 }; // For debugging + uint extendedHi16 = 0; // Count extended hi16 treatments + Elf32_Addr lastHiSymVal = 0; + bool hi16InShorts = false; + + // Loop over relocation entries + for (uint32 i = 0; i < cnt; i++) { + // Get the symbol this relocation entry is referring to + Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info)); + + // Get the target instruction in the code. + uint32 *target = (uint32 *)((byte *)relSegment + rel[i].r_offset); + + uint32 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 + debug(8, "elfloader: R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x", + 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 + debug(8, "elfloader: R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!", 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 + adjustedMainSegment; // Add in the new offset for the segment + + if (firstHi16 >= 0) { // We haven't treated the HI16s yet so do it now + for (uint32 j = firstHi16; j < i; j++) { + if (REL_TYPE(rel[j].r_info) != R_MIPS_HI16) + continue; // Skip over non-Hi16s + + lastTarget = (uint32 *)((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) + debug(8, "elfloader: R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, " + "lastTarget = %x, origt = %x, target = %x", + i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); + + if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM) + debug(8, "elfloader: R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, " + "lastTarget = %x, origt = %x, target = %x", + 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) + adjustedMainSegment) >> 2; // a already points to the target. Add our offset + *target &= 0xfc000000; // Clean lower 26 target bits + *target |= (relocation & 0x03ffffff); + + if (debugRelocs[3]++ < DEBUG_NUM) + debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, " + "a=%x, origTarget=%x, target=%x", + i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); + } else { + if (debugRelocs[4]++ < DEBUG_NUM) + debug(8, "elfloader: R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, " + "a=%x, origTarget=%x, target=%x", + 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) + debug(8, "elfloader: R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, " + "target=%x, offset=%x", + 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 + adjustedMainSegment; // Shift by main offset + + *target = relocation; + + if (debugRelocs[6]++ < DEBUG_NUM) + debug(8, "elfloader: R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x", + i, a, origTarget, *target); + } + + break; + + default: + warning("elfloader: Unknown relocation type %x at relocation %d.", REL_TYPE(rel[i].r_info), i); + free(rel); + return false; + } + } + + debug(2, "elfloader: Done with relocation. extendedHi16=%d", extendedHi16); + + free(rel); + return true; +} + +bool MIPSDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + // Loop over sections, finding relocation sections + for (uint32 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 + int32(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(curShdr->sh_offset, curShdr->sh_size, _segment - _segmentVMA)) + return false; + } else { // In Shorts segment + if (!relocate(curShdr->sh_offset, curShdr->sh_size, (byte *)_shortsSegment->getOffset())) + return false; + } + } + } + + return true; +} + +void MIPSDLObject::relocateSymbols(ptrdiff_t offset) { + // Loop over symbols, add relocation offset + Elf32_Sym *s = _symtab; + + for (uint32 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)) { + if (s->st_value < _segmentVMA) + s->st_value = _segmentVMA; // deal with symbols referring to sections, which start before the VMA + + s->st_value += offset; + + if (s->st_value < Elf32_Addr(_segment) || s->st_value > Elf32_Addr(_segment) + _segmentSize) + warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value); + } else { // shorts section + s->st_value += _shortsSegment->getOffset(); + if (!_shortsSegment->inSegment((char *)s->st_value)) + warning("elfloader: Symbol out of bounds! st_value = %x", s->st_value); + } + } + } +} + +bool MIPSDLObject::loadSegment(Elf32_Phdr *phdr) { + byte *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 + _segment = (byte *)memalign(phdr->p_align, phdr->p_memsz); + + if (!_segment) { + warning("elfloader: Out of memory."); + return false; + } + + debug(2, "elfloader: Allocated segment @ %p", _segment); + + // Get offset to load segment into + baseAddress = _segment; + _segmentSize = phdr->p_memsz; + _segmentVMA = phdr->p_vaddr; + + } else { // This is a shorts section. + _shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr); + + baseAddress = (byte *)_shortsSegment->getStart(); + debug(2, "elfloader: Shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x", + _shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, + _shortsSegment->getOffset()); + } + + // Set .sbss segment to 0 if necessary + if (phdr->p_memsz > phdr->p_filesz) { + debug(2, "elfloader: Setting %p to %p to 0 for bss", baseAddress + phdr->p_filesz, + baseAddress + phdr->p_memsz); + memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); + } + + debug(2, "elfloader: Reading the segment into memory"); + + // Read the segment into memory + if (!_file->seek(phdr->p_offset, SEEK_SET) || + _file->read(baseAddress, phdr->p_filesz) != phdr->p_filesz) { + warning("elfloader: Segment load failed."); + return false; + } + + debug(2, "elfloader: Segment has been read into memory"); + + return true; +} + +// Unload all objects from memory +void MIPSDLObject::unload() { + DLObject::unload(); + freeShortsSegment(); +} + +void MIPSDLObject::freeShortsSegment() { + if (_shortsSegment) { + ShortsMan.deleteSegment(_shortsSegment); + _shortsSegment = 0; + } +} + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) */ + diff --git a/backends/plugins/elf/mips-loader.h b/backends/plugins/elf/mips-loader.h new file mode 100644 index 0000000000..23bd5980c8 --- /dev/null +++ b/backends/plugins/elf/mips-loader.h @@ -0,0 +1,64 @@ + +/* 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_PLUGINS_MIPS_LOADER_H +#define BACKENDS_PLUGINS_MIPS_LOADER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) + +#include "backends/plugins/elf/elf-loader.h" +#include "backends/plugins/elf/shorts-segment-manager.h" + +class MIPSDLObject : public DLObject { +protected: + ShortSegmentManager::Segment *_shortsSegment; // For assigning shorts ranges + uint32 _gpVal; // Value of Global Pointer + + virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment); + virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); + virtual void relocateSymbols(ptrdiff_t offset); + virtual bool loadSegment(Elf32_Phdr *phdr); + virtual void unload(); + + void freeShortsSegment(); + +public: + MIPSDLObject() : + DLObject() { + _shortsSegment = NULL; + _gpVal = 0; + } + ~MIPSDLObject() { + freeShortsSegment(); + } +}; + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) */ + +#endif /* BACKENDS_PLUGINS_MIPS_LOADER_H */ + diff --git a/backends/platform/psp/plugin.syms b/backends/plugins/elf/plugin.syms index 24ee1a19dc..70465ae976 100644 --- a/backends/platform/psp/plugin.syms +++ b/backends/plugins/elf/plugin.syms @@ -1,3 +1,4 @@ +PLUGIN_getBuildDate PLUGIN_getVersion PLUGIN_getType PLUGIN_getTypeVersion diff --git a/backends/plugins/elf/ppc-loader.cpp b/backends/plugins/elf/ppc-loader.cpp new file mode 100644 index 0000000000..ec6d442876 --- /dev/null +++ b/backends/plugins/elf/ppc-loader.cpp @@ -0,0 +1,129 @@ +/* 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/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET) + +#include "backends/plugins/elf/elf-loader.h" +#include "backends/plugins/elf/ppc-loader.h" + +#include "common/debug.h" + +bool PPCDLObject::relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment) { + Elf32_Rela *rel = NULL; + + if (!(rel = (Elf32_Rela *)malloc(size))) { + warning("elfloader: Out of memory."); + return false; + } + + if (!_file->seek(offset, SEEK_SET) || _file->read(rel, size) != size) { + warning("elfloader: Relocation table load failed."); + free(rel); + return false; + } + + uint32 cnt = size / sizeof(*rel); + + debug(2, "elfloader: Loaded relocation table. %d entries. base address=%p", cnt, relSegment); + + uint32 *src; + uint32 value; + + for (uint32 i = 0; i < cnt; i++) { + // Get the symbol this relocation entry is referring to + Elf32_Sym *sym = _symtab + (REL_INDEX(rel[i].r_info)); + + // Get the target instruction in the code + src = (uint32 *)((char *)relSegment + rel[i].r_offset - _segmentVMA); + value = sym->st_value + rel[i].r_addend; + + //debug(8, "elfloader: i=%05d %p +0x%04x: (0x%08x) 0x%08x ", i, src, rel[i].r_addend, sym->st_value, *src); + + switch (REL_TYPE(rel[i].r_info)) { + case R_PPC_ADDR32: + *src = value; + debug(8, "elfloader: R_PPC_ADDR32 -> 0x%08x", *src); + break; + case R_PPC_ADDR16_LO: + *(uint16 *)src = value; + debug(8, "elfloader: R_PPC_ADDR16_LO -> 0x%08x", *src); + break; + case R_PPC_ADDR16_HI: + *(uint16 *)src = value >> 16; + debug(8, "elfloader: R_PPC_ADDR16_HA -> 0x%08x", *src); + break; + case R_PPC_ADDR16_HA: + *(uint16 *)src = (value + 0x8000) >> 16; + debug(8, "elfloader: R_PPC_ADDR16_HA -> 0x%08x", *src); + break; + case R_PPC_REL24: + *src = (*src & ~0x03fffffc) | ((value - (uint32)src) & 0x03fffffc); + debug(8, "elfloader: R_PPC_REL24 -> 0x%08x", *src); + break; + case R_PPC_REL32: + *src = value - (uint32)src; + debug(8, "elfloader: R_PPC_REL32 -> 0x%08x", *src); + break; + default: + warning("elfloader: Unknown relocation type %d", REL_TYPE(rel[i].r_info)); + free(rel); + return false; + } + } + + free(rel); + return true; +} + +bool PPCDLObject::relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + for (uint32 i = 0; i < ehdr->e_shnum; i++) { + Elf32_Shdr *curShdr = &(shdr[i]); + + if ((curShdr->sh_type == SHT_REL) && + curShdr->sh_entsize == sizeof(Elf32_Rel) && + int32(curShdr->sh_link) == _symtab_sect && + curShdr->sh_info < ehdr->e_shnum && + (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { + warning("elfloader: REL entries not supported!"); + return false; + } + + if ((curShdr->sh_type == SHT_RELA) && + curShdr->sh_entsize == sizeof(Elf32_Rela) && + int32(curShdr->sh_link) == _symtab_sect && + curShdr->sh_info < ehdr->e_shnum && + (shdr[curShdr->sh_info].sh_flags & SHF_ALLOC)) { + if (!relocate(curShdr->sh_offset, curShdr->sh_size, _segment)) + return false; + } + } + + return true; +} + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET) */ + diff --git a/backends/plugins/elf/ppc-loader.h b/backends/plugins/elf/ppc-loader.h new file mode 100644 index 0000000000..edf2b33965 --- /dev/null +++ b/backends/plugins/elf/ppc-loader.h @@ -0,0 +1,44 @@ +/* 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_PLUGINS_PPC_LOADER_H +#define BACKENDS_PLUGINS_PPC_LOADER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET) + +#include "backends/plugins/elf/elf-loader.h" + +class PPCDLObject : public DLObject { +protected: + virtual bool relocate(Elf32_Off offset, Elf32_Word size, byte *relSegment); + virtual bool relocateRels(Elf32_Ehdr *ehdr, Elf32_Shdr *shdr); +}; + +#endif /* defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(PPC_TARGET) */ + +#endif /* BACKENDS_PLUGINS_PPC_LOADER_H */ + diff --git a/backends/plugins/elf/shorts-segment-manager.cpp b/backends/plugins/elf/shorts-segment-manager.cpp new file mode 100644 index 0000000000..99a765287b --- /dev/null +++ b/backends/plugins/elf/shorts-segment-manager.cpp @@ -0,0 +1,90 @@ +/* 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/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) + +#include "backends/plugins/elf/shorts-segment-manager.h" + +#include "common/debug.h" +#include "common/textconsole.h" + +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 + +ShortSegmentManager::ShortSegmentManager() { + _shortsStart = &__plugin_hole_start ; //shorts segment begins at the plugin hole we made when linking + _shortsEnd = &__plugin_hole_end; //and ends at the end of that hole. +} + +ShortSegmentManager::Segment *ShortSegmentManager::newSegment(uint32 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 (uint32(currAddress) - uint32(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) { + warning("elfloader: No space in shorts segment for %x bytes. Last address is %p, max address is %p.", + size, lastAddress, _shortsEnd); + return 0; + } + + 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); + + debug(2, "elfloader: Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.", + size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress); + + return seg; +} + +void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) { + debug(2, "elfloader: Deleting shorts segment from %p to %p.", seg->getStart(), seg->getEnd()); + _list.remove(seg); + delete seg; +} + +#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) + + diff --git a/backends/plugins/elf/shorts-segment-manager.h b/backends/plugins/elf/shorts-segment-manager.h new file mode 100644 index 0000000000..219648d91d --- /dev/null +++ b/backends/plugins/elf/shorts-segment-manager.h @@ -0,0 +1,117 @@ +/* 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 SHORTS_SEGMENT_MANAGER_H +#define SHORTS_SEGMENT_MANAGER_H + +#include "common/scummsys.h" + +#if defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) + +#include "backends/plugins/elf/elf32.h" + +#include "common/singleton.h" +#include "common/list.h" + +#define ShortsMan ShortSegmentManager::instance() + +/** + * ShortSegmentManager + * + * Since MIPS is limited to 32 bits per instruction, loading data that's further away than 16 bits + * takes several instructions. Thus, small global data (which is likely to be accessed a lot from + * multiple locations) is often put into a GP-relative area (GP standing for the global pointer register) + * in MIPS processors. This class manages these segments of small global data, and is used by the + * member functions of MIPSDLObject, which query in information from this manager in order to deal with + * this segment during the loading/unloading of plugins. + * + * Since there's no true dynamic linker to change the GP register between plugins and the main engine, + * custom ld linker scripts for both the main executable and the plugins ensure the GP-area is in the + * same place for both. The ShortSegmentManager accesses this place via the symbols __plugin_hole_start + * and __plugin_hole_end, which are defined in those custom ld linker scripts. + */ +class ShortSegmentManager : public Common::Singleton<ShortSegmentManager> { +private: + char *_shortsStart; + char *_shortsEnd; + +public: + char *getShortsStart() { + return _shortsStart; + } + + // Returns whether or not an absolute address is in the GP-relative section. + bool inGeneralSegment(char *addr) { + return (addr >= _shortsStart && addr < _shortsEnd); + } + + class Segment { + private: + friend class ShortSegmentManager; + Segment(char *start, uint32 size, char *origAddr) : + _startAddress(start), + _size(size), + _origAddress(origAddr) { + } + + virtual ~Segment() { + } + + char *_startAddress; // Start of shorts segment in memory + uint32 _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 (addr >= _startAddress && addr <= _startAddress + _size); + } + }; + + Segment *newSegment(uint32 size, char *origAddr); + void deleteSegment(Segment *); + +private: + ShortSegmentManager(); + friend class Common::Singleton<ShortSegmentManager>; + Common::List<Segment *> _list; + char *_highestAddress; +}; + +#endif // defined(DYNAMIC_MODULES) && defined(USE_ELF_LOADER) && defined(MIPS_TARGET) + +#endif /* SHORTS_SEGMENT_MANAGER_H */ + diff --git a/backends/plugins/elf/version.cpp b/backends/plugins/elf/version.cpp new file mode 100644 index 0000000000..0277c6ae1c --- /dev/null +++ b/backends/plugins/elf/version.cpp @@ -0,0 +1,32 @@ +/* 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 "backends/plugins/elf/version.h" + +#ifdef USE_ELF_LOADER +const char *gScummVMPluginBuildDate __attribute__((visibility("hidden"))) = + __DATE__ " " __TIME__ ; +#endif + diff --git a/backends/plugins/elf/version.h b/backends/plugins/elf/version.h new file mode 100644 index 0000000000..726204aeb7 --- /dev/null +++ b/backends/plugins/elf/version.h @@ -0,0 +1,35 @@ +/* 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_PLUGINS_ELF_VERSION_H +#define BACKENDS_PLUGINS_ELF_VERSION_H + +#include "common/scummsys.h" + +#ifdef USE_ELF_LOADER +extern const char *gScummVMPluginBuildDate; +#endif + +#endif + diff --git a/backends/plugins/ps2/main_prog.ld b/backends/plugins/ps2/main_prog.ld new file mode 100644 index 0000000000..9dba69c50e --- /dev/null +++ b/backends/plugins/ps2/main_prog.ld @@ -0,0 +1,99 @@ +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) + } + + /*This "plugin hole" is so the plugins can all have global small data + in the same place.*/ + __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/plugins/ps2/plugin.ld b/backends/plugins/ps2/plugin.ld new file mode 100644 index 0000000000..45efe4db7a --- /dev/null +++ b/backends/plugins/ps2/plugin.ld @@ -0,0 +1,94 @@ +/* PHDRS specifies ELF Program Headers (or segments) to the plugin linker */ +PHDRS { + plugin PT_LOAD ; /* Specifies that the plugin segment should be loaded from file */ + shorts PT_LOAD ; /* Specifies that the shorts segment should be loaded from file */ +} + +SECTIONS { + .text 0: { + _ftext = . ; + *(.text) + *(.text.*) + *(.gnu.linkonce.t*) + KEEP(*(.init)) + KEEP(*(.fini)) + QUAD(0) + } : plugin /*The ": plugin" tells the linker to assign this and + the following sections to the "plugin" segment*/ + PROVIDE(_etext = .); + PROVIDE(etext = .); + + .reginfo : { *(.reginfo) } + + /* Global/static constructors and deconstructors. */ + .ctors ALIGN(16): { + ___plugin_ctors = .; + KEEP(*(SORT(.ctors.*))) + KEEP(*(.ctors)) + ___plugin_ctors_end = .; + } + .dtors ALIGN(16): { + ___plugin_dtors = .; + KEEP(*(SORT(.dtors.*))) + KEEP(*(.dtors)) + ___plugin_dtors_end = .; + } + + /* 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) } + + .bss ALIGN(128) : { + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + } + _end_bss = .; + + _end = . ; + PROVIDE(end = .); + + /* Symbols needed by crt0.s. */ + PROVIDE(_heap_size = -1); + PROVIDE(_stack = -1); + PROVIDE(_stack_size = 128 * 1024); + + /*We assign the output location counter to the plugin hole made + in main_prog.ld, then assign the small data sections to the shorts segment*/ + . = __plugin_hole_start; + .lit4 ALIGN(128): { *(.lit4) } : shorts + .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) + } +} diff --git a/backends/plugins/ps2/ps2-provider.cpp b/backends/plugins/ps2/ps2-provider.cpp new file mode 100644 index 0000000000..37bdff0525 --- /dev/null +++ b/backends/plugins/ps2/ps2-provider.cpp @@ -0,0 +1,45 @@ +/* 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/elf/mips-loader.h" + +class PS2DLObject : public MIPSDLObject { +protected: + + virtual void flushDataCache(void *, uint32) const { + FlushCache(0); + FlushCache(2); + } +}; + +Plugin *PS2PluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin<PS2DLObject>(node.getPath()); +} + +#endif // defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__) + diff --git a/backends/plugins/ps2/ps2-provider.h b/backends/plugins/ps2/ps2-provider.h new file mode 100644 index 0000000000..3d4b4b0128 --- /dev/null +++ b/backends/plugins/ps2/ps2-provider.h @@ -0,0 +1,41 @@ +/* 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__) + +#ifndef BACKENDS_PLUGINS_PS2_PROVIDER_H +#define BACKENDS_PLUGINS_PS2_PROVIDER_H + +#include "backends/plugins/elf/elf-provider.h" + +class PS2PluginProvider : public ELFPluginProvider { +public: + Plugin *createPlugin(const Common::FSNode &node) const; +}; + +#endif // BACKENDS_PLUGINS_PS2_PROVIDER_H + +#endif // defined(DYNAMIC_MODULES) && defined(__PLAYSTATION2__) + diff --git a/backends/platform/psp/main_prog.ld b/backends/plugins/psp/main_prog.ld index 4216e7f0ab..4216e7f0ab 100644 --- a/backends/platform/psp/main_prog.ld +++ b/backends/plugins/psp/main_prog.ld diff --git a/backends/platform/psp/plugin.ld b/backends/plugins/psp/plugin.ld index 7534c15290..a4456d199d 100644 --- a/backends/platform/psp/plugin.ld +++ b/backends/plugins/psp/plugin.ld @@ -1,11 +1,12 @@ -OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips", - "elf32-littlemips") +OUTPUT_FORMAT("elf32-littlemips", "elf32-bigmips", "elf32-littlemips") OUTPUT_ARCH(mips:allegrex) + PHDRS { plugin PT_LOAD ; shorts PT_LOAD ; } + /* Do we need any of these for elf? __DYNAMIC = 0; */ SECTIONS @@ -208,7 +209,7 @@ SECTIONS .debug_varnames 0 : { *(.debug_varnames) } /DISCARD/ : { *(.comment) *(.pdr) } /DISCARD/ : { *(.note.GNU-stack) } - + . = __plugin_hole_start; .got : { *(.got.plt) *(.got) } : shorts /* We want the small data sections together, so single-instruction offsets @@ -234,6 +235,4 @@ SECTIONS PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); } - - } diff --git a/backends/plugins/psp/psp-provider.cpp b/backends/plugins/psp/psp-provider.cpp index 5760424cbf..87e4428024 100644 --- a/backends/plugins/psp/psp-provider.cpp +++ b/backends/plugins/psp/psp-provider.cpp @@ -25,86 +25,23 @@ #if defined(DYNAMIC_MODULES) && defined(__PSP__) -#include "backends/plugins/psp/psp-provider.h" -#include "backends/plugins/dynamic-plugin.h" -#include "common/fs.h" - -#include "backends/platform/psp/psploader.h" - -#include "backends/platform/psp/trace.h" +#include <psputils.h> +#include <psputilsforkernel.h> +#include "backends/plugins/psp/psp-provider.h" +#include "backends/plugins/elf/mips-loader.h" -class PSPPlugin : public DynamicPlugin { +class PSPDLObject : public MIPSDLObject { 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: - PSPPlugin(const Common::String &filename) - : _dlHandle(0), _filename(filename) {} - - ~PSPPlugin() { - 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; - } + virtual void flushDataCache(void *ptr, uint32 len) const { + sceKernelDcacheWritebackRange(ptr, len); + sceKernelIcacheInvalidateRange(ptr, len); } }; - -Plugin* PSPPluginProvider::createPlugin(const Common::FSNode &node) const { - return new PSPPlugin(node.getPath()); -} - -bool PSPPluginProvider::isPluginFilename(const Common::FSNode &node) const { - // Check the plugin suffix - Common::String filename = node.getName(); - PSP_DEBUG_PRINT("Testing name %s", filename.c_str()); - if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg")) { - PSP_DEBUG_PRINT(" fail.\n"); - return false; - } - - PSP_DEBUG_PRINT(" success!\n"); - return true; +Plugin *PSPPluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin<PSPDLObject>(node.getPath()); } #endif // defined(DYNAMIC_MODULES) && defined(__PSP__) + diff --git a/backends/plugins/psp/psp-provider.h b/backends/plugins/psp/psp-provider.h index d6c44c5a85..39e0d32caa 100644 --- a/backends/plugins/psp/psp-provider.h +++ b/backends/plugins/psp/psp-provider.h @@ -18,26 +18,24 @@ * 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$ + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/branches/gsoc2010-plugins/backends/plugins/ds/ds-provider.h $ + * $Id: ds-provider.h 52112 2010-08-16 08:41:04Z toneman1138 $ * */ -#ifndef BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H -#define BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H - -#include "base/plugins.h" - #if defined(DYNAMIC_MODULES) && defined(__PSP__) -class PSPPluginProvider : public FilePluginProvider { -protected: - Plugin* createPlugin(const Common::FSNode &node) const; +#ifndef BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H +#define BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H - bool isPluginFilename(const Common::FSNode &node) const; +#include "backends/plugins/elf/elf-provider.h" +class PSPPluginProvider : public ELFPluginProvider { +public: + Plugin *createPlugin(const Common::FSNode &node) const; }; +#endif // BACKENDS_PLUGINS_PSP_PROVIDER_H + #endif // defined(DYNAMIC_MODULES) && defined(__PSP__) -#endif /* BACKENDS_PLUGINS_PSP_PSP_PROVIDER_H */ diff --git a/backends/plugins/sdl/sdl-provider.cpp b/backends/plugins/sdl/sdl-provider.cpp index be04b5a1eb..6f8ca594f6 100644 --- a/backends/plugins/sdl/sdl-provider.cpp +++ b/backends/plugins/sdl/sdl-provider.cpp @@ -25,6 +25,9 @@ #if defined(DYNAMIC_MODULES) && defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL + #include "backends/plugins/sdl/sdl-provider.h" #include "backends/plugins/dynamic-plugin.h" #include "common/fs.h" diff --git a/backends/plugins/wii/plugin.ld b/backends/plugins/wii/plugin.ld new file mode 100644 index 0000000000..61b90d3394 --- /dev/null +++ b/backends/plugins/wii/plugin.ld @@ -0,0 +1,263 @@ +/* + * Linkscript for Wii + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc"); +OUTPUT_ARCH(powerpc:common); + +PHDRS +{ + plugin PT_LOAD FLAGS(7); +} + +SECTIONS +{ + . = 0x81000000; + + /* Program */ + .init : + { + KEEP (*crt0.o(*.init)) + KEEP (*(.init)) + } :plugin = 0 + .plt : { *(.plt) } + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rela.got1 : { *(.rela.got1) } + .rela.got2 : { *(.rela.got2) } + .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } + .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } + .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } + .rela.sbss : { *(.rela.sbss .rela.sbss.* .rel.gnu.linkonce.sb.*) } + .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } + .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } + .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + .text : + { + *(.text) + *(.text.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t.*) + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + } = 0 + + .fini : + { + KEEP (*(.fini)) + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + } = 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.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + /* 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 : + { + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + } + + .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) } + .fixup : { *(.fixup) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + + .ctors : + { + ___plugin_ctors = .; + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + ___plugin_ctors_end = .; + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + } + + .dtors : + { + ___plugin_dtors = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + ___plugin_dtors_end = .; + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + } + + .jcr : { KEEP (*(.jcr)) } + .got : { *(.got.plt) *(.got) } + + + /* 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.*) + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + } + + _edata = .; + PROVIDE (edata = .); + + .sbss : + { + __sbss_start = .; + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + . = ALIGN(32); /* REQUIRED. LD is flaky without it. */ + __sbss_end = .; + } + + .bss : + { + __bss_start = .; + PROVIDE (__bss_start = .); + *(.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); + + PROVIDE (__bss_end = .); + __bss_end = .; + } + + _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) } + .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) } + /* These must appear regardless of . */ +} + +__isIPL = 0; +__stack_addr = (__bss_start + SIZEOF(.bss) + 0x20000 + 7) & (-8); +__stack_end = (__bss_start + SIZEOF(.bss)); +__intrstack_addr = (__stack_addr + 0x4000); +__intrstack_end = (__stack_addr); +__Arena1Lo = (__intrstack_addr + 31) & (-32); +__Arena1Hi = (0x816ffff0); +__Arena2Lo = (0x90002000); +__Arena2Hi = (0x933E0000); + +__gxregs = (__Arena1Hi + 31) & (-32); +__ipcbufferLo = (0x933e0000); +__ipcbufferHi = (0x93400000); + +/* for backward compatibility with old crt0 */ +PROVIDE (__stack = (0x816ffff0)); + +PROVIDE(__isIPL = __isIPL); +PROVIDE(__stack_addr = __stack_addr); +PROVIDE(__stack_end = __stack_end); +PROVIDE(__intrstack_addr = __intrstack_addr); +PROVIDE(__intrstack_end = __intrstack_end); +PROVIDE(__Arena1Lo = __Arena1Lo); +PROVIDE(__Arena1Hi = __Arena1Hi); +PROVIDE(__Arena2Lo = __Arena2Lo); +PROVIDE(__Arena2Hi = __Arena2Hi); +PROVIDE(__ipcbufferLo = __ipcbufferLo); +PROVIDE(__ipcbufferHi = __ipcbufferHi); +PROVIDE(__gxregs = __gxregs); diff --git a/backends/plugins/wii/wii-provider.cpp b/backends/plugins/wii/wii-provider.cpp new file mode 100644 index 0000000000..b05bc59432 --- /dev/null +++ b/backends/plugins/wii/wii-provider.cpp @@ -0,0 +1,47 @@ +/* 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(__WII__) + +#include <malloc.h> +#include <ogc/cache.h> + +#include "backends/plugins/wii/wii-provider.h" +#include "backends/plugins/elf/ppc-loader.h" + +class WiiDLObject : public PPCDLObject { +protected: + virtual void flushDataCache(void *ptr, uint32 len) const { + DCFlushRange(ptr, len); + ICInvalidateRange(ptr, len); + } +}; + +Plugin *WiiPluginProvider::createPlugin(const Common::FSNode &node) const { + return new TemplatedELFPlugin<WiiDLObject>(node.getPath()); +} + +#endif // defined(DYNAMIC_MODULES) && defined(__WII__) + diff --git a/backends/plugins/wii/wii-provider.h b/backends/plugins/wii/wii-provider.h new file mode 100644 index 0000000000..4ec771490d --- /dev/null +++ b/backends/plugins/wii/wii-provider.h @@ -0,0 +1,41 @@ +/* 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(__WII__) + +#ifndef BACKENDS_PLUGINS_WII_PROVIDER_H +#define BACKENDS_PLUGINS_WII_PROVIDER_H + +#include "backends/plugins/elf/elf-provider.h" + +class WiiPluginProvider : public ELFPluginProvider { +public: + Plugin *createPlugin(const Common::FSNode &node) const; +}; + +#endif // BACKENDS_PLUGINS_WII_PROVIDER_H + +#endif // defined(DYNAMIC_MODULES) && defined(__WII__) + diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp index 1ab898d2d6..c88f36f5cc 100644 --- a/backends/saves/default/default-saves.cpp +++ b/backends/saves/default/default-saves.cpp @@ -34,8 +34,9 @@ #include "common/config-manager.h" #include "common/zlib.h" +#ifndef _WIN32_WCE #include <errno.h> // for removeSavefile() - +#endif DefaultSaveFileManager::DefaultSaveFileManager() { } diff --git a/backends/timer/default/default-timer.h b/backends/timer/default/default-timer.h index 778c69b32d..e7ac3d122f 100644 --- a/backends/timer/default/default-timer.h +++ b/backends/timer/default/default-timer.h @@ -40,8 +40,7 @@ private: public: DefaultTimerManager(); - virtual ~DefaultTimerManager(); - + ~DefaultTimerManager(); bool installTimerProc(TimerProc proc, int32 interval, void *refCon); void removeTimerProc(TimerProc proc); diff --git a/backends/timer/sdl/sdl-timer.cpp b/backends/timer/sdl/sdl-timer.cpp index 4957b4bc1c..83b2cff3eb 100644 --- a/backends/timer/sdl/sdl-timer.cpp +++ b/backends/timer/sdl/sdl-timer.cpp @@ -26,6 +26,9 @@ #if defined(SDL_BACKEND) +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_EXCEPTION_FILE + #include "backends/timer/sdl/sdl-timer.h" static Uint32 timer_handler(Uint32 interval, void *param) { diff --git a/backends/vkeybd/virtual-keyboard-gui.cpp b/backends/vkeybd/virtual-keyboard-gui.cpp index ad9dd9f638..8bfadfd88c 100644 --- a/backends/vkeybd/virtual-keyboard-gui.cpp +++ b/backends/vkeybd/virtual-keyboard-gui.cpp @@ -29,7 +29,7 @@ #include "graphics/cursorman.h" #include "graphics/fontman.h" -#include "gui/GuiManager.h" +#include "gui/gui-manager.h" namespace Common { diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp index 6a644e0cdf..dd11866262 100644 --- a/backends/vkeybd/virtual-keyboard-parser.cpp +++ b/backends/vkeybd/virtual-keyboard-parser.cpp @@ -270,7 +270,7 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) { int r, g, b; if (node->values.contains("transparent_color")) { - if (!parseIntegerKey(node->values["transparent_color"].c_str(), 3, &r, &g, &b)) + if (!parseIntegerKey(node->values["transparent_color"], 3, &r, &g, &b)) return parserError("Could not parse color value"); } else { // default to purple @@ -281,7 +281,7 @@ bool VirtualKeyboardParser::parserCallback_layout(ParserNode *node) { _mode->transparentColor = format.RGBToColor(r, g, b); if (node->values.contains("display_font_color")) { - if (!parseIntegerKey(node->values["display_font_color"].c_str(), 3, &r, &g, &b)) + if (!parseIntegerKey(node->values["display_font_color"], 3, &r, &g, &b)) return parserError("Could not parse color value"); } else { r = g = b = 0; // default to black @@ -336,7 +336,7 @@ byte VirtualKeyboardParser::parseFlags(const String& flags) { bool VirtualKeyboardParser::parseRect(Rect &rect, const String& coords) { int x1, y1, x2, y2; - if (!parseIntegerKey(coords.c_str(), 4, &x1, &y1, &x2, &y2)) + if (!parseIntegerKey(coords, 4, &x1, &y1, &x2, &y2)) return parserError("Invalid coords for rect area"); rect.left = x1; rect.top = y1; |