mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-03 01:15:58 +00:00
updated my outdate copy of trunk, added couple of more tests in gfxtests
svn-id: r49510
This commit is contained in:
commit
207a5e0779
3
AUTHORS
3
AUTHORS
@ -166,6 +166,9 @@ ScummVM Team
|
|||||||
|
|
||||||
Backend Teams
|
Backend Teams
|
||||||
-------------
|
-------------
|
||||||
|
Android:
|
||||||
|
Angus Lees
|
||||||
|
|
||||||
Dreamcast:
|
Dreamcast:
|
||||||
Marcus Comstedt
|
Marcus Comstedt
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ Martin Kiewitz
|
|||||||
Pawel Kolodziejski
|
Pawel Kolodziejski
|
||||||
Mutwin Kraus
|
Mutwin Kraus
|
||||||
Andrew Kurushin
|
Andrew Kurushin
|
||||||
|
Angus Lees
|
||||||
Claudio Matsuoka
|
Claudio Matsuoka
|
||||||
Thomas Mayer
|
Thomas Mayer
|
||||||
Neil Millstone
|
Neil Millstone
|
||||||
|
8
NEWS
8
NEWS
@ -2,12 +2,18 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
|
|||||||
http://scummvm.svn.sourceforge.net/viewvc/scummvm/?view=log
|
http://scummvm.svn.sourceforge.net/viewvc/scummvm/?view=log
|
||||||
|
|
||||||
1.2.0 (????-??-??)
|
1.2.0 (????-??-??)
|
||||||
|
New Ports:
|
||||||
|
- Added Android port.
|
||||||
|
|
||||||
PSP port:
|
PSP port:
|
||||||
- Switched to new backend design which fixes minor graphical issues,
|
- Switched to new backend design which fixes minor graphical issues,
|
||||||
speeds things up, and provides 16-bit support.
|
speeds things up, and provides 16-bit support.
|
||||||
|
- Enabled playback of MP3 files using the hardware decoder (ME). This means that
|
||||||
|
the port is now optimized for MP3 playback (as opposed to OGG).
|
||||||
|
|
||||||
General:
|
General:
|
||||||
- Switched to the "fast" DOSBox OPL emulator.
|
- Switched to the "fast" DOSBox OPL emulator.
|
||||||
|
- Fixed a crash in the rjp1 player code affecting the FOTAQ Amiga version.
|
||||||
|
|
||||||
1.1.2 (????-??-??)
|
1.1.2 (????-??-??)
|
||||||
Broken Sword 2
|
Broken Sword 2
|
||||||
@ -17,7 +23,7 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
|
|||||||
|
|
||||||
1.1.1 (2010-05-02)
|
1.1.1 (2010-05-02)
|
||||||
New Ports:
|
New Ports:
|
||||||
- Added Nintendo 64 Port. (Actually added in 1.1.0, but forgot to mention it. oops)
|
- Added Nintendo 64 port. (Actually added in 1.1.0, but forgot to mention it. oops)
|
||||||
|
|
||||||
General:
|
General:
|
||||||
- Fixed several minor bugs here and there.
|
- Fixed several minor bugs here and there.
|
||||||
|
21
README
21
README
@ -81,9 +81,10 @@ You can find a thorough list with details on which games are supported
|
|||||||
and how well on the compatibility page. ScummVM is continually
|
and how well on the compatibility page. ScummVM is continually
|
||||||
improving, so check back often.
|
improving, so check back often.
|
||||||
|
|
||||||
Among the systems on which you can play those games are Windows, Linux,
|
Among the systems on which you can play those games are regular desktop
|
||||||
Mac OS X, Dreamcast, PocketPC, PalmOS, AmigaOS, BeOS, OS/2, PSP, PS2,
|
computers (running Windows, Linux, Mac OS X, ...), game consoles
|
||||||
SymbianOS/EPOC, iPhone and many more.
|
(Dreamcast, Nintendo DS & Wii, PS2, PSP, ...), smartphones (Android,
|
||||||
|
iPhone, PocketPC, Symbian ...) and more.
|
||||||
|
|
||||||
At this time ScummVM should be considered beta software, and is still
|
At this time ScummVM should be considered beta software, and is still
|
||||||
under heavy development. Be aware that whilst we attempt to make sure
|
under heavy development. Be aware that whilst we attempt to make sure
|
||||||
@ -843,21 +844,25 @@ contact us!
|
|||||||
|
|
||||||
Supported platforms include (but are not limited to):
|
Supported platforms include (but are not limited to):
|
||||||
|
|
||||||
UNIX (Linux, Solaris, IRIX, *BSD)
|
UNIX (Linux, Solaris, IRIX, *BSD, ...)
|
||||||
Windows
|
Windows
|
||||||
Windows CE and Windows Mobile (including Smartphones and PocketPCs)
|
Windows CE and Windows Mobile (including Smartphones and PocketPCs)
|
||||||
Mac OS X
|
Mac OS X
|
||||||
AmigaOS
|
AmigaOS
|
||||||
|
Android
|
||||||
BeOS
|
BeOS
|
||||||
Dreamcast
|
Dreamcast
|
||||||
iPhone (also includes the iPod Touch)
|
GP2x
|
||||||
|
iPhone (also includes iPod Touch and iPad)
|
||||||
|
Maemo (Nokia Internet tablets 770, N800, N810, N900)
|
||||||
|
Nintendo 64
|
||||||
Nintendo DS
|
Nintendo DS
|
||||||
|
Nintendo Wii
|
||||||
|
OS/2
|
||||||
PalmOS
|
PalmOS
|
||||||
PlayStation 2
|
PlayStation 2
|
||||||
PlayStation Portable
|
PlayStation Portable
|
||||||
RISC OS
|
|
||||||
Symbian
|
Symbian
|
||||||
Maemo (Nokia Internet tablets 770, N800, N810, N900)
|
|
||||||
|
|
||||||
The Dreamcast port does not support The Curse of Monkey Island, nor The
|
The Dreamcast port does not support The Curse of Monkey Island, nor The
|
||||||
Dig. The PalmOS port does not support The Curse of Monkey Island,
|
Dig. The PalmOS port does not support The Curse of Monkey Island,
|
||||||
@ -865,6 +870,8 @@ Beneath a Steel Sky, nor either Simon the Sorcerer 1 or 2. The Dig will
|
|||||||
only work on some Palm devices (those with a large dynamic heap). The
|
only work on some Palm devices (those with a large dynamic heap). The
|
||||||
Nintendo DS port does not support Full Throttle, The Dig, or The Curse
|
Nintendo DS port does not support Full Throttle, The Dig, or The Curse
|
||||||
of Monkey Island.
|
of Monkey Island.
|
||||||
|
For more platform specific limitations, please refer to our Wiki:
|
||||||
|
http://wiki.scummvm.org/index.php/Platforms
|
||||||
|
|
||||||
In the Macintosh port, the right mouse button is emulated via Cmd-Click
|
In the Macintosh port, the right mouse button is emulated via Cmd-Click
|
||||||
(that is, you click the mouse button while holding the
|
(that is, you click the mouse button while holding the
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
*/
|
*/
|
||||||
#ifdef __PSP__
|
#ifdef __PSP__
|
||||||
|
|
||||||
|
#include <pspiofilemgr_stat.h>
|
||||||
|
#include <pspiofilemgr.h>
|
||||||
#include <SDL/SDL_thread.h>
|
#include <SDL/SDL_thread.h>
|
||||||
#include <SDL/SDL_mutex.h>
|
#include <SDL/SDL_mutex.h>
|
||||||
|
|
||||||
@ -32,28 +34,48 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
//#define __PSP_PRINT_TO_FILE__
|
#define MIN2(a,b) ((a < b) ? a : b)
|
||||||
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
|
#define MIN3(a,b,c) ( (a < b) ? (a < c ? a : c) : (b < c ? b : c) )
|
||||||
|
|
||||||
|
//#define __PSP_PRINT_TO_FILE__ /* For debugging suspend stuff, we have no screen output */
|
||||||
|
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
|
||||||
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
|
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
|
||||||
|
|
||||||
#include "backends/platform/psp/trace.h"
|
#include "backends/platform/psp/trace.h"
|
||||||
|
|
||||||
|
//#define DEBUG_BUFFERS /* to see the contents of the buffers being read */
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUFFERS
|
||||||
|
void printBuffer(byte *ptr, uint32 len) {
|
||||||
|
uint32 printLen = len <= 10 ? len : 10;
|
||||||
|
|
||||||
|
for (int i = 0; i < printLen; i++) {
|
||||||
|
PSP_INFO_PRINT("%x ", ptr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 10) {
|
||||||
|
PSP_INFO_PRINT("... ");
|
||||||
|
for (int i = len - 10; i < len; i++)
|
||||||
|
PSP_INFO_PRINT("%x ", ptr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
PSP_INFO_PRINT("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
|
PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
|
||||||
: StdioStream((void *)1), _path(path), _writeMode(writeMode) {
|
: StdioStream((void *)1), _path(path), _writeMode(writeMode),
|
||||||
|
_ferror(false), _pos(0),
|
||||||
|
_physicalPos(0), _fileSize(0), _inCache(false), _eos(false),
|
||||||
|
_cacheStartOffset(-1), _cache(0),
|
||||||
|
_errorSuspend(0), _errorSource(0),
|
||||||
|
_errorPos(0), _errorHandle(0), _suspendCount(0) {
|
||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
assert(!path.empty());
|
// assert(!path.empty()); // do we need this?
|
||||||
|
|
||||||
_handle = (void *)0; // Need to do this since base class asserts not 0.
|
_handle = (void *)0; // Need to do this since base class asserts not 0.
|
||||||
_ferror = false;
|
|
||||||
_feof = false;
|
|
||||||
_pos = 0;
|
|
||||||
|
|
||||||
/* for error checking */
|
|
||||||
_errorSuspend = 0;
|
|
||||||
_errorSource = 0;
|
|
||||||
_errorPos = 0;
|
|
||||||
_errorHandle = 0;
|
|
||||||
_suspendCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PSPIoStream::~PSPIoStream() {
|
PSPIoStream::~PSPIoStream() {
|
||||||
@ -63,9 +85,12 @@ PSPIoStream::~PSPIoStream() {
|
|||||||
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
||||||
|
|
||||||
PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
|
PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended
|
||||||
// Must do this before fclose() or resume() will reopen.
|
// Must do this before fclose() or resume() will reopen.
|
||||||
|
|
||||||
fclose((FILE *)_handle); // We don't need a critical section(?). Worst case, the handle gets closed on its own
|
fclose((FILE *)_handle); // We don't need a critical section. Worst case, the handle gets closed on its own
|
||||||
|
|
||||||
|
if (_cache)
|
||||||
|
free(_cache);
|
||||||
|
|
||||||
PowerMan.endCriticalSection();
|
PowerMan.endCriticalSection();
|
||||||
}
|
}
|
||||||
@ -82,6 +107,17 @@ void *PSPIoStream::open() {
|
|||||||
|
|
||||||
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
|
_handle = fopen(_path.c_str(), _writeMode ? "wb" : "rb"); // open
|
||||||
|
|
||||||
|
if (_handle) {
|
||||||
|
// Get the file size. This way is much faster than going to the end of the file and back
|
||||||
|
SceIoStat stat;
|
||||||
|
sceIoGetstat(_path.c_str(), &stat);
|
||||||
|
_fileSize = *((uint32 *)(void *)&stat.st_size); // 4GB file is big enough for us
|
||||||
|
PSP_DEBUG_PRINT("%s filesize = %d\n", _path.c_str(), _fileSize);
|
||||||
|
|
||||||
|
// Allocate the cache
|
||||||
|
_cache = (char *)memalign(64, CACHE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
|
PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
|
||||||
|
|
||||||
PowerMan.endCriticalSection();
|
PowerMan.endCriticalSection();
|
||||||
@ -91,100 +127,183 @@ void *PSPIoStream::open() {
|
|||||||
|
|
||||||
bool PSPIoStream::err() const {
|
bool PSPIoStream::err() const {
|
||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
if (_ferror)
|
|
||||||
PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], _errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
|
if (_ferror) // We dump since no printing to screen with suspend
|
||||||
_ferror, _errorSource, _errorSuspend, _pos, _errorPos, _errorHandle, _suspendCount);
|
PSP_ERROR("mem_ferror[%d], source[%d], suspend error[%d], pos[%d], \
|
||||||
|
_errorPos[%d], _errorHandle[%p], suspendCount[%d]\n",
|
||||||
|
_ferror, _errorSource, _errorSuspend, _pos,
|
||||||
|
_errorPos, _errorHandle, _suspendCount);
|
||||||
|
|
||||||
return _ferror;
|
return _ferror;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PSPIoStream::clearErr() {
|
void PSPIoStream::clearErr() {
|
||||||
_ferror = false; // Remove regular error bit
|
_ferror = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PSPIoStream::eos() const {
|
bool PSPIoStream::eos() const {
|
||||||
return _feof;
|
return _eos;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 PSPIoStream::pos() const {
|
int32 PSPIoStream::pos() const {
|
||||||
return _pos;
|
return _pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32 PSPIoStream::size() const {
|
int32 PSPIoStream::size() const {
|
||||||
DEBUG_ENTER_FUNC();
|
return _fileSize;
|
||||||
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
|
||||||
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
|
||||||
|
|
||||||
fseek((FILE *)_handle, 0, SEEK_END);
|
|
||||||
int32 length = ftell((FILE *)_handle);
|
|
||||||
fseek((FILE *)_handle, _pos, SEEK_SET);
|
|
||||||
|
|
||||||
if (_pos < 0 || length < 0) { // Check for errors
|
|
||||||
_errorSource = 2;
|
|
||||||
PSP_ERROR("pos[%d] or length[%d] < 0!\n", _pos, length);
|
|
||||||
_ferror = true;
|
|
||||||
length = -1; // If our oldPos is bad, we want length to be bad too to signal
|
|
||||||
clearerr((FILE *)_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerMan.endCriticalSection();
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PSPIoStream::seek(int32 offs, int whence) {
|
bool PSPIoStream::seek(int32 offs, int whence) {
|
||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
|
PSP_DEBUG_PRINT_FUNC("offset[0x%x], whence[%d], _pos[0x%x], _physPos[0x%x]\n", offs, whence, _pos, _physicalPos);
|
||||||
// Check if we can access the file
|
_eos = false;
|
||||||
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
|
||||||
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
int32 posToSearchFor = 0;
|
||||||
|
switch (whence) {
|
||||||
int ret = fseek((FILE *)_handle, offs, whence);
|
case SEEK_CUR:
|
||||||
|
posToSearchFor = _pos;
|
||||||
if (ret != 0) {
|
break;
|
||||||
_ferror = true;
|
case SEEK_END:
|
||||||
PSP_ERROR("fseek returned with [%d], non-zero\n", ret);
|
posToSearchFor = _fileSize; // unsure. Does it take us here or to EOS - 1?
|
||||||
clearerr((FILE *)_handle);
|
break;
|
||||||
_feof = feof((FILE *)_handle);
|
|
||||||
_errorSource = 3;
|
|
||||||
} else { // everything ok
|
|
||||||
_feof = false; // Reset eof flag since we know it was ok
|
|
||||||
}
|
}
|
||||||
|
posToSearchFor += offs;
|
||||||
_pos = ftell((FILE *)_handle); // update pos
|
|
||||||
|
// Check for bad values
|
||||||
PowerMan.endCriticalSection();
|
if (posToSearchFor < 0) {
|
||||||
|
_ferror = true;
|
||||||
return (ret == 0);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (posToSearchFor > _fileSize) {
|
||||||
|
_ferror = true;
|
||||||
|
_eos = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we can find it in cache
|
||||||
|
if (isOffsetInCache(posToSearchFor)) {
|
||||||
|
PSP_DEBUG_PRINT("seek offset[0x%x] found in cache. Cache starts[0x%x]\n", posToSearchFor, _cacheStartOffset);
|
||||||
|
_inCache = true;
|
||||||
|
} else { // not in cache
|
||||||
|
_inCache = false;
|
||||||
|
}
|
||||||
|
_pos = posToSearchFor;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 PSPIoStream::read(void *ptr, uint32 len) {
|
uint32 PSPIoStream::read(void *ptr, uint32 len) {
|
||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
// Check if we can access the file
|
PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x], ptr[%p]\n", _path.c_str(), len, ptr);
|
||||||
|
|
||||||
|
if (_ferror || _eos)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
byte *destPtr = (byte *)ptr;
|
||||||
|
uint32 lenFromFile = len; // how much we read from the actual file
|
||||||
|
uint32 lenFromCache = 0; // how much we read from cache
|
||||||
|
uint32 lenRemainingInFile = _fileSize - _pos;
|
||||||
|
|
||||||
|
if (lenFromFile > lenRemainingInFile) {
|
||||||
|
lenFromFile = lenRemainingInFile;
|
||||||
|
_eos = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Are we in cache?
|
||||||
|
if (_inCache && isCacheValid()) {
|
||||||
|
uint32 offsetInCache = _pos - _cacheStartOffset;
|
||||||
|
// We can read at most what's in the cache or the remaining size of the file
|
||||||
|
lenFromCache = MIN2(lenFromFile, CACHE_SIZE - offsetInCache); // unsure
|
||||||
|
|
||||||
|
PSP_DEBUG_PRINT("reading 0x%x bytes from cache to %p. pos[0x%x] physPos[0x%x] cacheStart[0x%x]\n", lenFromCache, destPtr, _pos, _physicalPos, _cacheStartOffset);
|
||||||
|
|
||||||
|
memcpy(destPtr, &_cache[offsetInCache], lenFromCache);
|
||||||
|
_pos += lenFromCache;
|
||||||
|
|
||||||
|
if (lenFromCache < lenFromFile) { // there's more to copy from the file
|
||||||
|
lenFromFile -= lenFromCache;
|
||||||
|
lenRemainingInFile -= lenFromCache; // since we moved pos
|
||||||
|
destPtr += lenFromCache;
|
||||||
|
} else { // we're done
|
||||||
|
#ifdef DEBUG_BUFFERS
|
||||||
|
printBuffer((byte *)ptr, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return lenFromCache; // how much we actually read
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
||||||
|
|
||||||
PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
|
|
||||||
|
synchronizePhysicalPos(); // we need to update our physical position
|
||||||
size_t ret = fread((byte *)ptr, 1, len, (FILE *)_handle);
|
|
||||||
|
if (lenFromFile <= MIN_READ_SIZE) { // We load the cache in case the read is small enough
|
||||||
_pos += ret; // Update pos
|
// This optimization is based on the principle that reading 1 byte is as expensive as 1000 bytes
|
||||||
|
uint32 lenToCopyToCache = MIN2((uint32)MIN_READ_SIZE, lenRemainingInFile); // at most remaining file size
|
||||||
if (ret != len) { // Check for eof
|
|
||||||
_feof = feof((FILE *)_handle);
|
PSP_DEBUG_PRINT("filling cache with 0x%x bytes from physicalPos[0x%x]. cacheStart[0x%x], pos[0x%x], fileSize[0x%x]\n", lenToCopyToCache, _physicalPos, _cacheStartOffset, _pos, _fileSize);
|
||||||
if (!_feof) { // It wasn't an eof. Must be an error
|
|
||||||
|
size_t ret = fread(_cache, 1, lenToCopyToCache, (FILE *)_handle);
|
||||||
|
if (ret != lenToCopyToCache) {
|
||||||
|
PSP_ERROR("in filling cache, failed to get 0x%x bytes. Only got 0x%x\n", lenToCopyToCache, ret);
|
||||||
_ferror = true;
|
_ferror = true;
|
||||||
clearerr((FILE *)_handle);
|
clearerr((FILE *)_handle);
|
||||||
_pos = ftell((FILE *)_handle); // Update our position
|
|
||||||
_errorSource = 4;
|
|
||||||
PSP_ERROR("fread returned ret[%d] instead of len[%d]\n", ret, len);
|
|
||||||
}
|
}
|
||||||
|
_cacheStartOffset = _physicalPos;
|
||||||
|
_inCache = true;
|
||||||
|
|
||||||
|
_physicalPos += ret;
|
||||||
|
|
||||||
|
PSP_DEBUG_PRINT("copying 0x%x bytes from cache to %p\n", lenFromFile, destPtr);
|
||||||
|
|
||||||
|
// Copy to the destination buffer from cache
|
||||||
|
memcpy(destPtr, _cache, lenFromFile);
|
||||||
|
_pos += lenFromFile;
|
||||||
|
|
||||||
|
} else { // Too big for cache. No caching
|
||||||
|
PSP_DEBUG_PRINT("reading 0x%x bytes from file to %p. Pos[0x%x], physPos[0x%x]\n", lenFromFile, destPtr, _pos, _physicalPos);
|
||||||
|
size_t ret = fread(destPtr, 1, lenFromFile, (FILE *)_handle);
|
||||||
|
|
||||||
|
_physicalPos += ret; // Update pos
|
||||||
|
_pos = _physicalPos;
|
||||||
|
|
||||||
|
if (ret != lenFromFile) { // error
|
||||||
|
PSP_ERROR("fread returned [0x%x] instead of len[0x%x]\n", ret, lenFromFile);
|
||||||
|
_ferror = true;
|
||||||
|
clearerr((FILE *)_handle);
|
||||||
|
_errorSource = 4;
|
||||||
|
}
|
||||||
|
_inCache = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerMan.endCriticalSection();
|
PowerMan.endCriticalSection();
|
||||||
|
|
||||||
return ret;
|
#ifdef DEBUG_BUFFERS
|
||||||
|
printBuffer((byte *)ptr, len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return lenFromCache + lenFromFile; // total of what was copied
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Test if seeking backwards/forwards has any effect on performance
|
||||||
|
inline bool PSPIoStream::synchronizePhysicalPos() {
|
||||||
|
if (_pos != _physicalPos) {
|
||||||
|
if (fseek((FILE *)_handle, _pos - _physicalPos, SEEK_CUR) != 0)
|
||||||
|
return false;
|
||||||
|
_physicalPos = _pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool PSPIoStream::isOffsetInCache(uint32 offset) {
|
||||||
|
if (_cacheStartOffset != -1 &&
|
||||||
|
offset >= (uint32)_cacheStartOffset &&
|
||||||
|
offset < (uint32)(_cacheStartOffset + CACHE_SIZE))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
|
uint32 PSPIoStream::write(const void *ptr, uint32 len) {
|
||||||
@ -193,18 +312,30 @@ uint32 PSPIoStream::write(const void *ptr, uint32 len) {
|
|||||||
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
|
||||||
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
PSP_DEBUG_PRINT_FUNC("Suspended\n");
|
||||||
|
|
||||||
PSP_DEBUG_PRINT_FUNC("filename[%s], len[%d]\n", _path.c_str(), len);
|
PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x]\n", _path.c_str(), len);
|
||||||
|
|
||||||
|
if (_ferror)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_eos = false; // we can't have eos with write
|
||||||
|
synchronizePhysicalPos();
|
||||||
|
|
||||||
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
|
size_t ret = fwrite(ptr, 1, len, (FILE *)_handle);
|
||||||
|
|
||||||
_pos += ret;
|
// If we're making the file bigger, adjust the size
|
||||||
|
if (_physicalPos + (int)ret > _fileSize)
|
||||||
|
_fileSize = _physicalPos + ret;
|
||||||
|
_physicalPos += ret;
|
||||||
|
_pos = _physicalPos;
|
||||||
|
_inCache = false;
|
||||||
|
_cacheStartOffset = -1; // invalidate cache
|
||||||
|
|
||||||
if (ret != len) { // Set error
|
if (ret != len) { // Set error
|
||||||
_ferror = true;
|
_ferror = true;
|
||||||
clearerr((FILE *)_handle);
|
clearerr((FILE *)_handle);
|
||||||
_pos = ftell((FILE *)_handle); // Update pos
|
_pos = ftell((FILE *)_handle); // Update pos
|
||||||
_errorSource = 5;
|
_errorSource = 5;
|
||||||
PSP_ERROR("fwrite returned[%d] instead of len[%d]\n", ret, len);
|
PSP_ERROR("fwrite returned[0x%x] instead of len[0x%x]\n", ret, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerMan.endCriticalSection();
|
PowerMan.endCriticalSection();
|
||||||
@ -224,7 +355,7 @@ bool PSPIoStream::flush() {
|
|||||||
_ferror = true;
|
_ferror = true;
|
||||||
clearerr((FILE *)_handle);
|
clearerr((FILE *)_handle);
|
||||||
_errorSource = 6;
|
_errorSource = 6;
|
||||||
PSP_ERROR("fflush returned ret[%u]\n", ret);
|
PSP_ERROR("fflush returned ret[%d]\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerMan.endCriticalSection();
|
PowerMan.endCriticalSection();
|
||||||
@ -286,6 +417,9 @@ int PSPIoStream::resume() {
|
|||||||
// Resume our previous position
|
// Resume our previous position
|
||||||
if (_handle > 0 && _pos > 0) {
|
if (_handle > 0 && _pos > 0) {
|
||||||
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
|
ret = fseek((FILE *)_handle, _pos, SEEK_SET);
|
||||||
|
|
||||||
|
_physicalPos = _pos;
|
||||||
|
_inCache = false;
|
||||||
|
|
||||||
if (ret != 0) { // Check for problem
|
if (ret != 0) { // Check for problem
|
||||||
_errorSuspend = ResumeError;
|
_errorSuspend = ResumeError;
|
||||||
|
@ -35,25 +35,39 @@
|
|||||||
*/
|
*/
|
||||||
class PSPIoStream : public StdioStream, public Suspendable {
|
class PSPIoStream : public StdioStream, public Suspendable {
|
||||||
protected:
|
protected:
|
||||||
Common::String _path; /* Need to maintain for reopening after suspend */
|
Common::String _path;
|
||||||
bool _writeMode; /* "" */
|
int _fileSize;
|
||||||
int _pos; /* "" */
|
bool _writeMode; // for resuming in the right mode
|
||||||
mutable int _ferror; /* Save file ferror */
|
int _physicalPos; // position in the real file
|
||||||
mutable bool _feof; /* and eof */
|
int _pos; // position. Sometimes virtual
|
||||||
|
bool _inCache; // whether we're in cache (virtual) mode
|
||||||
|
bool _eos; // EOS flag
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SuspendError = 2,
|
SuspendError = 2,
|
||||||
ResumeError = 3
|
ResumeError = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
int _errorSuspend;
|
enum {
|
||||||
|
CACHE_SIZE = 1024,
|
||||||
|
MIN_READ_SIZE = 1024 // reading less than 1024 takes exactly the same time as 1024
|
||||||
|
};
|
||||||
|
|
||||||
|
// For caching
|
||||||
|
char *_cache;
|
||||||
|
int _cacheStartOffset; // starting offset of the cache. -1 when cache is invalid
|
||||||
|
|
||||||
|
mutable int _ferror; // file error state
|
||||||
|
int _errorSuspend; // for debugging
|
||||||
mutable int _errorSource;
|
mutable int _errorSource;
|
||||||
|
|
||||||
// Error checking
|
|
||||||
int _errorPos;
|
int _errorPos;
|
||||||
void * _errorHandle;
|
void * _errorHandle;
|
||||||
int _suspendCount;
|
int _suspendCount;
|
||||||
|
|
||||||
|
bool synchronizePhysicalPos(); // synchronize the physical and virtual positions
|
||||||
|
bool isOffsetInCache(uint32 pos); // check if an offset is found in cache
|
||||||
|
bool isCacheValid() { return _cacheStartOffset != -1; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +40,7 @@ MODULE_OBJS := \
|
|||||||
saves/posix/posix-saves.o \
|
saves/posix/posix-saves.o \
|
||||||
saves/psp/psp-saves.o \
|
saves/psp/psp-saves.o \
|
||||||
timer/default/default-timer.o \
|
timer/default/default-timer.o \
|
||||||
|
timer/psp/timer.o \
|
||||||
vkeybd/image-map.o \
|
vkeybd/image-map.o \
|
||||||
vkeybd/polygon.o \
|
vkeybd/polygon.o \
|
||||||
vkeybd/virtual-keyboard.o \
|
vkeybd/virtual-keyboard.o \
|
||||||
|
84
backends/platform/android/README.build
Normal file
84
backends/platform/android/README.build
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
Building the ScummVM Android port
|
||||||
|
=================================
|
||||||
|
|
||||||
|
You will need these things to build:
|
||||||
|
1. Android EGL headers and library
|
||||||
|
2. Android SDK
|
||||||
|
3. An arm-android-eabi GCC toolchain
|
||||||
|
|
||||||
|
In the example commands, we are going to build against the Android 1.5
|
||||||
|
native ABI (but using the Android 1.6 SDK tools). Other version
|
||||||
|
combinations might/should be possible with a bit of tweaking.
|
||||||
|
|
||||||
|
In detail:
|
||||||
|
|
||||||
|
1. Android EGL headers and library
|
||||||
|
|
||||||
|
You can build these from the full Android source, but it is far easier
|
||||||
|
to just download the 3 Android EGL headers from here:
|
||||||
|
http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=opengl/include/EGL;hb=HEAD
|
||||||
|
(copy them to a directory called "EGL" somewhere)
|
||||||
|
|
||||||
|
... and grab libEGL.so off an existing phone/emulator:
|
||||||
|
adb pull /system/lib/libEGL.so /tmp
|
||||||
|
|
||||||
|
2. Android SDK
|
||||||
|
|
||||||
|
Download and install somewhere.
|
||||||
|
|
||||||
|
3. arm-android-eabi GCC toolchain
|
||||||
|
|
||||||
|
You have several choices for toolchains:
|
||||||
|
|
||||||
|
- Use Google arm-eabi prebuilt toolchain.
|
||||||
|
|
||||||
|
This is shipped with both the Android source release and Android NDK.
|
||||||
|
The problem is that "arm-eabi-gcc" can't actually link anything
|
||||||
|
successfully without extra command line flags. To use this with the
|
||||||
|
ScummVM configure/build environment you will need to create a family
|
||||||
|
of shell wrapper scripts that convert "arm-android-eabi-foo" to
|
||||||
|
"arm-eabi-foo -mandroid".
|
||||||
|
|
||||||
|
For example, I use this script:
|
||||||
|
#!/bin/sh
|
||||||
|
exec arm-eabi-${0##*-} -mandroid -DANDROID "$@"
|
||||||
|
|
||||||
|
... and create a family of symlinks/hardlinks pointing to it called
|
||||||
|
arm-android-eabi-gcc, arm-android-eabi-g++, etc. For tools that don't
|
||||||
|
take a "-mandroid" argument - like arm-eabi-strip - I bypass the shell
|
||||||
|
wrapper and just create an arm-android-eabi-strip symlink to the tool
|
||||||
|
directly.
|
||||||
|
|
||||||
|
- Build your own arm-android-eabi toolchain from GCC source.
|
||||||
|
|
||||||
|
This is lots of fun. I suggest my Android openembedded patches, see:
|
||||||
|
http://wiki.github.com/anguslees/openembedded-android/
|
||||||
|
(You just need to have lots of disk space and type a few commands)
|
||||||
|
If you get stuck, ask
|
||||||
|
|
||||||
|
Alternatively, do a websearch - there are several other cross-compile
|
||||||
|
toolchains around.
|
||||||
|
|
||||||
|
|
||||||
|
Building ScummVM
|
||||||
|
================
|
||||||
|
|
||||||
|
export ANDROID_SDK=<root of Android SDK>
|
||||||
|
|
||||||
|
PATH=$ANDROID_SDK/platforms/android-1.6/tools:$ANDROID_SDK/tools:$PATH
|
||||||
|
# You also want to ensure your arm-android-eabi toolchain is in your $PATH
|
||||||
|
|
||||||
|
export ANDROID_TOP=<root of built Android source>
|
||||||
|
|
||||||
|
EGL_INC="-I<location of EGL/ header directory>"
|
||||||
|
EGL_LIBS="-L<location of libEGL.so>"
|
||||||
|
|
||||||
|
CPPFLAGS="$EGL_INC" \
|
||||||
|
LDFLAGS="-g $EGL_LIBS" \
|
||||||
|
./configure --backend=android --host=android --enable-zlib #and any other flags
|
||||||
|
make scummvm.apk
|
||||||
|
|
||||||
|
This will build a "monolithic" ScummVM package, with the engines
|
||||||
|
statically linked in. If you want to build separate engine packages,
|
||||||
|
like on the market, add "--enable-plugins --default-dynamic" to
|
||||||
|
configure and also make scummvm-engine-scumm.apk, etc.
|
1413
backends/platform/android/android.cpp
Normal file
1413
backends/platform/android/android.cpp
Normal file
File diff suppressed because it is too large
Load Diff
52
backends/platform/android/android.mk
Normal file
52
backends/platform/android/android.mk
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Android specific build targets
|
||||||
|
|
||||||
|
AAPT = aapt
|
||||||
|
DX = dx
|
||||||
|
APKBUILDER = apkbuilder
|
||||||
|
ADB = adb -e
|
||||||
|
ANDROID_JAR = $(ANDROID_SDK)/platforms/android-1.6/android.jar
|
||||||
|
JAVAC ?= javac
|
||||||
|
JAVACFLAGS = -source 1.5 -target 1.5
|
||||||
|
|
||||||
|
# FIXME: find/mark plugin entry points and add all this back again:
|
||||||
|
#LDFLAGS += -Wl,--gc-sections
|
||||||
|
#CXXFLAGS += -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden
|
||||||
|
|
||||||
|
scummvm.apk: build.tmp/libscummvm.so resources.ap_ classes.dex
|
||||||
|
# Package installer won't delete old libscummvm.so on upgrade so
|
||||||
|
# replace it with a zero size file
|
||||||
|
$(INSTALL) -d build.stage/common/lib/armeabi
|
||||||
|
touch build.stage/common/lib/armeabi/libscummvm.so
|
||||||
|
# We now handle the library unpacking ourselves from mylib/
|
||||||
|
$(INSTALL) -d build.stage/common/mylib/armeabi
|
||||||
|
$(INSTALL) -c -m 644 build.tmp/libscummvm.so build.stage/common/mylib/armeabi/
|
||||||
|
$(STRIP) build.stage/common/mylib/armeabi/libscummvm.so
|
||||||
|
# "-nf lib/armeabi/libscummvm.so" builds bogus paths?
|
||||||
|
$(APKBUILDER) $@ -z resources.ap_ -f classes.dex -rf build.stage/common || { $(RM) $@; exit 1; }
|
||||||
|
|
||||||
|
scummvm-engine-%.apk: plugins/lib%.so build.tmp/%/resources.ap_ build.tmp/plugins/classes.dex
|
||||||
|
$(INSTALL) -d build.stage/$*/apk/mylib/armeabi/
|
||||||
|
$(INSTALL) -c -m 644 plugins/lib$*.so build.stage/$*/apk/mylib/armeabi/
|
||||||
|
$(STRIP) build.stage/$*/apk/mylib/armeabi/lib$*.so
|
||||||
|
$(APKBUILDER) $@ -z build.tmp/$*/resources.ap_ -f build.tmp/plugins/classes.dex -rf build.stage/$*/apk || { $(RM) $@; exit 1; }
|
||||||
|
|
||||||
|
release/%.apk: %.apk
|
||||||
|
@$(MKDIR) -p $(@D)
|
||||||
|
@$(RM) $@
|
||||||
|
$(CP) $< $@.tmp
|
||||||
|
# remove debugging signature
|
||||||
|
zip -d $@.tmp META-INF/\*
|
||||||
|
jarsigner $(JARSIGNER_FLAGS) $@.tmp release
|
||||||
|
zipalign 4 $@.tmp $@
|
||||||
|
$(RM) $@.tmp
|
||||||
|
|
||||||
|
androidrelease: release/scummvm.apk $(patsubst plugins/lib%.so,release/scummvm-engine-%.apk,$(PLUGINS))
|
||||||
|
|
||||||
|
androidtest: scummvm.apk scummvm-engine-scumm.apk scummvm-engine-kyra.apk
|
||||||
|
@set -e; for apk in $^; do \
|
||||||
|
echo $(ADB) install -r $$apk; \
|
||||||
|
$(ADB) install -r $$apk; \
|
||||||
|
done
|
||||||
|
$(ADB) shell am start -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n org.inodes.gus.scummvm/.Unpacker
|
||||||
|
|
||||||
|
.PHONY: androidrelease androidtest
|
414
backends/platform/android/asset-archive.cpp
Normal file
414
backends/platform/android/asset-archive.cpp
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
/* 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(ANDROID)
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "common/str.h"
|
||||||
|
#include "common/stream.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
#include "common/archive.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
#include "backends/platform/android/asset-archive.h"
|
||||||
|
|
||||||
|
extern JNIEnv* JNU_GetEnv();
|
||||||
|
|
||||||
|
// Must match android.content.res.AssetManager.ACCESS_*
|
||||||
|
const jint ACCESS_UNKNOWN = 0;
|
||||||
|
const jint ACCESS_RANDOM = 1;
|
||||||
|
|
||||||
|
// This might be useful to someone else. Assumes markSupported() == true.
|
||||||
|
class JavaInputStream : public Common::SeekableReadStream {
|
||||||
|
public:
|
||||||
|
JavaInputStream(JNIEnv* env, jobject is);
|
||||||
|
virtual ~JavaInputStream();
|
||||||
|
virtual bool eos() const { return _eos; }
|
||||||
|
virtual bool err() const { return _err; }
|
||||||
|
virtual void clearErr() { _eos = _err = false; }
|
||||||
|
virtual uint32 read(void *dataPtr, uint32 dataSize);
|
||||||
|
virtual int32 pos() const { return _pos; }
|
||||||
|
virtual int32 size() const { return _len; }
|
||||||
|
virtual bool seek(int32 offset, int whence = SEEK_SET);
|
||||||
|
private:
|
||||||
|
void close(JNIEnv* env);
|
||||||
|
jmethodID MID_mark;
|
||||||
|
jmethodID MID_available;
|
||||||
|
jmethodID MID_close;
|
||||||
|
jmethodID MID_read;
|
||||||
|
jmethodID MID_reset;
|
||||||
|
jmethodID MID_skip;
|
||||||
|
jobject _input_stream;
|
||||||
|
jsize _buflen;
|
||||||
|
jbyteArray _buf;
|
||||||
|
uint32 _pos;
|
||||||
|
jint _len;
|
||||||
|
bool _eos;
|
||||||
|
bool _err;
|
||||||
|
};
|
||||||
|
|
||||||
|
JavaInputStream::JavaInputStream(JNIEnv* env, jobject is) :
|
||||||
|
_eos(false), _err(false), _pos(0)
|
||||||
|
{
|
||||||
|
_input_stream = env->NewGlobalRef(is);
|
||||||
|
_buflen = 8192;
|
||||||
|
_buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
|
||||||
|
|
||||||
|
jclass cls = env->GetObjectClass(_input_stream);
|
||||||
|
MID_mark = env->GetMethodID(cls, "mark", "(I)V");
|
||||||
|
assert(MID_mark);
|
||||||
|
MID_available = env->GetMethodID(cls, "available", "()I");
|
||||||
|
assert(MID_mark);
|
||||||
|
MID_close = env->GetMethodID(cls, "close", "()V");
|
||||||
|
assert(MID_close);
|
||||||
|
MID_read = env->GetMethodID(cls, "read", "([BII)I");
|
||||||
|
assert(MID_read);
|
||||||
|
MID_reset = env->GetMethodID(cls, "reset", "()V");
|
||||||
|
assert(MID_reset);
|
||||||
|
MID_skip = env->GetMethodID(cls, "skip", "(J)J");
|
||||||
|
assert(MID_skip);
|
||||||
|
|
||||||
|
// Mark start of stream, so we can reset back to it.
|
||||||
|
// readlimit is set to something bigger than anything we might
|
||||||
|
// want to seek within.
|
||||||
|
env->CallVoidMethod(_input_stream, MID_mark, 10*1024*1024);
|
||||||
|
_len = env->CallIntMethod(_input_stream, MID_available);
|
||||||
|
}
|
||||||
|
|
||||||
|
JavaInputStream::~JavaInputStream() {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
close(env);
|
||||||
|
env->DeleteGlobalRef(_buf);
|
||||||
|
env->DeleteGlobalRef(_input_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JavaInputStream::close(JNIEnv* env) {
|
||||||
|
env->CallVoidMethod(_input_stream, MID_close);
|
||||||
|
if (env->ExceptionCheck())
|
||||||
|
env->ExceptionClear();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 JavaInputStream::read(void *dataPtr, uint32 dataSize) {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
|
||||||
|
if (_buflen < dataSize) {
|
||||||
|
_buflen = dataSize;
|
||||||
|
env->DeleteGlobalRef(_buf);
|
||||||
|
_buf = static_cast<jbyteArray>(env->NewGlobalRef(env->NewByteArray(_buflen)));
|
||||||
|
}
|
||||||
|
|
||||||
|
jint ret = env->CallIntMethod(_input_stream, MID_read, _buf, 0, dataSize);
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
warning("Exception during JavaInputStream::read(%p, %d)",
|
||||||
|
dataPtr, dataSize);
|
||||||
|
env->ExceptionDescribe();
|
||||||
|
env->ExceptionClear();
|
||||||
|
_err = true;
|
||||||
|
ret = -1;
|
||||||
|
} else if (ret == -1) {
|
||||||
|
_eos = true;
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
env->GetByteArrayRegion(_buf, 0, ret, static_cast<jbyte*>(dataPtr));
|
||||||
|
_pos += ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JavaInputStream::seek(int32 offset, int whence) {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
uint32 newpos;
|
||||||
|
switch (whence) {
|
||||||
|
case SEEK_SET:
|
||||||
|
newpos = offset;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
newpos = _pos + offset;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
newpos = _len + offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
debug("Unknown 'whence' arg %d", whence);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
jlong skip_bytes;
|
||||||
|
if (newpos > _pos) {
|
||||||
|
skip_bytes = newpos - _pos;
|
||||||
|
} else {
|
||||||
|
// Can't skip backwards, so jump back to start and skip from there.
|
||||||
|
env->CallVoidMethod(_input_stream, MID_reset);
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
warning("Failed to rewind to start of asset stream");
|
||||||
|
env->ExceptionDescribe();
|
||||||
|
env->ExceptionClear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_pos = 0;
|
||||||
|
skip_bytes = newpos;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (skip_bytes > 0) {
|
||||||
|
jlong ret = env->CallLongMethod(_input_stream, MID_skip, skip_bytes);
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
warning("Failed to skip %ld bytes into asset stream",
|
||||||
|
static_cast<long>(skip_bytes));
|
||||||
|
env->ExceptionDescribe();
|
||||||
|
env->ExceptionClear();
|
||||||
|
return false;
|
||||||
|
} else if (ret == 0) {
|
||||||
|
warning("InputStream->skip(%ld) didn't skip any bytes. Aborting seek.",
|
||||||
|
static_cast<long>(skip_bytes));
|
||||||
|
return false; // No point looping forever...
|
||||||
|
}
|
||||||
|
_pos += ret;
|
||||||
|
skip_bytes -= ret;
|
||||||
|
}
|
||||||
|
_eos = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Must match android.content.res.AssetFileDescriptor.UNKNOWN_LENGTH
|
||||||
|
const jlong UNKNOWN_LENGTH = -1;
|
||||||
|
|
||||||
|
// Reading directly from a fd is so much more efficient, that it is
|
||||||
|
// worth optimising for.
|
||||||
|
class AssetFdReadStream : public Common::SeekableReadStream {
|
||||||
|
public:
|
||||||
|
AssetFdReadStream(JNIEnv* env, jobject assetfd);
|
||||||
|
virtual ~AssetFdReadStream();
|
||||||
|
virtual bool eos() const { return _eos; }
|
||||||
|
virtual bool err() const { return _err; }
|
||||||
|
virtual void clearErr() { _eos = _err = false; }
|
||||||
|
virtual uint32 read(void *dataPtr, uint32 dataSize);
|
||||||
|
virtual int32 pos() const { return _pos; }
|
||||||
|
virtual int32 size() const { return _declared_len; }
|
||||||
|
virtual bool seek(int32 offset, int whence = SEEK_SET);
|
||||||
|
private:
|
||||||
|
void close(JNIEnv* env);
|
||||||
|
int _fd;
|
||||||
|
jmethodID MID_close;
|
||||||
|
jobject _assetfd;
|
||||||
|
jlong _start_off;
|
||||||
|
jlong _declared_len;
|
||||||
|
uint32 _pos;
|
||||||
|
bool _eos;
|
||||||
|
bool _err;
|
||||||
|
};
|
||||||
|
|
||||||
|
AssetFdReadStream::AssetFdReadStream(JNIEnv* env, jobject assetfd) :
|
||||||
|
_eos(false), _err(false), _pos(0)
|
||||||
|
{
|
||||||
|
_assetfd = env->NewGlobalRef(assetfd);
|
||||||
|
|
||||||
|
jclass cls = env->GetObjectClass(_assetfd);
|
||||||
|
MID_close = env->GetMethodID(cls, "close", "()V");
|
||||||
|
assert(MID_close);
|
||||||
|
|
||||||
|
jmethodID MID_getStartOffset =
|
||||||
|
env->GetMethodID(cls, "getStartOffset", "()J");
|
||||||
|
assert(MID_getStartOffset);
|
||||||
|
_start_off = env->CallLongMethod(_assetfd, MID_getStartOffset);
|
||||||
|
|
||||||
|
jmethodID MID_getDeclaredLength =
|
||||||
|
env->GetMethodID(cls, "getDeclaredLength", "()J");
|
||||||
|
assert(MID_getDeclaredLength);
|
||||||
|
_declared_len = env->CallLongMethod(_assetfd, MID_getDeclaredLength);
|
||||||
|
|
||||||
|
jmethodID MID_getFileDescriptor =
|
||||||
|
env->GetMethodID(cls, "getFileDescriptor", "()Ljava/io/FileDescriptor;");
|
||||||
|
assert(MID_getFileDescriptor);
|
||||||
|
jobject javafd = env->CallObjectMethod(_assetfd, MID_getFileDescriptor);
|
||||||
|
assert(javafd);
|
||||||
|
jclass fd_cls = env->GetObjectClass(javafd);
|
||||||
|
jfieldID FID_descriptor = env->GetFieldID(fd_cls, "descriptor", "I");
|
||||||
|
assert(FID_descriptor);
|
||||||
|
_fd = env->GetIntField(javafd, FID_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetFdReadStream::~AssetFdReadStream() {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
env->CallVoidMethod(_assetfd, MID_close);
|
||||||
|
if (env->ExceptionCheck())
|
||||||
|
env->ExceptionClear();
|
||||||
|
env->DeleteGlobalRef(_assetfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 AssetFdReadStream::read(void *dataPtr, uint32 dataSize) {
|
||||||
|
if (_declared_len != UNKNOWN_LENGTH) {
|
||||||
|
jlong cap = _declared_len - _pos;
|
||||||
|
if (dataSize > cap)
|
||||||
|
dataSize = cap;
|
||||||
|
}
|
||||||
|
int ret = ::read(_fd, dataPtr, dataSize);
|
||||||
|
if (ret == 0)
|
||||||
|
_eos = true;
|
||||||
|
else if (ret == -1)
|
||||||
|
_err = true;
|
||||||
|
else
|
||||||
|
_pos += ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AssetFdReadStream::seek(int32 offset, int whence) {
|
||||||
|
if (whence == SEEK_SET) {
|
||||||
|
if (_declared_len != UNKNOWN_LENGTH && offset > _declared_len)
|
||||||
|
offset = _declared_len;
|
||||||
|
offset += _start_off;
|
||||||
|
} else if (whence == SEEK_END && _declared_len != UNKNOWN_LENGTH) {
|
||||||
|
whence = SEEK_SET;
|
||||||
|
offset = _start_off + _declared_len + offset;
|
||||||
|
}
|
||||||
|
int ret = lseek(_fd, offset, whence);
|
||||||
|
if (ret == -1)
|
||||||
|
return false;
|
||||||
|
_pos = ret - _start_off;
|
||||||
|
_eos = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidAssetArchive::AndroidAssetArchive(jobject am) {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
_am = env->NewGlobalRef(am);
|
||||||
|
|
||||||
|
jclass cls = env->GetObjectClass(_am);
|
||||||
|
MID_open = env->GetMethodID(cls, "open",
|
||||||
|
"(Ljava/lang/String;I)Ljava/io/InputStream;");
|
||||||
|
assert(MID_open);
|
||||||
|
MID_openFd = env->GetMethodID(cls, "openFd",
|
||||||
|
"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
|
||||||
|
assert(MID_openFd);
|
||||||
|
MID_list = env->GetMethodID(cls, "list",
|
||||||
|
"(Ljava/lang/String;)[Ljava/lang/String;");
|
||||||
|
assert(MID_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
AndroidAssetArchive::~AndroidAssetArchive() {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
env->DeleteGlobalRef(_am);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AndroidAssetArchive::hasFile(const Common::String &name) {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
jstring path = env->NewStringUTF(name.c_str());
|
||||||
|
jobject result = env->CallObjectMethod(_am, MID_open, path, ACCESS_UNKNOWN);
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
// Assume FileNotFoundException
|
||||||
|
//warning("Error while calling AssetManager->open(%s)", name.c_str());
|
||||||
|
//env->ExceptionDescribe();
|
||||||
|
env->ExceptionClear();
|
||||||
|
env->DeleteLocalRef(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
env->DeleteLocalRef(result);
|
||||||
|
env->DeleteLocalRef(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AndroidAssetArchive::listMembers(Common::ArchiveMemberList &member_list) {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
Common::List<Common::String> dirlist;
|
||||||
|
dirlist.push_back("");
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
while (!dirlist.empty()) {
|
||||||
|
const Common::String dir = dirlist.back();
|
||||||
|
dirlist.pop_back();
|
||||||
|
|
||||||
|
jstring jpath = env->NewStringUTF(dir.c_str());
|
||||||
|
jobjectArray jpathlist = static_cast<jobjectArray>(env->CallObjectMethod(_am, MID_list, jpath));
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
warning("Error while calling AssetManager->list(%s). Ignoring.",
|
||||||
|
dir.c_str());
|
||||||
|
env->ExceptionDescribe();
|
||||||
|
env->ExceptionClear();
|
||||||
|
continue; // May as well keep going ...
|
||||||
|
}
|
||||||
|
env->DeleteLocalRef(jpath);
|
||||||
|
|
||||||
|
for (jsize i = 0; i < env->GetArrayLength(jpathlist); ++i) {
|
||||||
|
jstring elem = (jstring)env->GetObjectArrayElement(jpathlist, i);
|
||||||
|
const char* p = env->GetStringUTFChars(elem, NULL);
|
||||||
|
Common::String thispath = dir;
|
||||||
|
if (!thispath.empty())
|
||||||
|
thispath += "/";
|
||||||
|
thispath += p;
|
||||||
|
|
||||||
|
// Assume files have a . in them, and directories don't
|
||||||
|
if (strchr(p, '.')) {
|
||||||
|
member_list.push_back(getMember(thispath));
|
||||||
|
++count;
|
||||||
|
} else
|
||||||
|
dirlist.push_back(thispath);
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(elem, p);
|
||||||
|
env->DeleteLocalRef(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
env->DeleteLocalRef(jpathlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::ArchiveMemberPtr AndroidAssetArchive::getMember(const Common::String &name) {
|
||||||
|
return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::SeekableReadStream *AndroidAssetArchive::createReadStreamForMember(const Common::String &path) const {
|
||||||
|
JNIEnv* env = JNU_GetEnv();
|
||||||
|
jstring jpath = env->NewStringUTF(path.c_str());
|
||||||
|
|
||||||
|
// Try openFd() first ...
|
||||||
|
jobject afd = env->CallObjectMethod(_am, MID_openFd, jpath);
|
||||||
|
if (env->ExceptionCheck())
|
||||||
|
env->ExceptionClear();
|
||||||
|
else if (afd != NULL) {
|
||||||
|
// success :)
|
||||||
|
env->DeleteLocalRef(jpath);
|
||||||
|
return new AssetFdReadStream(env, afd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... and fallback to normal open() if that doesn't work
|
||||||
|
jobject is = env->CallObjectMethod(_am, MID_open, jpath, ACCESS_RANDOM);
|
||||||
|
if (env->ExceptionCheck()) {
|
||||||
|
// Assume FileNotFoundException
|
||||||
|
//warning("Error opening %s", path.c_str());
|
||||||
|
//env->ExceptionDescribe();
|
||||||
|
env->ExceptionClear();
|
||||||
|
env->DeleteLocalRef(jpath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JavaInputStream(env, is);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
53
backends/platform/android/asset-archive.h
Normal file
53
backends/platform/android/asset-archive.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/* 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(ANDROID)
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
#include "common/str.h"
|
||||||
|
#include "common/stream.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
#include "common/archive.h"
|
||||||
|
|
||||||
|
class AndroidAssetArchive : public Common::Archive {
|
||||||
|
public:
|
||||||
|
AndroidAssetArchive(jobject am);
|
||||||
|
virtual ~AndroidAssetArchive();
|
||||||
|
|
||||||
|
virtual bool hasFile(const Common::String &name);
|
||||||
|
virtual int listMembers(Common::ArchiveMemberList &list);
|
||||||
|
virtual Common::ArchiveMemberPtr getMember(const Common::String &name);
|
||||||
|
virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
jmethodID MID_open;
|
||||||
|
jmethodID MID_openFd;
|
||||||
|
jmethodID MID_list;
|
||||||
|
|
||||||
|
jobject _am;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
85
backends/platform/android/module.mk
Normal file
85
backends/platform/android/module.mk
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
MODULE := backends/platform/android
|
||||||
|
|
||||||
|
MODULE_OBJS := \
|
||||||
|
android.o asset-archive.o video.o
|
||||||
|
|
||||||
|
MODULE_DIRS += \
|
||||||
|
backends/platform/android/
|
||||||
|
|
||||||
|
# We don't use the rules.mk here on purpose
|
||||||
|
OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
|
||||||
|
|
||||||
|
JAVA_SRC = \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/ScummVM.java \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/ScummVMApplication.java \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/ScummVMActivity.java \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/EditableSurfaceView.java \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/Unpacker.java \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/Manifest.java \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/R.java
|
||||||
|
|
||||||
|
JAVA_PLUGIN_SRC = \
|
||||||
|
$(MODULE)/org/inodes/gus/scummvm/PluginProvider.java
|
||||||
|
|
||||||
|
RESOURCES = \
|
||||||
|
$(srcdir)/dists/android/res/values/strings.xml \
|
||||||
|
$(srcdir)/dists/android/res/layout/main.xml \
|
||||||
|
$(srcdir)/dists/android/res/layout/splash.xml \
|
||||||
|
$(srcdir)/dists/android/res/drawable/gradient.xml \
|
||||||
|
$(srcdir)/dists/android/res/drawable/scummvm.png \
|
||||||
|
$(srcdir)/dists/android/res/drawable/scummvm_big.png
|
||||||
|
|
||||||
|
ASSETS = $(DIST_FILES_ENGINEDATA) $(DIST_FILES_THEMES)
|
||||||
|
|
||||||
|
PLUGIN_RESOURCES = \
|
||||||
|
$(srcdir)/dists/android/res/values/strings.xml \
|
||||||
|
$(srcdir)/dists/android/res/drawable/scummvm.png
|
||||||
|
|
||||||
|
# These must be incremented for each market upload
|
||||||
|
#ANDROID_VERSIONCODE = 6 Specified in dists/android/AndroidManifest.xml.in
|
||||||
|
ANDROID_PLUGIN_VERSIONCODE = 6
|
||||||
|
|
||||||
|
# This library contains scummvm proper
|
||||||
|
build.tmp/libscummvm.so: $(OBJS)
|
||||||
|
@$(MKDIR) -p $(@D)
|
||||||
|
$(CXX) $(PLUGIN_LDFLAGS) -shared $(LDFLAGS) -Wl,-soname,$(@F) -Wl,--no-undefined -o $@ $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
backends/platform/android/org/inodes/gus/scummvm/R.java backends/platform/android/org/inodes/gus/scummvm/Manifest.java: $(srcdir)/dists/android/AndroidManifest.xml $(filter %.xml,$(RESOURCES)) $(ANDROID_JAR)
|
||||||
|
$(AAPT) package -m -J backends/platform/android -M $< -S $(srcdir)/dists/android/res -I $(ANDROID_JAR)
|
||||||
|
|
||||||
|
build.tmp/classes/%.class: $(srcdir)/backends/platform/android/%.java $(srcdir)/backends/platform/android/org/inodes/gus/scummvm/R.java
|
||||||
|
@$(MKDIR) -p $(@D)
|
||||||
|
$(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes -bootclasspath $(ANDROID_JAR) $<
|
||||||
|
|
||||||
|
build.tmp/classes.plugin/%.class: $(srcdir)/backends/platform/android/%.java
|
||||||
|
@$(MKDIR) -p $(@D)
|
||||||
|
$(JAVAC) $(JAVACFLAGS) -cp $(srcdir)/backends/platform/android -d build.tmp/classes.plugin -bootclasspath $(ANDROID_JAR) $<
|
||||||
|
|
||||||
|
classes.dex: $(JAVA_SRC:backends/platform/android/%.java=build.tmp/classes/%.class)
|
||||||
|
$(DX) --dex --output=$@ build.tmp/classes
|
||||||
|
|
||||||
|
build.tmp/plugins/classes.dex: $(JAVA_PLUGIN_SRC:backends/platform/android/%.java=build.tmp/classes.plugin/%.class)
|
||||||
|
@$(MKDIR) -p $(@D)
|
||||||
|
$(DX) --dex --output=$@ build.tmp/classes.plugin
|
||||||
|
|
||||||
|
resources.ap_: $(srcdir)/dists/android/AndroidManifest.xml $(RESOURCES) $(ASSETS) $(ANDROID_JAR) $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA)
|
||||||
|
$(INSTALL) -d build.tmp/assets/
|
||||||
|
$(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) build.tmp/assets/
|
||||||
|
$(AAPT) package -f -M $< -S $(srcdir)/dists/android/res -A build.tmp/assets -I $(ANDROID_JAR) -F $@
|
||||||
|
|
||||||
|
build.tmp/%/resources.ap_: build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml build.stage/%/res/drawable/scummvm.png $(ANDROID_JAR)
|
||||||
|
$(AAPT) package -f -M $< -S build.stage/$*/res -I $(ANDROID_JAR) -F $@
|
||||||
|
|
||||||
|
build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml: dists/android/mkmanifest.pl configure dists/android/AndroidManifest.xml
|
||||||
|
dists/android/mkmanifest.pl --id=$* --configure=configure \
|
||||||
|
--version-name=$(VERSION) \
|
||||||
|
--version-code=$(ANDROID_PLUGIN_VERSIONCODE) \
|
||||||
|
--stringres=build.stage/$*/res/values/strings.xml \
|
||||||
|
--manifest=build.tmp/$*/AndroidManifest.xml \
|
||||||
|
--master-manifest=dists/android/AndroidManifest.xml \
|
||||||
|
--unpacklib=mylib/armeabi/lib$*.so
|
||||||
|
|
||||||
|
build.stage/%/res/drawable/scummvm.png: dists/android/res/drawable/scummvm.png
|
||||||
|
@$(MKDIR) -p $(@D)
|
||||||
|
$(CP) $< $@
|
@ -0,0 +1,59 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.InputType;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
import android.view.inputmethod.BaseInputConnection;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.view.inputmethod.InputConnection;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
|
||||||
|
public class EditableSurfaceView extends SurfaceView {
|
||||||
|
public EditableSurfaceView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditableSurfaceView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditableSurfaceView(Context context, AttributeSet attrs,
|
||||||
|
int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCheckIsTextEditor() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MyInputConnection extends BaseInputConnection {
|
||||||
|
public MyInputConnection() {
|
||||||
|
super(EditableSurfaceView.this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performEditorAction(int actionCode) {
|
||||||
|
if (actionCode == EditorInfo.IME_ACTION_DONE) {
|
||||||
|
InputMethodManager imm = (InputMethodManager)
|
||||||
|
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.hideSoftInputFromWindow(getWindowToken(), 0);
|
||||||
|
}
|
||||||
|
return super.performEditorAction(actionCode); // Sends enter key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||||
|
outAttrs.initialCapsMode = 0;
|
||||||
|
outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;
|
||||||
|
outAttrs.inputType = (InputType.TYPE_CLASS_TEXT |
|
||||||
|
InputType.TYPE_TEXT_VARIATION_NORMAL |
|
||||||
|
InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
|
||||||
|
outAttrs.imeOptions = (EditorInfo.IME_ACTION_DONE |
|
||||||
|
EditorInfo.IME_FLAG_NO_EXTRACT_UI);
|
||||||
|
|
||||||
|
return new MyInputConnection();
|
||||||
|
}
|
||||||
|
}
|
330
backends/platform/android/org/inodes/gus/scummvm/Event.java
Normal file
330
backends/platform/android/org/inodes/gus/scummvm/Event.java
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Event {
|
||||||
|
// Common::EventType enum.
|
||||||
|
// Must be kept in sync with common/events.h
|
||||||
|
public final static int EVENT_INVALID = 0;
|
||||||
|
public final static int EVENT_KEYDOWN = 1;
|
||||||
|
public final static int EVENT_KEYUP = 2;
|
||||||
|
public final static int EVENT_MOUSEMOVE = 3;
|
||||||
|
public final static int EVENT_LBUTTONDOWN = 4;
|
||||||
|
public final static int EVENT_LBUTTONUP = 5;
|
||||||
|
public final static int EVENT_RBUTTONDOWN = 6;
|
||||||
|
public final static int EVENT_RBUTTONUP = 7;
|
||||||
|
public final static int EVENT_WHEELUP = 8;
|
||||||
|
public final static int EVENT_WHEELDOWN = 9;
|
||||||
|
public final static int EVENT_QUIT = 10;
|
||||||
|
public final static int EVENT_SCREEN_CHANGED = 11;
|
||||||
|
public final static int EVENT_PREDICTIVE_DIALOG = 12;
|
||||||
|
public final static int EVENT_MBUTTONDOWN = 13;
|
||||||
|
public final static int EVENT_MBUTTONUP = 14;
|
||||||
|
public final static int EVENT_MAINMENU = 15;
|
||||||
|
public final static int EVENT_RTL = 16;
|
||||||
|
|
||||||
|
// common/keyboard.h
|
||||||
|
public final static int ASCII_F1 = 315;
|
||||||
|
public final static int ASCII_F2 = 316;
|
||||||
|
public final static int ASCII_F3 = 317;
|
||||||
|
public final static int ASCII_F4 = 318;
|
||||||
|
public final static int ASCII_F5 = 319;
|
||||||
|
public final static int ASCII_F6 = 320;
|
||||||
|
public final static int ASCII_F7 = 321;
|
||||||
|
public final static int ASCII_F8 = 322;
|
||||||
|
public final static int ASCII_F9 = 323;
|
||||||
|
public final static int ASCII_F10 = 324;
|
||||||
|
public final static int ASCII_F11 = 325;
|
||||||
|
public final static int ASCII_F12 = 326;
|
||||||
|
public final static int KBD_CTRL = 1 << 0;
|
||||||
|
public final static int KBD_ALT = 1 << 1;
|
||||||
|
public final static int KBD_SHIFT = 1 << 2;
|
||||||
|
|
||||||
|
public final static int KEYCODE_INVALID = 0;
|
||||||
|
public final static int KEYCODE_BACKSPACE = 8;
|
||||||
|
public final static int KEYCODE_TAB = 9;
|
||||||
|
public final static int KEYCODE_CLEAR = 12;
|
||||||
|
public final static int KEYCODE_RETURN = 13;
|
||||||
|
public final static int KEYCODE_PAUSE = 19;
|
||||||
|
public final static int KEYCODE_ESCAPE = 27;
|
||||||
|
public final static int KEYCODE_SPACE = 32;
|
||||||
|
public final static int KEYCODE_EXCLAIM = 33;
|
||||||
|
public final static int KEYCODE_QUOTEDBL = 34;
|
||||||
|
public final static int KEYCODE_HASH = 35;
|
||||||
|
public final static int KEYCODE_DOLLAR = 36;
|
||||||
|
public final static int KEYCODE_AMPERSAND = 38;
|
||||||
|
public final static int KEYCODE_QUOTE = 39;
|
||||||
|
public final static int KEYCODE_LEFTPAREN = 40;
|
||||||
|
public final static int KEYCODE_RIGHTPAREN = 41;
|
||||||
|
public final static int KEYCODE_ASTERISK = 42;
|
||||||
|
public final static int KEYCODE_PLUS = 43;
|
||||||
|
public final static int KEYCODE_COMMA = 44;
|
||||||
|
public final static int KEYCODE_MINUS = 45;
|
||||||
|
public final static int KEYCODE_PERIOD = 46;
|
||||||
|
public final static int KEYCODE_SLASH = 47;
|
||||||
|
public final static int KEYCODE_0 = 48;
|
||||||
|
public final static int KEYCODE_1 = 49;
|
||||||
|
public final static int KEYCODE_2 = 50;
|
||||||
|
public final static int KEYCODE_3 = 51;
|
||||||
|
public final static int KEYCODE_4 = 52;
|
||||||
|
public final static int KEYCODE_5 = 53;
|
||||||
|
public final static int KEYCODE_6 = 54;
|
||||||
|
public final static int KEYCODE_7 = 55;
|
||||||
|
public final static int KEYCODE_8 = 56;
|
||||||
|
public final static int KEYCODE_9 = 57;
|
||||||
|
public final static int KEYCODE_COLON = 58;
|
||||||
|
public final static int KEYCODE_SEMICOLON = 59;
|
||||||
|
public final static int KEYCODE_LESS = 60;
|
||||||
|
public final static int KEYCODE_EQUALS = 61;
|
||||||
|
public final static int KEYCODE_GREATER = 62;
|
||||||
|
public final static int KEYCODE_QUESTION = 63;
|
||||||
|
public final static int KEYCODE_AT = 64;
|
||||||
|
public final static int KEYCODE_LEFTBRACKET = 91;
|
||||||
|
public final static int KEYCODE_BACKSLASH = 92;
|
||||||
|
public final static int KEYCODE_RIGHTBRACKET = 93;
|
||||||
|
public final static int KEYCODE_CARET = 94;
|
||||||
|
public final static int KEYCODE_UNDERSCORE = 95;
|
||||||
|
public final static int KEYCODE_BACKQUOTE = 96;
|
||||||
|
public final static int KEYCODE_a = 97;
|
||||||
|
public final static int KEYCODE_b = 98;
|
||||||
|
public final static int KEYCODE_c = 99;
|
||||||
|
public final static int KEYCODE_d = 100;
|
||||||
|
public final static int KEYCODE_e = 101;
|
||||||
|
public final static int KEYCODE_f = 102;
|
||||||
|
public final static int KEYCODE_g = 103;
|
||||||
|
public final static int KEYCODE_h = 104;
|
||||||
|
public final static int KEYCODE_i = 105;
|
||||||
|
public final static int KEYCODE_j = 106;
|
||||||
|
public final static int KEYCODE_k = 107;
|
||||||
|
public final static int KEYCODE_l = 108;
|
||||||
|
public final static int KEYCODE_m = 109;
|
||||||
|
public final static int KEYCODE_n = 110;
|
||||||
|
public final static int KEYCODE_o = 111;
|
||||||
|
public final static int KEYCODE_p = 112;
|
||||||
|
public final static int KEYCODE_q = 113;
|
||||||
|
public final static int KEYCODE_r = 114;
|
||||||
|
public final static int KEYCODE_s = 115;
|
||||||
|
public final static int KEYCODE_t = 116;
|
||||||
|
public final static int KEYCODE_u = 117;
|
||||||
|
public final static int KEYCODE_v = 118;
|
||||||
|
public final static int KEYCODE_w = 119;
|
||||||
|
public final static int KEYCODE_x = 120;
|
||||||
|
public final static int KEYCODE_y = 121;
|
||||||
|
public final static int KEYCODE_z = 122;
|
||||||
|
public final static int KEYCODE_DELETE = 127;
|
||||||
|
// Numeric keypad
|
||||||
|
public final static int KEYCODE_KP0 = 256;
|
||||||
|
public final static int KEYCODE_KP1 = 257;
|
||||||
|
public final static int KEYCODE_KP2 = 258;
|
||||||
|
public final static int KEYCODE_KP3 = 259;
|
||||||
|
public final static int KEYCODE_KP4 = 260;
|
||||||
|
public final static int KEYCODE_KP5 = 261;
|
||||||
|
public final static int KEYCODE_KP6 = 262;
|
||||||
|
public final static int KEYCODE_KP7 = 263;
|
||||||
|
public final static int KEYCODE_KP8 = 264;
|
||||||
|
public final static int KEYCODE_KP9 = 265;
|
||||||
|
public final static int KEYCODE_KP_PERIOD = 266;
|
||||||
|
public final static int KEYCODE_KP_DIVIDE = 267;
|
||||||
|
public final static int KEYCODE_KP_MULTIPLY = 268;
|
||||||
|
public final static int KEYCODE_KP_MINUS = 269;
|
||||||
|
public final static int KEYCODE_KP_PLUS = 270;
|
||||||
|
public final static int KEYCODE_KP_ENTER = 271;
|
||||||
|
public final static int KEYCODE_KP_EQUALS = 272;
|
||||||
|
// Arrows + Home/End pad
|
||||||
|
public final static int KEYCODE_UP = 273;
|
||||||
|
public final static int KEYCODE_DOWN = 274;
|
||||||
|
public final static int KEYCODE_RIGHT = 275;
|
||||||
|
public final static int KEYCODE_LEFT = 276;
|
||||||
|
public final static int KEYCODE_INSERT = 277;
|
||||||
|
public final static int KEYCODE_HOME = 278;
|
||||||
|
public final static int KEYCODE_END = 279;
|
||||||
|
public final static int KEYCODE_PAGEUP = 280;
|
||||||
|
public final static int KEYCODE_PAGEDOWN = 281;
|
||||||
|
// Function keys
|
||||||
|
public final static int KEYCODE_F1 = 282;
|
||||||
|
public final static int KEYCODE_F2 = 283;
|
||||||
|
public final static int KEYCODE_F3 = 284;
|
||||||
|
public final static int KEYCODE_F4 = 285;
|
||||||
|
public final static int KEYCODE_F5 = 286;
|
||||||
|
public final static int KEYCODE_F6 = 287;
|
||||||
|
public final static int KEYCODE_F7 = 288;
|
||||||
|
public final static int KEYCODE_F8 = 289;
|
||||||
|
public final static int KEYCODE_F9 = 290;
|
||||||
|
public final static int KEYCODE_F10 = 291;
|
||||||
|
public final static int KEYCODE_F11 = 292;
|
||||||
|
public final static int KEYCODE_F12 = 293;
|
||||||
|
public final static int KEYCODE_F13 = 294;
|
||||||
|
public final static int KEYCODE_F14 = 295;
|
||||||
|
public final static int KEYCODE_F15 = 296;
|
||||||
|
// Key state modifier keys
|
||||||
|
public final static int KEYCODE_NUMLOCK = 300;
|
||||||
|
public final static int KEYCODE_CAPSLOCK = 301;
|
||||||
|
public final static int KEYCODE_SCROLLOCK = 302;
|
||||||
|
public final static int KEYCODE_RSHIFT = 303;
|
||||||
|
public final static int KEYCODE_LSHIFT = 304;
|
||||||
|
public final static int KEYCODE_RCTRL = 305;
|
||||||
|
public final static int KEYCODE_LCTRL = 306;
|
||||||
|
public final static int KEYCODE_RALT = 307;
|
||||||
|
public final static int KEYCODE_LALT = 308;
|
||||||
|
public final static int KEYCODE_RMETA = 309;
|
||||||
|
public final static int KEYCODE_LMETA = 310;
|
||||||
|
public final static int KEYCODE_LSUPER = 311; // Left "Windows" key
|
||||||
|
public final static int KEYCODE_RSUPER = 312; // Right "Windows" key
|
||||||
|
public final static int KEYCODE_MODE = 313; // "Alt Gr" key
|
||||||
|
public final static int KEYCODE_COMPOSE = 314; // Multi-key compose key
|
||||||
|
// Miscellaneous function keys
|
||||||
|
public final static int KEYCODE_HELP = 315;
|
||||||
|
public final static int KEYCODE_PRINT = 316;
|
||||||
|
public final static int KEYCODE_SYSREQ = 317;
|
||||||
|
public final static int KEYCODE_BREAK = 318;
|
||||||
|
public final static int KEYCODE_MENU = 319;
|
||||||
|
public final static int KEYCODE_POWER = 320; // Power Macintosh power key
|
||||||
|
public final static int KEYCODE_EURO = 321; // Some european keyboards
|
||||||
|
public final static int KEYCODE_UNDO = 322; // Atari keyboard has Undo
|
||||||
|
|
||||||
|
// Android KeyEvent keycode -> ScummVM keycode
|
||||||
|
public final static Map<Integer, Integer> androidKeyMap;
|
||||||
|
static {
|
||||||
|
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
|
||||||
|
|
||||||
|
map.put(KeyEvent.KEYCODE_DEL, KEYCODE_BACKSPACE);
|
||||||
|
map.put(KeyEvent.KEYCODE_TAB, KEYCODE_TAB);
|
||||||
|
map.put(KeyEvent.KEYCODE_CLEAR, KEYCODE_CLEAR);
|
||||||
|
map.put(KeyEvent.KEYCODE_ENTER, KEYCODE_RETURN);
|
||||||
|
//map.put(??, KEYCODE_PAUSE);
|
||||||
|
map.put(KeyEvent.KEYCODE_BACK, KEYCODE_ESCAPE);
|
||||||
|
map.put(KeyEvent.KEYCODE_SPACE, KEYCODE_SPACE);
|
||||||
|
//map.put(??, KEYCODE_EXCLAIM);
|
||||||
|
//map.put(??, KEYCODE_QUOTEDBL);
|
||||||
|
map.put(KeyEvent.KEYCODE_POUND, KEYCODE_HASH);
|
||||||
|
//map.put(??, KEYCODE_DOLLAR);
|
||||||
|
//map.put(??, KEYCODE_AMPERSAND);
|
||||||
|
map.put(KeyEvent.KEYCODE_APOSTROPHE, KEYCODE_QUOTE);
|
||||||
|
//map.put(??, KEYCODE_LEFTPAREN);
|
||||||
|
//map.put(??, KEYCODE_RIGHTPAREN);
|
||||||
|
//map.put(??, KEYCODE_ASTERISK);
|
||||||
|
map.put(KeyEvent.KEYCODE_PLUS, KEYCODE_PLUS);
|
||||||
|
map.put(KeyEvent.KEYCODE_COMMA, KEYCODE_COMMA);
|
||||||
|
map.put(KeyEvent.KEYCODE_MINUS, KEYCODE_MINUS);
|
||||||
|
map.put(KeyEvent.KEYCODE_PERIOD, KEYCODE_PERIOD);
|
||||||
|
map.put(KeyEvent.KEYCODE_SLASH, KEYCODE_SLASH);
|
||||||
|
map.put(KeyEvent.KEYCODE_0, KEYCODE_0);
|
||||||
|
map.put(KeyEvent.KEYCODE_1, KEYCODE_1);
|
||||||
|
map.put(KeyEvent.KEYCODE_2, KEYCODE_2);
|
||||||
|
map.put(KeyEvent.KEYCODE_3, KEYCODE_3);
|
||||||
|
map.put(KeyEvent.KEYCODE_4, KEYCODE_4);
|
||||||
|
map.put(KeyEvent.KEYCODE_5, KEYCODE_5);
|
||||||
|
map.put(KeyEvent.KEYCODE_6, KEYCODE_6);
|
||||||
|
map.put(KeyEvent.KEYCODE_7, KEYCODE_7);
|
||||||
|
map.put(KeyEvent.KEYCODE_8, KEYCODE_8);
|
||||||
|
map.put(KeyEvent.KEYCODE_9, KEYCODE_9);
|
||||||
|
//map.put(??, KEYCODE_COLON);
|
||||||
|
map.put(KeyEvent.KEYCODE_SEMICOLON, KEYCODE_SEMICOLON);
|
||||||
|
//map.put(??, KEYCODE_LESS);
|
||||||
|
map.put(KeyEvent.KEYCODE_EQUALS, KEYCODE_EQUALS);
|
||||||
|
//map.put(??, KEYCODE_GREATER);
|
||||||
|
//map.put(??, KEYCODE_QUESTION);
|
||||||
|
map.put(KeyEvent.KEYCODE_AT, KEYCODE_AT);
|
||||||
|
map.put(KeyEvent.KEYCODE_LEFT_BRACKET, KEYCODE_LEFTBRACKET);
|
||||||
|
map.put(KeyEvent.KEYCODE_BACKSLASH, KEYCODE_BACKSLASH);
|
||||||
|
map.put(KeyEvent.KEYCODE_RIGHT_BRACKET, KEYCODE_RIGHTBRACKET);
|
||||||
|
//map.put(??, KEYCODE_CARET);
|
||||||
|
//map.put(??, KEYCODE_UNDERSCORE);
|
||||||
|
//map.put(??, KEYCODE_BACKQUOTE);
|
||||||
|
map.put(KeyEvent.KEYCODE_A, KEYCODE_a);
|
||||||
|
map.put(KeyEvent.KEYCODE_B, KEYCODE_b);
|
||||||
|
map.put(KeyEvent.KEYCODE_C, KEYCODE_c);
|
||||||
|
map.put(KeyEvent.KEYCODE_D, KEYCODE_d);
|
||||||
|
map.put(KeyEvent.KEYCODE_E, KEYCODE_e);
|
||||||
|
map.put(KeyEvent.KEYCODE_F, KEYCODE_f);
|
||||||
|
map.put(KeyEvent.KEYCODE_G, KEYCODE_g);
|
||||||
|
map.put(KeyEvent.KEYCODE_H, KEYCODE_h);
|
||||||
|
map.put(KeyEvent.KEYCODE_I, KEYCODE_i);
|
||||||
|
map.put(KeyEvent.KEYCODE_J, KEYCODE_j);
|
||||||
|
map.put(KeyEvent.KEYCODE_K, KEYCODE_k);
|
||||||
|
map.put(KeyEvent.KEYCODE_L, KEYCODE_l);
|
||||||
|
map.put(KeyEvent.KEYCODE_M, KEYCODE_m);
|
||||||
|
map.put(KeyEvent.KEYCODE_N, KEYCODE_n);
|
||||||
|
map.put(KeyEvent.KEYCODE_O, KEYCODE_o);
|
||||||
|
map.put(KeyEvent.KEYCODE_P, KEYCODE_p);
|
||||||
|
map.put(KeyEvent.KEYCODE_Q, KEYCODE_q);
|
||||||
|
map.put(KeyEvent.KEYCODE_R, KEYCODE_r);
|
||||||
|
map.put(KeyEvent.KEYCODE_S, KEYCODE_s);
|
||||||
|
map.put(KeyEvent.KEYCODE_T, KEYCODE_t);
|
||||||
|
map.put(KeyEvent.KEYCODE_U, KEYCODE_u);
|
||||||
|
map.put(KeyEvent.KEYCODE_V, KEYCODE_v);
|
||||||
|
map.put(KeyEvent.KEYCODE_W, KEYCODE_w);
|
||||||
|
map.put(KeyEvent.KEYCODE_X, KEYCODE_x);
|
||||||
|
map.put(KeyEvent.KEYCODE_Y, KEYCODE_y);
|
||||||
|
map.put(KeyEvent.KEYCODE_Z, KEYCODE_z);
|
||||||
|
//map.put(KeyEvent.KEYCODE_DEL, KEYCODE_DELETE); use BACKSPACE instead
|
||||||
|
//map.put(??, KEYCODE_KP_*);
|
||||||
|
map.put(KeyEvent.KEYCODE_DPAD_UP, KEYCODE_UP);
|
||||||
|
map.put(KeyEvent.KEYCODE_DPAD_DOWN, KEYCODE_DOWN);
|
||||||
|
map.put(KeyEvent.KEYCODE_DPAD_RIGHT, KEYCODE_RIGHT);
|
||||||
|
map.put(KeyEvent.KEYCODE_DPAD_LEFT, KEYCODE_LEFT);
|
||||||
|
//map.put(??, KEYCODE_INSERT);
|
||||||
|
//map.put(??, KEYCODE_HOME);
|
||||||
|
//map.put(??, KEYCODE_END);
|
||||||
|
//map.put(??, KEYCODE_PAGEUP);
|
||||||
|
//map.put(??, KEYCODE_PAGEDOWN);
|
||||||
|
//map.put(??, KEYCODE_F{1-15});
|
||||||
|
map.put(KeyEvent.KEYCODE_NUM, KEYCODE_NUMLOCK);
|
||||||
|
//map.put(??, KEYCODE_CAPSLOCK);
|
||||||
|
//map.put(??, KEYCODE_SCROLLLOCK);
|
||||||
|
map.put(KeyEvent.KEYCODE_SHIFT_RIGHT, KEYCODE_RSHIFT);
|
||||||
|
map.put(KeyEvent.KEYCODE_SHIFT_LEFT, KEYCODE_LSHIFT);
|
||||||
|
//map.put(??, KEYCODE_RCTRL);
|
||||||
|
//map.put(??, KEYCODE_LCTRL);
|
||||||
|
map.put(KeyEvent.KEYCODE_ALT_RIGHT, KEYCODE_RALT);
|
||||||
|
map.put(KeyEvent.KEYCODE_ALT_LEFT, KEYCODE_LALT);
|
||||||
|
// ?? META, SUPER
|
||||||
|
// ?? MODE, COMPOSE
|
||||||
|
// ?? HELP, PRINT, SYSREQ, BREAK, EURO, UNDO
|
||||||
|
map.put(KeyEvent.KEYCODE_MENU, KEYCODE_MENU);
|
||||||
|
map.put(KeyEvent.KEYCODE_POWER, KEYCODE_POWER);
|
||||||
|
|
||||||
|
androidKeyMap = Collections.unmodifiableMap(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int type;
|
||||||
|
public boolean synthetic;
|
||||||
|
public int kbd_keycode;
|
||||||
|
public int kbd_ascii;
|
||||||
|
public int kbd_flags;
|
||||||
|
public int mouse_x;
|
||||||
|
public int mouse_y;
|
||||||
|
public boolean mouse_relative; // Used for trackball events
|
||||||
|
|
||||||
|
public Event() {
|
||||||
|
type = EVENT_INVALID;
|
||||||
|
synthetic = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Event(int type) {
|
||||||
|
this.type = type;
|
||||||
|
synthetic = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Event KeyboardEvent(int type, int keycode, int ascii,
|
||||||
|
int flags) {
|
||||||
|
Event e = new Event();
|
||||||
|
e.type = type;
|
||||||
|
e.kbd_keycode = keycode;
|
||||||
|
e.kbd_ascii = ascii;
|
||||||
|
e.kbd_flags = flags;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Event MouseEvent(int type, int x, int y) {
|
||||||
|
Event e = new Event();
|
||||||
|
e.type = type;
|
||||||
|
e.mouse_x = x;
|
||||||
|
e.mouse_y = y;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class PluginProvider extends BroadcastReceiver {
|
||||||
|
public final static String META_UNPACK_LIB =
|
||||||
|
"org.inodes.gus.scummvm.meta.UNPACK_LIB";
|
||||||
|
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (!intent.getAction().equals(ScummVMApplication.ACTION_PLUGIN_QUERY))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bundle extras = getResultExtras(true);
|
||||||
|
|
||||||
|
final ActivityInfo info;
|
||||||
|
try {
|
||||||
|
info = context.getPackageManager()
|
||||||
|
.getReceiverInfo(new ComponentName(context, this.getClass()),
|
||||||
|
PackageManager.GET_META_DATA);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.e(this.toString(), "Error finding my own info?", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String mylib = info.metaData.getString(META_UNPACK_LIB);
|
||||||
|
if (mylib != null) {
|
||||||
|
ArrayList<String> all_libs =
|
||||||
|
extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
|
||||||
|
|
||||||
|
all_libs.add(new Uri.Builder()
|
||||||
|
.scheme("plugin")
|
||||||
|
.authority(context.getPackageName())
|
||||||
|
.path(mylib)
|
||||||
|
.toString());
|
||||||
|
|
||||||
|
extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
|
||||||
|
all_libs);
|
||||||
|
}
|
||||||
|
|
||||||
|
setResultExtras(extras);
|
||||||
|
}
|
||||||
|
}
|
317
backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
Normal file
317
backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
Normal file
@ -0,0 +1,317 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.media.AudioFormat;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.AudioTrack;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Process;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.SurfaceHolder;
|
||||||
|
|
||||||
|
import javax.microedition.khronos.egl.EGL10;
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
|
import javax.microedition.khronos.egl.EGLContext;
|
||||||
|
import javax.microedition.khronos.egl.EGLDisplay;
|
||||||
|
import javax.microedition.khronos.egl.EGLSurface;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
|
||||||
|
// At least in Android 2.1, eglCreateWindowSurface() requires an
|
||||||
|
// EGLNativeWindowSurface object, which is hidden deep in the bowels
|
||||||
|
// of libui. Until EGL is properly exposed, it's probably safer to
|
||||||
|
// use the Java versions of most EGL functions :(
|
||||||
|
|
||||||
|
public class ScummVM implements SurfaceHolder.Callback {
|
||||||
|
private final static String LOG_TAG = "ScummVM.java";
|
||||||
|
|
||||||
|
private final int AUDIO_FRAME_SIZE = 2 * 2; // bytes. 16bit audio * stereo
|
||||||
|
public static class AudioSetupException extends Exception {}
|
||||||
|
|
||||||
|
private long nativeScummVM; // native code hangs itself here
|
||||||
|
boolean scummVMRunning = false;
|
||||||
|
|
||||||
|
private native void create(AssetManager am);
|
||||||
|
|
||||||
|
public ScummVM(Context context) {
|
||||||
|
create(context.getAssets()); // Init C++ code, set nativeScummVM
|
||||||
|
}
|
||||||
|
|
||||||
|
private native void nativeDestroy();
|
||||||
|
|
||||||
|
public synchronized void destroy() {
|
||||||
|
if (nativeScummVM != 0) {
|
||||||
|
nativeDestroy();
|
||||||
|
nativeScummVM = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected void finalize() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surface creation:
|
||||||
|
// GUI thread: create surface, release lock
|
||||||
|
// ScummVM thread: acquire lock (block), read surface
|
||||||
|
//
|
||||||
|
// Surface deletion:
|
||||||
|
// GUI thread: post event, acquire lock (block), return
|
||||||
|
// ScummVM thread: read event, free surface, release lock
|
||||||
|
//
|
||||||
|
// In other words, ScummVM thread does this:
|
||||||
|
// acquire lock
|
||||||
|
// setup surface
|
||||||
|
// when SCREEN_CHANGED arrives:
|
||||||
|
// destroy surface
|
||||||
|
// release lock
|
||||||
|
// back to acquire lock
|
||||||
|
static final int configSpec[] = {
|
||||||
|
EGL10.EGL_RED_SIZE, 5,
|
||||||
|
EGL10.EGL_GREEN_SIZE, 5,
|
||||||
|
EGL10.EGL_BLUE_SIZE, 5,
|
||||||
|
EGL10.EGL_DEPTH_SIZE, 0,
|
||||||
|
EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT,
|
||||||
|
EGL10.EGL_NONE,
|
||||||
|
};
|
||||||
|
EGL10 egl;
|
||||||
|
EGLDisplay eglDisplay = EGL10.EGL_NO_DISPLAY;
|
||||||
|
EGLConfig eglConfig;
|
||||||
|
EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
|
||||||
|
EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
|
||||||
|
Semaphore surfaceLock = new Semaphore(0, true);
|
||||||
|
SurfaceHolder nativeSurface;
|
||||||
|
|
||||||
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
|
nativeSurface = holder;
|
||||||
|
surfaceLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void surfaceChanged(SurfaceHolder holder, int format,
|
||||||
|
int width, int height) {
|
||||||
|
// Disabled while I debug GL problems
|
||||||
|
//pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
|
pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
|
||||||
|
try {
|
||||||
|
surfaceLock.acquire();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(this.toString(),
|
||||||
|
"Interrupted while waiting for surface lock", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by ScummVM thread (from initBackend)
|
||||||
|
private void createScummVMGLContext() {
|
||||||
|
egl = (EGL10)EGLContext.getEGL();
|
||||||
|
eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
|
||||||
|
int[] version = new int[2];
|
||||||
|
egl.eglInitialize(eglDisplay, version);
|
||||||
|
int[] num_config = new int[1];
|
||||||
|
egl.eglChooseConfig(eglDisplay, configSpec, null, 0, num_config);
|
||||||
|
|
||||||
|
final int numConfigs = num_config[0];
|
||||||
|
if (numConfigs <= 0)
|
||||||
|
throw new IllegalArgumentException("No configs match configSpec");
|
||||||
|
|
||||||
|
EGLConfig[] configs = new EGLConfig[numConfigs];
|
||||||
|
egl.eglChooseConfig(eglDisplay, configSpec, configs, numConfigs,
|
||||||
|
num_config);
|
||||||
|
eglConfig = configs[0];
|
||||||
|
|
||||||
|
eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
|
||||||
|
EGL10.EGL_NO_CONTEXT, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by ScummVM thread
|
||||||
|
protected void setupScummVMSurface() {
|
||||||
|
try {
|
||||||
|
surfaceLock.acquire();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(this.toString(),
|
||||||
|
"Interrupted while waiting for surface lock", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
|
||||||
|
nativeSurface, null);
|
||||||
|
egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by ScummVM thread
|
||||||
|
protected void destroyScummVMSurface() {
|
||||||
|
if (eglSurface != null) {
|
||||||
|
egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
|
||||||
|
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
|
||||||
|
egl.eglDestroySurface(eglDisplay, eglSurface);
|
||||||
|
eglSurface = EGL10.EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
surfaceLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurface(SurfaceHolder holder) {
|
||||||
|
holder.addCallback(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set scummvm config options
|
||||||
|
final public native static void loadConfigFile(String path);
|
||||||
|
final public native static void setConfMan(String key, int value);
|
||||||
|
final public native static void setConfMan(String key, String value);
|
||||||
|
|
||||||
|
// Feed an event to ScummVM. Safe to call from other threads.
|
||||||
|
final public native void pushEvent(Event e);
|
||||||
|
|
||||||
|
final private native void audioMixCallback(byte[] buf);
|
||||||
|
|
||||||
|
// Runs the actual ScummVM program and returns when it does.
|
||||||
|
// This should not be called from multiple threads simultaneously...
|
||||||
|
final public native int scummVMMain(String[] argv);
|
||||||
|
|
||||||
|
// Callbacks from C++ peer instance
|
||||||
|
//protected GraphicsMode[] getSupportedGraphicsModes() {}
|
||||||
|
protected void displayMessageOnOSD(String msg) {}
|
||||||
|
protected void setWindowCaption(String caption) {}
|
||||||
|
protected void showVirtualKeyboard(boolean enable) {}
|
||||||
|
protected String[] getSysArchives() { return new String[0]; }
|
||||||
|
protected String[] getPluginDirectories() { return new String[0]; }
|
||||||
|
protected void initBackend() throws AudioSetupException {
|
||||||
|
createScummVMGLContext();
|
||||||
|
initAudio();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AudioThread extends Thread {
|
||||||
|
final private int buf_size;
|
||||||
|
private boolean is_paused = false;
|
||||||
|
final private ScummVM scummvm;
|
||||||
|
final private AudioTrack audio_track;
|
||||||
|
|
||||||
|
AudioThread(ScummVM scummvm, AudioTrack audio_track, int buf_size) {
|
||||||
|
super("AudioThread");
|
||||||
|
this.scummvm = scummvm;
|
||||||
|
this.audio_track = audio_track;
|
||||||
|
this.buf_size = buf_size;
|
||||||
|
setPriority(Thread.MAX_PRIORITY);
|
||||||
|
setDaemon(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pauseAudio() {
|
||||||
|
synchronized (this) {
|
||||||
|
is_paused = true;
|
||||||
|
}
|
||||||
|
audio_track.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resumeAudio() {
|
||||||
|
synchronized (this) {
|
||||||
|
is_paused = false;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
audio_track.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
byte[] buf = new byte[buf_size];
|
||||||
|
audio_track.play();
|
||||||
|
int offset = 0;
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
synchronized (this) {
|
||||||
|
while (is_paused)
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == buf.length) {
|
||||||
|
// Grab new audio data
|
||||||
|
scummvm.audioMixCallback(buf);
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
int len = buf.length - offset;
|
||||||
|
int ret = audio_track.write(buf, offset, len);
|
||||||
|
if (ret < 0) {
|
||||||
|
Log.w(LOG_TAG, String.format(
|
||||||
|
"AudioTrack.write(%dB) returned error %d",
|
||||||
|
buf.length, ret));
|
||||||
|
break;
|
||||||
|
} else if (ret != len) {
|
||||||
|
Log.w(LOG_TAG, String.format(
|
||||||
|
"Short audio write. Wrote %dB, not %dB",
|
||||||
|
ret, buf.length));
|
||||||
|
// Buffer is full, so yield cpu for a while
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
offset += ret;
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(this.toString(), "Audio thread interrupted", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private AudioThread audio_thread;
|
||||||
|
|
||||||
|
final public int audioSampleRate() {
|
||||||
|
return AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAudio() throws AudioSetupException {
|
||||||
|
int sample_rate = audioSampleRate();
|
||||||
|
int buf_size =
|
||||||
|
AudioTrack.getMinBufferSize(sample_rate,
|
||||||
|
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
|
||||||
|
AudioFormat.ENCODING_PCM_16BIT);
|
||||||
|
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));
|
||||||
|
buf_size = guess;
|
||||||
|
}
|
||||||
|
Log.d(LOG_TAG, String.format("Using %dB buffer for %dHZ audio",
|
||||||
|
buf_size, sample_rate));
|
||||||
|
AudioTrack audio_track =
|
||||||
|
new AudioTrack(AudioManager.STREAM_MUSIC,
|
||||||
|
sample_rate,
|
||||||
|
AudioFormat.CHANNEL_CONFIGURATION_STEREO,
|
||||||
|
AudioFormat.ENCODING_PCM_16BIT,
|
||||||
|
buf_size,
|
||||||
|
AudioTrack.MODE_STREAM);
|
||||||
|
if (audio_track.getState() != AudioTrack.STATE_INITIALIZED) {
|
||||||
|
Log.e(LOG_TAG, "Error initialising Android audio system.");
|
||||||
|
throw new AudioSetupException();
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_thread = new AudioThread(this, audio_track, buf_size);
|
||||||
|
audio_thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pause() {
|
||||||
|
audio_thread.pauseAudio();
|
||||||
|
// TODO: need to pause engine too
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resume() {
|
||||||
|
// TODO: need to resume engine too
|
||||||
|
audio_thread.resumeAudio();
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
// For grabbing with gdb...
|
||||||
|
final boolean sleep_for_debugger = false;
|
||||||
|
if (sleep_for_debugger) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(20*1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.loadLibrary("scummvm");
|
||||||
|
File cache_dir = ScummVMApplication.getLastCacheDir();
|
||||||
|
String libname = System.mapLibraryName("scummvm");
|
||||||
|
File libpath = new File(cache_dir, libname);
|
||||||
|
System.load(libpath.getPath());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,446 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class ScummVMActivity extends Activity {
|
||||||
|
private boolean _do_right_click;
|
||||||
|
private boolean _last_click_was_right;
|
||||||
|
|
||||||
|
// game pixels to move per trackball/dpad event.
|
||||||
|
// FIXME: replace this with proper mouse acceleration
|
||||||
|
private final static int TRACKBALL_SCALE = 2;
|
||||||
|
|
||||||
|
private class MyScummVM extends ScummVM {
|
||||||
|
private boolean scummvmRunning = false;
|
||||||
|
|
||||||
|
public MyScummVM() {
|
||||||
|
super(ScummVMActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initBackend() throws ScummVM.AudioSetupException {
|
||||||
|
synchronized (this) {
|
||||||
|
scummvmRunning = true;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
super.initBackend();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitUntilRunning() throws InterruptedException {
|
||||||
|
synchronized (this) {
|
||||||
|
while (!scummvmRunning)
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void displayMessageOnOSD(String msg) {
|
||||||
|
Log.i(this.toString(), "OSD: " + msg);
|
||||||
|
Toast.makeText(ScummVMActivity.this, msg, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setWindowCaption(final String caption) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
setTitle(caption);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String[] getPluginDirectories() {
|
||||||
|
String[] dirs = new String[1];
|
||||||
|
dirs[0] = ScummVMApplication.getLastCacheDir().getPath();
|
||||||
|
return dirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void showVirtualKeyboard(final boolean enable) {
|
||||||
|
if (getResources().getConfiguration().keyboard ==
|
||||||
|
Configuration.KEYBOARD_NOKEYS) {
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
showKeyboard(enable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private MyScummVM scummvm;
|
||||||
|
private Thread scummvm_thread;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
_do_right_click = false;
|
||||||
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
|
setContentView(R.layout.main);
|
||||||
|
takeKeyEvents(true);
|
||||||
|
|
||||||
|
// This is a common enough error that we should warn about it
|
||||||
|
// explicitly.
|
||||||
|
if (!Environment.getExternalStorageDirectory().canRead()) {
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.no_sdcard_title)
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setMessage(R.string.no_sdcard)
|
||||||
|
.setNegativeButton(R.string.quit,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog,
|
||||||
|
int which) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
|
||||||
|
main_surface.setOnTouchListener(new View.OnTouchListener() {
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
return onTouchEvent(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
main_surface.setOnKeyListener(new View.OnKeyListener() {
|
||||||
|
public boolean onKey(View v, int code, KeyEvent ev) {
|
||||||
|
return onKeyDown(code, ev);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
main_surface.requestFocus();
|
||||||
|
|
||||||
|
// Start ScummVM
|
||||||
|
scummvm = new MyScummVM();
|
||||||
|
scummvm_thread = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
runScummVM();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("ScummVM", "Fatal error in ScummVM thread", e);
|
||||||
|
new AlertDialog.Builder(ScummVMActivity.this)
|
||||||
|
.setTitle("Error")
|
||||||
|
.setMessage(e.toString())
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.show();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, "ScummVM");
|
||||||
|
scummvm_thread.start();
|
||||||
|
|
||||||
|
// Block UI thread until ScummVM has started. In particular,
|
||||||
|
// this means that surface and event callbacks should be safe
|
||||||
|
// after this point.
|
||||||
|
try {
|
||||||
|
scummvm.waitUntilRunning();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(this.toString(),
|
||||||
|
"Interrupted while waiting for ScummVM.initBackend", e);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
scummvm.setSurface(main_surface.getHolder());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Runs in another thread
|
||||||
|
private void runScummVM() throws IOException {
|
||||||
|
getFilesDir().mkdirs();
|
||||||
|
String[] args = {
|
||||||
|
"ScummVM-lib",
|
||||||
|
"--config=" + getFileStreamPath("scummvmrc").getPath(),
|
||||||
|
"--path=" + Environment.getExternalStorageDirectory().getPath(),
|
||||||
|
"--gui-theme=scummmodern",
|
||||||
|
"--savepath=" + getDir("saves", 0).getPath(),
|
||||||
|
};
|
||||||
|
|
||||||
|
int ret = scummvm.scummVMMain(args);
|
||||||
|
|
||||||
|
// On exit, tear everything down for a fresh
|
||||||
|
// restart next time.
|
||||||
|
System.exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean was_paused = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
if (scummvm != null) {
|
||||||
|
was_paused = true;
|
||||||
|
scummvm.pause();
|
||||||
|
}
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (scummvm != null && was_paused)
|
||||||
|
scummvm.resume();
|
||||||
|
was_paused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
if (scummvm != null) {
|
||||||
|
scummvm.pushEvent(new Event(Event.EVENT_QUIT));
|
||||||
|
try {
|
||||||
|
scummvm_thread.join(1000); // 1s timeout
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.i(this.toString(),
|
||||||
|
"Error while joining ScummVM thread", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final int MSG_MENU_LONG_PRESS = 1;
|
||||||
|
private final Handler keycodeMenuTimeoutHandler = new Handler() {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
if (msg.what == MSG_MENU_LONG_PRESS) {
|
||||||
|
InputMethodManager imm = (InputMethodManager)
|
||||||
|
getSystemService(INPUT_METHOD_SERVICE);
|
||||||
|
if (imm != null)
|
||||||
|
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyUp(int keyCode, KeyEvent kevent) {
|
||||||
|
return onKeyDown(keyCode, kevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyMultiple(int keyCode, int repeatCount,
|
||||||
|
KeyEvent kevent) {
|
||||||
|
return onKeyDown(keyCode, kevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onKeyDown(int keyCode, KeyEvent kevent) {
|
||||||
|
// Filter out "special" keys
|
||||||
|
switch (keyCode) {
|
||||||
|
case KeyEvent.KEYCODE_MENU:
|
||||||
|
// Have to reimplement hold-down-menu-brings-up-softkeybd
|
||||||
|
// ourselves, since we are otherwise hijacking the menu
|
||||||
|
// key :(
|
||||||
|
// See com.android.internal.policy.impl.PhoneWindow.onKeyDownPanel()
|
||||||
|
// for the usual Android implementation of this feature.
|
||||||
|
if (kevent.getRepeatCount() > 0)
|
||||||
|
// Ignore keyrepeat for menu
|
||||||
|
return false;
|
||||||
|
boolean timeout_fired = false;
|
||||||
|
if (getResources().getConfiguration().keyboard ==
|
||||||
|
Configuration.KEYBOARD_NOKEYS) {
|
||||||
|
timeout_fired = !keycodeMenuTimeoutHandler.hasMessages(MSG_MENU_LONG_PRESS);
|
||||||
|
keycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
|
||||||
|
if (kevent.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
keycodeMenuTimeoutHandler.sendMessageDelayed(
|
||||||
|
keycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
|
||||||
|
ViewConfiguration.getLongPressTimeout());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (kevent.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
if (!timeout_fired)
|
||||||
|
scummvm.pushEvent(new Event(Event.EVENT_MAINMENU));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case KeyEvent.KEYCODE_CAMERA:
|
||||||
|
case KeyEvent.KEYCODE_SEARCH:
|
||||||
|
_do_right_click = (kevent.getAction() == KeyEvent.ACTION_DOWN);
|
||||||
|
return true;
|
||||||
|
case KeyEvent.KEYCODE_DPAD_CENTER:
|
||||||
|
case KeyEvent.KEYCODE_DPAD_UP:
|
||||||
|
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||||
|
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||||
|
case KeyEvent.KEYCODE_DPAD_RIGHT: {
|
||||||
|
// HTC Hero doesn't seem to generate
|
||||||
|
// MotionEvent.ACTION_DOWN events on trackball press :(
|
||||||
|
// We'll have to just fake one here.
|
||||||
|
// Some other handsets lack a trackball, so the DPAD is
|
||||||
|
// the only way of moving the cursor.
|
||||||
|
int motion_action;
|
||||||
|
// FIXME: this logic is a mess.
|
||||||
|
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
|
||||||
|
switch (kevent.getAction()) {
|
||||||
|
case KeyEvent.ACTION_DOWN:
|
||||||
|
motion_action = MotionEvent.ACTION_DOWN;
|
||||||
|
break;
|
||||||
|
case KeyEvent.ACTION_UP:
|
||||||
|
motion_action = MotionEvent.ACTION_UP;
|
||||||
|
break;
|
||||||
|
default: // ACTION_MULTIPLE
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
motion_action = MotionEvent.ACTION_MOVE;
|
||||||
|
|
||||||
|
Event e = new Event(getEventType(motion_action));
|
||||||
|
e.mouse_x = 0;
|
||||||
|
e.mouse_y = 0;
|
||||||
|
e.mouse_relative = true;
|
||||||
|
switch (keyCode) {
|
||||||
|
case KeyEvent.KEYCODE_DPAD_UP:
|
||||||
|
e.mouse_y = -TRACKBALL_SCALE;
|
||||||
|
break;
|
||||||
|
case KeyEvent.KEYCODE_DPAD_DOWN:
|
||||||
|
e.mouse_y = TRACKBALL_SCALE;
|
||||||
|
break;
|
||||||
|
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||||
|
e.mouse_x = -TRACKBALL_SCALE;
|
||||||
|
break;
|
||||||
|
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||||
|
e.mouse_x = TRACKBALL_SCALE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scummvm.pushEvent(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case KeyEvent.KEYCODE_BACK:
|
||||||
|
// skip isSystem() check and fall through to main code
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (kevent.isSystem())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: what do I need to do for composed characters?
|
||||||
|
|
||||||
|
Event e = new Event();
|
||||||
|
|
||||||
|
switch (kevent.getAction()) {
|
||||||
|
case KeyEvent.ACTION_DOWN:
|
||||||
|
e.type = Event.EVENT_KEYDOWN;
|
||||||
|
e.synthetic = false;
|
||||||
|
break;
|
||||||
|
case KeyEvent.ACTION_UP:
|
||||||
|
e.type = Event.EVENT_KEYUP;
|
||||||
|
e.synthetic = false;
|
||||||
|
break;
|
||||||
|
case KeyEvent.ACTION_MULTIPLE:
|
||||||
|
// e.type is handled below
|
||||||
|
e.synthetic = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.kbd_keycode = Event.androidKeyMap.containsKey(keyCode) ?
|
||||||
|
Event.androidKeyMap.get(keyCode) : Event.KEYCODE_INVALID;
|
||||||
|
e.kbd_ascii = kevent.getUnicodeChar();
|
||||||
|
if (e.kbd_ascii == 0)
|
||||||
|
e.kbd_ascii = e.kbd_keycode; // scummvm keycodes are mostly ascii
|
||||||
|
|
||||||
|
|
||||||
|
e.kbd_flags = 0;
|
||||||
|
if (kevent.isAltPressed())
|
||||||
|
e.kbd_flags |= Event.KBD_ALT;
|
||||||
|
if (kevent.isSymPressed()) // no ctrl key in android, so use sym (?)
|
||||||
|
e.kbd_flags |= Event.KBD_CTRL;
|
||||||
|
if (kevent.isShiftPressed()) {
|
||||||
|
if (keyCode >= KeyEvent.KEYCODE_0 &&
|
||||||
|
keyCode <= KeyEvent.KEYCODE_9) {
|
||||||
|
// Shift+number -> convert to F* key
|
||||||
|
int offset = keyCode == KeyEvent.KEYCODE_0 ?
|
||||||
|
10 : keyCode - KeyEvent.KEYCODE_1; // turn 0 into 10
|
||||||
|
e.kbd_keycode = Event.KEYCODE_F1 + offset;
|
||||||
|
e.kbd_ascii = Event.ASCII_F1 + offset;
|
||||||
|
} else
|
||||||
|
e.kbd_flags |= Event.KBD_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kevent.getAction() == KeyEvent.ACTION_MULTIPLE) {
|
||||||
|
for (int i = 0; i <= kevent.getRepeatCount(); i++) {
|
||||||
|
e.type = Event.EVENT_KEYDOWN;
|
||||||
|
scummvm.pushEvent(e);
|
||||||
|
e.type = Event.EVENT_KEYUP;
|
||||||
|
scummvm.pushEvent(e);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
scummvm.pushEvent(e);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getEventType(int action) {
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
_last_click_was_right = _do_right_click;
|
||||||
|
return _last_click_was_right ?
|
||||||
|
Event.EVENT_RBUTTONDOWN : Event.EVENT_LBUTTONDOWN;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
return _last_click_was_right ?
|
||||||
|
Event.EVENT_RBUTTONUP : Event.EVENT_LBUTTONUP;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
return Event.EVENT_MOUSEMOVE;
|
||||||
|
default:
|
||||||
|
return Event.EVENT_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTrackballEvent(MotionEvent event) {
|
||||||
|
int type = getEventType(event.getAction());
|
||||||
|
if (type == Event.EVENT_INVALID)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Event e = new Event(type);
|
||||||
|
e.mouse_x =
|
||||||
|
(int)(event.getX() * event.getXPrecision()) * TRACKBALL_SCALE;
|
||||||
|
e.mouse_y =
|
||||||
|
(int)(event.getY() * event.getYPrecision()) * TRACKBALL_SCALE;
|
||||||
|
e.mouse_relative = true;
|
||||||
|
scummvm.pushEvent(e);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
int type = getEventType(event.getAction());
|
||||||
|
if (type == Event.EVENT_INVALID)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Event e = new Event(type);
|
||||||
|
e.mouse_x = (int)event.getX();
|
||||||
|
e.mouse_y = (int)event.getY();
|
||||||
|
e.mouse_relative = false;
|
||||||
|
scummvm.pushEvent(e);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showKeyboard(boolean show) {
|
||||||
|
SurfaceView main_surface = (SurfaceView)findViewById(R.id.main_surface);
|
||||||
|
InputMethodManager imm = (InputMethodManager)
|
||||||
|
getSystemService(INPUT_METHOD_SERVICE);
|
||||||
|
if (show)
|
||||||
|
imm.showSoftInput(main_surface, InputMethodManager.SHOW_IMPLICIT);
|
||||||
|
else
|
||||||
|
imm.hideSoftInputFromWindow(main_surface.getWindowToken(),
|
||||||
|
InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class ScummVMApplication extends Application {
|
||||||
|
public final static String ACTION_PLUGIN_QUERY = "org.inodes.gus.scummvm.action.PLUGIN_QUERY";
|
||||||
|
public final static String EXTRA_UNPACK_LIBS = "org.inodes.gus.scummvm.extra.UNPACK_LIBS";
|
||||||
|
|
||||||
|
private static File cache_dir;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
// This is still on /data :(
|
||||||
|
cache_dir = getCacheDir();
|
||||||
|
// This is mounted noexec :(
|
||||||
|
//cache_dir = new File(Environment.getExternalStorageDirectory(),
|
||||||
|
// "/.ScummVM.tmp");
|
||||||
|
// This is owned by download manager and requires special
|
||||||
|
// permissions to access :(
|
||||||
|
//cache_dir = Environment.getDownloadCacheDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getLastCacheDir() {
|
||||||
|
return cache_dir;
|
||||||
|
}
|
||||||
|
}
|
370
backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
Normal file
370
backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
package org.inodes.gus.scummvm;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
|
public class Unpacker extends Activity {
|
||||||
|
private final static String META_NEXT_ACTIVITY =
|
||||||
|
"org.inodes.gus.unpacker.nextActivity";
|
||||||
|
private ProgressBar mProgress;
|
||||||
|
private File mUnpackDest; // location to unpack into
|
||||||
|
private AsyncTask<String, Integer, Void> mUnpacker;
|
||||||
|
private final static int REQUEST_MARKET = 1;
|
||||||
|
|
||||||
|
private static class UnpackJob {
|
||||||
|
public ZipFile zipfile;
|
||||||
|
public Set<String> paths;
|
||||||
|
|
||||||
|
public UnpackJob(ZipFile zipfile, Set<String> paths) {
|
||||||
|
this.zipfile = zipfile;
|
||||||
|
this.paths = paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long UnpackSize() {
|
||||||
|
long size = 0;
|
||||||
|
for (String path: paths) {
|
||||||
|
ZipEntry entry = zipfile.getEntry(path);
|
||||||
|
if (entry != null) size += entry.getSize();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UnpackTask extends AsyncTask<String, Integer, Void> {
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
|
mProgress.setIndeterminate(false);
|
||||||
|
mProgress.setMax(progress[1]);
|
||||||
|
mProgress.setProgress(progress[0]);
|
||||||
|
mProgress.postInvalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void result) {
|
||||||
|
Bundle md = getMetaData();
|
||||||
|
String nextActivity = md.getString(META_NEXT_ACTIVITY);
|
||||||
|
if (nextActivity != null) {
|
||||||
|
final ComponentName cn =
|
||||||
|
ComponentName.unflattenFromString(nextActivity);
|
||||||
|
if (cn != null) {
|
||||||
|
final Intent origIntent = getIntent();
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setPackage(origIntent.getPackage());
|
||||||
|
intent.setComponent(cn);
|
||||||
|
if (origIntent.getExtras() != null)
|
||||||
|
intent.putExtras(origIntent.getExtras());
|
||||||
|
intent.putExtra(Intent.EXTRA_INTENT, origIntent);
|
||||||
|
intent.setDataAndType(origIntent.getData(),
|
||||||
|
origIntent.getType());
|
||||||
|
//intent.fillIn(getIntent(), 0);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
|
||||||
|
Log.i(this.toString(),
|
||||||
|
"Starting next activity with intent " + intent);
|
||||||
|
startActivity(intent);
|
||||||
|
} else {
|
||||||
|
Log.w(this.toString(),
|
||||||
|
"Unable to extract a component name from " + nextActivity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(String... all_libs) {
|
||||||
|
// This will contain all unpack jobs
|
||||||
|
Map<String, UnpackJob> unpack_jobs =
|
||||||
|
new HashMap<String, UnpackJob>(all_libs.length);
|
||||||
|
|
||||||
|
// This will contain all unpack filenames (so we can
|
||||||
|
// detect stale files in the unpack directory)
|
||||||
|
Set<String> all_files = new HashSet<String>(all_libs.length);
|
||||||
|
|
||||||
|
for (String lib: all_libs) {
|
||||||
|
final Uri uri = Uri.parse(lib);
|
||||||
|
final String pkg = uri.getAuthority();
|
||||||
|
final String path = uri.getPath().substring(1); // skip first /
|
||||||
|
|
||||||
|
all_files.add(new File(path).getName());
|
||||||
|
|
||||||
|
UnpackJob job = unpack_jobs.get(pkg);
|
||||||
|
if (job == null) {
|
||||||
|
try {
|
||||||
|
// getPackageResourcePath is hidden in Context,
|
||||||
|
// but exposed in ContextWrapper...
|
||||||
|
ContextWrapper context =
|
||||||
|
new ContextWrapper(createPackageContext(pkg, 0));
|
||||||
|
ZipFile zipfile =
|
||||||
|
new ZipFile(context.getPackageResourcePath());
|
||||||
|
job = new UnpackJob(zipfile, new HashSet<String>(1));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.e(this.toString(), "Package " + pkg +
|
||||||
|
" not found", e);
|
||||||
|
continue;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// FIXME: show some sort of GUI error dialog
|
||||||
|
Log.e(this.toString(),
|
||||||
|
"Error opening ZIP for package " + pkg, e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unpack_jobs.put(pkg, job);
|
||||||
|
}
|
||||||
|
job.paths.add(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete stale filenames from mUnpackDest
|
||||||
|
for (File file: mUnpackDest.listFiles()) {
|
||||||
|
if (!all_files.contains(file.getName())) {
|
||||||
|
Log.i(this.toString(),
|
||||||
|
"Deleting stale cached file " + file);
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int total_size = 0;
|
||||||
|
for (UnpackJob job: unpack_jobs.values())
|
||||||
|
total_size += job.UnpackSize();
|
||||||
|
|
||||||
|
publishProgress(0, total_size);
|
||||||
|
|
||||||
|
mUnpackDest.mkdirs();
|
||||||
|
|
||||||
|
int progress = 0;
|
||||||
|
|
||||||
|
for (UnpackJob job: unpack_jobs.values()) {
|
||||||
|
try {
|
||||||
|
ZipFile zipfile = job.zipfile;
|
||||||
|
for (String path: job.paths) {
|
||||||
|
ZipEntry zipentry = zipfile.getEntry(path);
|
||||||
|
if (zipentry == null)
|
||||||
|
throw new FileNotFoundException(
|
||||||
|
"Couldn't find " + path + " in zip");
|
||||||
|
File dest = new File(mUnpackDest, new File(path).getName());
|
||||||
|
if (dest.exists() &&
|
||||||
|
dest.lastModified() == zipentry.getTime() &&
|
||||||
|
dest.length() == zipentry.getSize()) {
|
||||||
|
// Already unpacked
|
||||||
|
progress += zipentry.getSize();
|
||||||
|
} else {
|
||||||
|
if (dest.exists())
|
||||||
|
Log.d(this.toString(),
|
||||||
|
"Replacing " + dest.getPath() +
|
||||||
|
" old.mtime=" + dest.lastModified() +
|
||||||
|
" new.mtime=" + zipentry.getTime() +
|
||||||
|
" old.size=" + dest.length() +
|
||||||
|
" new.size=" + zipentry.getSize());
|
||||||
|
else
|
||||||
|
Log.i(this.toString(),
|
||||||
|
"Extracting " + zipentry.getName() +
|
||||||
|
" from " + zipfile.getName() +
|
||||||
|
" to " + dest.getPath());
|
||||||
|
|
||||||
|
long next_update = progress;
|
||||||
|
|
||||||
|
InputStream in = zipfile.getInputStream(zipentry);
|
||||||
|
OutputStream out = new FileOutputStream(dest);
|
||||||
|
int len;
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
while ((len = in.read(buffer)) != -1) {
|
||||||
|
out.write(buffer, 0, len);
|
||||||
|
progress += len;
|
||||||
|
if (progress >= next_update) {
|
||||||
|
publishProgress(progress, total_size);
|
||||||
|
// Arbitrary limit of 2% update steps
|
||||||
|
next_update += total_size / 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
dest.setLastModified(zipentry.getTime());
|
||||||
|
}
|
||||||
|
publishProgress(progress, total_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
zipfile.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// FIXME: show some sort of GUI error dialog
|
||||||
|
Log.e(this.toString(), "Error unpacking plugin", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progress != total_size)
|
||||||
|
Log.d(this.toString(), "Ended with progress " + progress +
|
||||||
|
" != total size " + total_size);
|
||||||
|
|
||||||
|
setResult(RESULT_OK);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PluginBroadcastReciever extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (!intent.getAction()
|
||||||
|
.equals(ScummVMApplication.ACTION_PLUGIN_QUERY)) {
|
||||||
|
Log.e(this.toString(),
|
||||||
|
"Received unexpected action " + intent.getAction());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bundle extras = getResultExtras(false);
|
||||||
|
if (extras == null) {
|
||||||
|
// Nothing for us to do.
|
||||||
|
Unpacker.this.setResult(RESULT_OK);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> unpack_libs =
|
||||||
|
extras.getStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS);
|
||||||
|
|
||||||
|
if (unpack_libs != null && !unpack_libs.isEmpty()) {
|
||||||
|
final String[] libs =
|
||||||
|
unpack_libs.toArray(new String[unpack_libs.size()]);
|
||||||
|
mUnpacker = new UnpackTask().execute(libs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPlugins() {
|
||||||
|
Bundle extras = new Bundle(1);
|
||||||
|
|
||||||
|
ArrayList<String> unpack_libs = new ArrayList<String>(1);
|
||||||
|
// This is the common ScummVM code (not really a "plugin" as such)
|
||||||
|
unpack_libs.add(new Uri.Builder()
|
||||||
|
.scheme("plugin")
|
||||||
|
.authority(getPackageName())
|
||||||
|
.path("mylib/armeabi/libscummvm.so")
|
||||||
|
.toString());
|
||||||
|
extras.putStringArrayList(ScummVMApplication.EXTRA_UNPACK_LIBS,
|
||||||
|
unpack_libs);
|
||||||
|
|
||||||
|
Intent intent = new Intent(ScummVMApplication.ACTION_PLUGIN_QUERY);
|
||||||
|
sendOrderedBroadcast(intent, Manifest.permission.SCUMMVM_PLUGIN,
|
||||||
|
new PluginBroadcastReciever(),
|
||||||
|
null, RESULT_OK, null, extras);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle b) {
|
||||||
|
super.onCreate(b);
|
||||||
|
|
||||||
|
mUnpackDest = ScummVMApplication.getLastCacheDir();
|
||||||
|
|
||||||
|
setContentView(R.layout.splash);
|
||||||
|
mProgress = (ProgressBar)findViewById(R.id.progress);
|
||||||
|
|
||||||
|
setResult(RESULT_CANCELED);
|
||||||
|
|
||||||
|
tryUnpack();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryUnpack() {
|
||||||
|
Intent intent = new Intent(ScummVMApplication.ACTION_PLUGIN_QUERY);
|
||||||
|
List<ResolveInfo> plugins = getPackageManager()
|
||||||
|
.queryBroadcastReceivers(intent, 0);
|
||||||
|
if (plugins.isEmpty()) {
|
||||||
|
// No plugins installed
|
||||||
|
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.no_plugins_title)
|
||||||
|
.setMessage(R.string.no_plugins_found)
|
||||||
|
.setIcon(android.R.drawable.ic_dialog_alert)
|
||||||
|
.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||||
|
public void onCancel(DialogInterface dialog) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.quit,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final Uri uri = Uri.parse("market://search?q=ScummVM plugin");
|
||||||
|
final Intent market_intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||||
|
if (getPackageManager().resolveActivity(market_intent, 0) != null) {
|
||||||
|
alert.setPositiveButton(R.string.to_market,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
dialog.dismiss();
|
||||||
|
try {
|
||||||
|
startActivityForResult(market_intent,
|
||||||
|
REQUEST_MARKET);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Log.e(this.toString(),
|
||||||
|
"Error starting market", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
alert.show();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Already have at least one plugin installed
|
||||||
|
initPlugins();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStop() {
|
||||||
|
if (mUnpacker != null)
|
||||||
|
mUnpacker.cancel(true);
|
||||||
|
super.onStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode,
|
||||||
|
Intent data) {
|
||||||
|
switch (requestCode) {
|
||||||
|
case REQUEST_MARKET:
|
||||||
|
if (resultCode != RESULT_OK)
|
||||||
|
Log.w(this.toString(), "Market returned " + resultCode);
|
||||||
|
tryUnpack();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bundle getMetaData() {
|
||||||
|
try {
|
||||||
|
ActivityInfo ai = getPackageManager()
|
||||||
|
.getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
|
||||||
|
return ai.metaData;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.w(this.toString(), "Unable to find my own meta-data", e);
|
||||||
|
return new Bundle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
135
backends/platform/android/scummvm-android-themeengine.patch
Normal file
135
backends/platform/android/scummvm-android-themeengine.patch
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
diff -r 884e66fd1b9c gui/ThemeEngine.cpp
|
||||||
|
--- a/gui/ThemeEngine.cpp Tue Apr 13 09:30:52 2010 +1000
|
||||||
|
+++ b/gui/ThemeEngine.cpp Fri May 28 23:24:43 2010 +1000
|
||||||
|
@@ -390,21 +390,19 @@
|
||||||
|
|
||||||
|
// Try to create a Common::Archive with the files of the theme.
|
||||||
|
if (!_themeArchive && !_themeFile.empty()) {
|
||||||
|
- Common::FSNode node(_themeFile);
|
||||||
|
- if (node.getName().hasSuffix(".zip") && !node.isDirectory()) {
|
||||||
|
+ Common::ArchiveMemberPtr member = SearchMan.getMember(_themeFile);
|
||||||
|
+ if (member && member->getName().hasSuffix(".zip")) {
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
- Common::Archive *zipArchive = Common::makeZipArchive(node);
|
||||||
|
+ Common::Archive *zipArchive = Common::makeZipArchive(member->createReadStream());
|
||||||
|
|
||||||
|
if (!zipArchive) {
|
||||||
|
- warning("Failed to open Zip archive '%s'.", node.getPath().c_str());
|
||||||
|
+ warning("Failed to open Zip archive '%s'.", member->getDisplayName().c_str());
|
||||||
|
}
|
||||||
|
_themeArchive = zipArchive;
|
||||||
|
#else
|
||||||
|
warning("Trying to load theme '%s' in a Zip archive without zLib support", _themeFile.c_str());
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
- } else if (node.isDirectory()) {
|
||||||
|
- _themeArchive = new Common::FSDirectory(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1436,6 +1434,30 @@
|
||||||
|
return tok.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool ThemeEngine::themeConfigUsable(const Common::ArchiveMember &member, Common::String &themeName) {
|
||||||
|
+ Common::File stream;
|
||||||
|
+ bool foundHeader = false;
|
||||||
|
+
|
||||||
|
+ if (member.getName().hasSuffix(".zip")) {
|
||||||
|
+#ifdef USE_ZLIB
|
||||||
|
+ Common::Archive *zipArchive = Common::makeZipArchive(member.createReadStream());
|
||||||
|
+
|
||||||
|
+ if (zipArchive && zipArchive->hasFile("THEMERC")) {
|
||||||
|
+ stream.open("THEMERC", *zipArchive);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ delete zipArchive;
|
||||||
|
+#endif
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (stream.isOpen()) {
|
||||||
|
+ Common::String stxHeader = stream.readLine();
|
||||||
|
+ foundHeader = themeConfigParseHeader(stxHeader, themeName);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return foundHeader;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &themeName) {
|
||||||
|
Common::File stream;
|
||||||
|
bool foundHeader = false;
|
||||||
|
@@ -1493,10 +1515,6 @@
|
||||||
|
if (ConfMan.hasKey("themepath"))
|
||||||
|
listUsableThemes(Common::FSNode(ConfMan.get("themepath")), list);
|
||||||
|
|
||||||
|
-#ifdef DATA_PATH
|
||||||
|
- listUsableThemes(Common::FSNode(DATA_PATH), list);
|
||||||
|
-#endif
|
||||||
|
-
|
||||||
|
#if defined(MACOSX) || defined(IPHONE)
|
||||||
|
CFURLRef resourceUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
|
||||||
|
if (resourceUrl) {
|
||||||
|
@@ -1509,10 +1527,7 @@
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- if (ConfMan.hasKey("extrapath"))
|
||||||
|
- listUsableThemes(Common::FSNode(ConfMan.get("extrapath")), list);
|
||||||
|
-
|
||||||
|
- listUsableThemes(Common::FSNode("."), list, 1);
|
||||||
|
+ listUsableThemes(SearchMan, list);
|
||||||
|
|
||||||
|
// Now we need to strip all duplicates
|
||||||
|
// TODO: It might not be the best idea to strip duplicates. The user might
|
||||||
|
@@ -1531,6 +1546,34 @@
|
||||||
|
output.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
+void ThemeEngine::listUsableThemes(Common::Archive &archive, Common::List<ThemeDescriptor> &list) {
|
||||||
|
+ ThemeDescriptor td;
|
||||||
|
+
|
||||||
|
+#ifdef USE_ZLIB
|
||||||
|
+ Common::ArchiveMemberList fileList;
|
||||||
|
+ archive.listMatchingMembers(fileList, "*.zip");
|
||||||
|
+ for (Common::ArchiveMemberList::iterator i = fileList.begin();
|
||||||
|
+ i != fileList.end(); ++i) {
|
||||||
|
+ td.name.clear();
|
||||||
|
+ if (themeConfigUsable(**i, td.name)) {
|
||||||
|
+ td.filename = (*i)->getName();
|
||||||
|
+ td.id = (*i)->getDisplayName();
|
||||||
|
+
|
||||||
|
+ // If the name of the node object also contains
|
||||||
|
+ // the ".zip" suffix, we will strip it.
|
||||||
|
+ if (td.id.hasSuffix(".zip")) {
|
||||||
|
+ for (int j = 0; j < 4; ++j)
|
||||||
|
+ td.id.deleteLastChar();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ list.push_back(td);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fileList.clear();
|
||||||
|
+#endif
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) {
|
||||||
|
if (!node.exists() || !node.isReadable() || !node.isDirectory())
|
||||||
|
return;
|
||||||
|
diff -r 884e66fd1b9c gui/ThemeEngine.h
|
||||||
|
--- a/gui/ThemeEngine.h Tue Apr 13 09:30:52 2010 +1000
|
||||||
|
+++ b/gui/ThemeEngine.h Fri May 28 23:24:43 2010 +1000
|
||||||
|
@@ -560,11 +560,13 @@
|
||||||
|
static void listUsableThemes(Common::List<ThemeDescriptor> &list);
|
||||||
|
private:
|
||||||
|
static bool themeConfigUsable(const Common::FSNode &node, Common::String &themeName);
|
||||||
|
+ static bool themeConfigUsable(const Common::ArchiveMember &member, Common::String &themeName);
|
||||||
|
static bool themeConfigParseHeader(Common::String header, Common::String &themeName);
|
||||||
|
|
||||||
|
static Common::String getThemeFile(const Common::String &id);
|
||||||
|
static Common::String getThemeId(const Common::String &filename);
|
||||||
|
static void listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth = -1);
|
||||||
|
+ static void listUsableThemes(Common::Archive &archive, Common::List<ThemeDescriptor> &list);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OSystem *_system; /** Global system object. */
|
@ -38,7 +38,7 @@
|
|||||||
#include <system.h>
|
#include <system.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
//#include <registers_alt.h> // not needed in current libnds
|
#include <registers_alt.h> // Needed for SOUND_CR
|
||||||
#include <NDS/scummvm_ipc.h>
|
#include <NDS/scummvm_ipc.h>
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
#ifdef USE_DEBUGGER
|
#ifdef USE_DEBUGGER
|
||||||
@ -590,7 +590,7 @@ int main(int argc, char ** argv) {
|
|||||||
IPC->reset = false;
|
IPC->reset = false;
|
||||||
|
|
||||||
|
|
||||||
fifoInit();
|
//fifoInit();
|
||||||
|
|
||||||
for (int r = 0; r < 8; r++) {
|
for (int r = 0; r < 8; r++) {
|
||||||
IPC->adpcm.arm7Buffer[r] = (u8 *) malloc(512);
|
IPC->adpcm.arm7Buffer[r] = (u8 *) malloc(512);
|
||||||
|
6
backends/platform/ds/arm9/dist/readme_ds.txt
vendored
6
backends/platform/ds/arm9/dist/readme_ds.txt
vendored
@ -41,6 +41,10 @@ Visit the main ScummVM website <http://www.scummvm.org>
|
|||||||
What's New?
|
What's New?
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ScummVM DS 1.1.1
|
||||||
|
|
||||||
|
* Bugfix release: no new features
|
||||||
|
|
||||||
ScummVM DS 1.1.0
|
ScummVM DS 1.1.0
|
||||||
|
|
||||||
* New games are supported in this stable build: Return to Zork, Rodney's
|
* New games are supported in this stable build: Return to Zork, Rodney's
|
||||||
@ -319,7 +323,7 @@ CANNOT DO THIS.
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
I'm glad you asked. Here is a list of the compatible games in version
|
I'm glad you asked. Here is a list of the compatible games in version
|
||||||
1.1.0. Demo versions of the games listed should work too.
|
1.1.1. Demo versions of the games listed should work too.
|
||||||
|
|
||||||
Flight of the Amazon Queen, Beneath a Steel Sky, and Lure of the
|
Flight of the Amazon Queen, Beneath a Steel Sky, and Lure of the
|
||||||
Temptress have generously been released as freeware by the original
|
Temptress have generously been released as freeware by the original
|
||||||
|
@ -75,7 +75,7 @@ else
|
|||||||
ifdef DS_BUILD_K
|
ifdef DS_BUILD_K
|
||||||
|
|
||||||
else
|
else
|
||||||
USE_MAD = 1
|
# USE_MAD = 1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
#include "profiler/cyg-profile.h"
|
#include "profiler/cyg-profile.h"
|
||||||
#endif
|
#endif
|
||||||
#include "backends/fs/ds/ds-fs.h"
|
#include "backends/fs/ds/ds-fs.h"
|
||||||
|
#include "base/version.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
|
||||||
extern "C" void OurIntrMain(void);
|
extern "C" void OurIntrMain(void);
|
||||||
@ -701,7 +702,7 @@ void displayMode8Bit() {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true);
|
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 2, 0, true, true);
|
||||||
|
|
||||||
// Set this again because consoleinit resets it
|
// Set this again because consoleinit resets it
|
||||||
videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
|
videoSetMode(MODE_5_2D | (consoleEnable? DISPLAY_BG0_ACTIVE: 0) | DISPLAY_BG3_ACTIVE | DISPLAY_SPR_ACTIVE | DISPLAY_SPR_1D | DISPLAY_SPR_1D_BMP);
|
||||||
@ -939,7 +940,7 @@ void displayMode16Bit() {
|
|||||||
SUB_BG0_CR = BG_MAP_BASE(4) | BG_TILE_BASE(0);
|
SUB_BG0_CR = BG_MAP_BASE(4) | BG_TILE_BASE(0);
|
||||||
SUB_BG0_Y0 = 0;
|
SUB_BG0_Y0 = 0;
|
||||||
|
|
||||||
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false);
|
consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 0, false, true);
|
||||||
// consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(4), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
|
// consoleInitDefault((u16*)SCREEN_BASE_BLOCK_SUB(4), (u16*)CHAR_BASE_BLOCK_SUB(0), 16);
|
||||||
|
|
||||||
for (int r = 0; r < 32 * 32; r++) {
|
for (int r = 0; r < 32 * 32; r++) {
|
||||||
@ -3162,7 +3163,7 @@ int main(void) {
|
|||||||
consolePrintf("-------------------------------\n");
|
consolePrintf("-------------------------------\n");
|
||||||
consolePrintf("ScummVM DS\n");
|
consolePrintf("ScummVM DS\n");
|
||||||
consolePrintf("Ported by Neil Millstone\n");
|
consolePrintf("Ported by Neil Millstone\n");
|
||||||
consolePrintf("Version 1.1.0 ");
|
consolePrintf("Version %s ", gScummVMVersion);
|
||||||
#if defined(DS_BUILD_A)
|
#if defined(DS_BUILD_A)
|
||||||
consolePrintf("build A\n");
|
consolePrintf("build A\n");
|
||||||
consolePrintf("Lucasarts SCUMM games (SCUMM)\n");
|
consolePrintf("Lucasarts SCUMM games (SCUMM)\n");
|
||||||
|
@ -33,6 +33,18 @@
|
|||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct sTransferSoundData {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
const void *data;
|
||||||
|
u32 len;
|
||||||
|
u32 rate;
|
||||||
|
u8 vol;
|
||||||
|
u8 pan;
|
||||||
|
u8 format;
|
||||||
|
u8 PADDING;
|
||||||
|
} TransferSoundData, * pTransferSoundData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
@ -121,19 +121,6 @@ public:
|
|||||||
|
|
||||||
virtual Audio::Mixer *getMixer();
|
virtual Audio::Mixer *getMixer();
|
||||||
|
|
||||||
// Poll CD status
|
|
||||||
// Returns true if cd audio is playing
|
|
||||||
bool pollCD();
|
|
||||||
|
|
||||||
// Play CD audio track
|
|
||||||
void playCD(int track, int num_loops, int start_frame, int duration);
|
|
||||||
|
|
||||||
// Stop CD audio track
|
|
||||||
void stopCD();
|
|
||||||
|
|
||||||
// Update CD audio status
|
|
||||||
void updateCD();
|
|
||||||
|
|
||||||
// Quit
|
// Quit
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
@ -163,8 +150,6 @@ public:
|
|||||||
bool setGraphicsMode(int mode);
|
bool setGraphicsMode(int mode);
|
||||||
int getGraphicsMode() const;
|
int getGraphicsMode() const;
|
||||||
|
|
||||||
bool openCD(int drive);
|
|
||||||
|
|
||||||
bool hasFeature(Feature f);
|
bool hasFeature(Feature f);
|
||||||
void setFeatureState(Feature f, bool enable);
|
void setFeatureState(Feature f, bool enable);
|
||||||
bool getFeatureState(Feature f);
|
bool getFeatureState(Feature f);
|
||||||
@ -206,15 +191,6 @@ protected:
|
|||||||
bool _overlayVisible;
|
bool _overlayVisible;
|
||||||
Graphics::PixelFormat _overlayFormat;
|
Graphics::PixelFormat _overlayFormat;
|
||||||
|
|
||||||
// CD Audio
|
|
||||||
SDL_CD *_cdrom;
|
|
||||||
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
|
|
||||||
uint32 _cdEndTime, _cdStopTime;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
DF_WANT_RECT_OPTIM = 1 << 0
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kTransactionNone = 0,
|
kTransactionNone = 0,
|
||||||
kTransactionActive = 1,
|
kTransactionActive = 1,
|
||||||
@ -255,7 +231,6 @@ protected:
|
|||||||
Graphics::Surface _framebuffer;
|
Graphics::Surface _framebuffer;
|
||||||
|
|
||||||
/** Current video mode flags (see DF_* constants) */
|
/** Current video mode flags (see DF_* constants) */
|
||||||
uint32 _modeFlags;
|
|
||||||
bool _modeChanged;
|
bool _modeChanged;
|
||||||
int _screenChangeCount;
|
int _screenChangeCount;
|
||||||
|
|
||||||
@ -272,9 +247,6 @@ protected:
|
|||||||
// Dirty rect management
|
// Dirty rect management
|
||||||
SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];
|
SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];
|
||||||
int _numDirtyRects;
|
int _numDirtyRects;
|
||||||
uint32 *_dirtyChecksums;
|
|
||||||
bool _cksumValid;
|
|
||||||
int _cksumNum;
|
|
||||||
|
|
||||||
// Keyboard mouse emulation. Disabled by fingolfin 2004-12-18.
|
// Keyboard mouse emulation. Disabled by fingolfin 2004-12-18.
|
||||||
// I am keeping the rest of the code in for now, since the joystick
|
// I am keeping the rest of the code in for now, since the joystick
|
||||||
@ -371,9 +343,6 @@ protected:
|
|||||||
Common::TimerManager *_timer;
|
Common::TimerManager *_timer;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addDirtyRgnAuto(const byte *buf);
|
|
||||||
void makeChecksums(const byte *buf);
|
|
||||||
|
|
||||||
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false);
|
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false);
|
||||||
|
|
||||||
void drawMouse();
|
void drawMouse();
|
||||||
|
@ -193,13 +193,11 @@ void OSystem_GP2X::initBackend() {
|
|||||||
memset(&_videoMode, 0, sizeof(_videoMode));
|
memset(&_videoMode, 0, sizeof(_videoMode));
|
||||||
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
|
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
|
||||||
|
|
||||||
_cksumValid = false;
|
|
||||||
_videoMode.mode = GFX_NORMAL;
|
_videoMode.mode = GFX_NORMAL;
|
||||||
_videoMode.scaleFactor = 1;
|
_videoMode.scaleFactor = 1;
|
||||||
_scalerProc = Normal1x;
|
_scalerProc = Normal1x;
|
||||||
_videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
|
_videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
|
||||||
_scalerType = 0;
|
_scalerType = 0;
|
||||||
_modeFlags = 0;
|
|
||||||
_adjustZoomOnMouse = false;
|
_adjustZoomOnMouse = false;
|
||||||
ConfMan.setBool("FM_low_quality", true);
|
ConfMan.setBool("FM_low_quality", true);
|
||||||
|
|
||||||
@ -246,7 +244,7 @@ OSystem_GP2X::OSystem_GP2X()
|
|||||||
_hwscreen(0), _screen(0), _tmpscreen(0),
|
_hwscreen(0), _screen(0), _tmpscreen(0),
|
||||||
_overlayVisible(false),
|
_overlayVisible(false),
|
||||||
_overlayscreen(0), _tmpscreen2(0),
|
_overlayscreen(0), _tmpscreen2(0),
|
||||||
_cdrom(0), _scalerProc(0), _modeChanged(false), _screenChangeCount(0), _dirtyChecksums(0),
|
_scalerProc(0), _modeChanged(false), _screenChangeCount(0),
|
||||||
_mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0),
|
_mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0),
|
||||||
_mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true),
|
_mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true),
|
||||||
_joystick(0),
|
_joystick(0),
|
||||||
@ -281,7 +279,6 @@ OSystem_GP2X::~OSystem_GP2X() {
|
|||||||
SDL_RemoveTimer(_timerID);
|
SDL_RemoveTimer(_timerID);
|
||||||
closeMixer();
|
closeMixer();
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
free(_currentPalette);
|
free(_currentPalette);
|
||||||
free(_cursorPalette);
|
free(_cursorPalette);
|
||||||
free(_mouseData);
|
free(_mouseData);
|
||||||
@ -380,7 +377,6 @@ bool OSystem_GP2X::hasFeature(Feature f) {
|
|||||||
return
|
return
|
||||||
(f == kFeatureFullscreenMode) ||
|
(f == kFeatureFullscreenMode) ||
|
||||||
(f == kFeatureAspectRatioCorrection) ||
|
(f == kFeatureAspectRatioCorrection) ||
|
||||||
(f == kFeatureAutoComputeDirtyRects) ||
|
|
||||||
(f == kFeatureCursorHasPalette);
|
(f == kFeatureCursorHasPalette);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,12 +387,6 @@ void OSystem_GP2X::setFeatureState(Feature f, bool enable) {
|
|||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
setAspectRatioCorrection(enable);
|
setAspectRatioCorrection(enable);
|
||||||
break;
|
break;
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
if (enable)
|
|
||||||
_modeFlags |= DF_WANT_RECT_OPTIM;
|
|
||||||
else
|
|
||||||
_modeFlags &= ~DF_WANT_RECT_OPTIM;
|
|
||||||
break;
|
|
||||||
case kFeatureDisableKeyFiltering:
|
case kFeatureDisableKeyFiltering:
|
||||||
// TODO: Extend as more support for this is added to engines.
|
// TODO: Extend as more support for this is added to engines.
|
||||||
return;
|
return;
|
||||||
@ -413,8 +403,6 @@ bool OSystem_GP2X::getFeatureState(Feature f) {
|
|||||||
return false;
|
return false;
|
||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
return _videoMode.aspectRatioCorrection;
|
return _videoMode.aspectRatioCorrection;
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
return _modeFlags & DF_WANT_RECT_OPTIM;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -431,7 +419,6 @@ void OSystem_GP2X::quit() {
|
|||||||
SDL_RemoveTimer(_timerID);
|
SDL_RemoveTimer(_timerID);
|
||||||
closeMixer();
|
closeMixer();
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
free(_currentPalette);
|
free(_currentPalette);
|
||||||
free(_cursorPalette);
|
free(_cursorPalette);
|
||||||
free(_mouseData);
|
free(_mouseData);
|
||||||
@ -650,26 +637,3 @@ Audio::Mixer *OSystem_GP2X::getMixer() {
|
|||||||
assert(_mixer);
|
assert(_mixer);
|
||||||
return _mixer;
|
return _mixer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
|
||||||
#pragma mark --- CD Audio ---
|
|
||||||
#pragma mark -
|
|
||||||
|
|
||||||
bool OSystem_GP2X::openCD(int drive) {
|
|
||||||
return (_cdrom = NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_GP2X::stopCD() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_GP2X::playCD(int track, int num_loops, int start_frame, int duration) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSystem_GP2X::pollCD() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_GP2X::updateCD() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
@ -270,12 +270,7 @@ void OSystem_GP2X::initSize(uint w, uint h, const Graphics::PixelFormat *format)
|
|||||||
_videoMode.screenWidth = w;
|
_videoMode.screenWidth = w;
|
||||||
_videoMode.screenHeight = h;
|
_videoMode.screenHeight = h;
|
||||||
|
|
||||||
_cksumNum = (w * h / (8 * 8));
|
|
||||||
|
|
||||||
_transactionDetails.sizeChanged = true;
|
_transactionDetails.sizeChanged = true;
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int OSystem_GP2X::effectiveScreenHeight() const {
|
int OSystem_GP2X::effectiveScreenHeight() const {
|
||||||
@ -724,41 +719,32 @@ void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, in
|
|||||||
assert(h > 0 && y + h <= _videoMode.screenHeight);
|
assert(h > 0 && y + h <= _videoMode.screenHeight);
|
||||||
assert(w > 0 && x + w <= _videoMode.screenWidth);
|
assert(w > 0 && x + w <= _videoMode.screenWidth);
|
||||||
|
|
||||||
if (IS_ALIGNED(src, 4) && pitch == _videoMode.screenWidth && x == 0 && y == 0 &&
|
/* Clip the coordinates */
|
||||||
w == _videoMode.screenWidth && h == _videoMode.screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
|
if (x < 0) {
|
||||||
/* Special, optimized case for full screen updates.
|
w += x;
|
||||||
* It tries to determine what areas were actually changed,
|
src -= x;
|
||||||
* and just updates those, on the actual display. */
|
x = 0;
|
||||||
addDirtyRgnAuto(src);
|
|
||||||
} else {
|
|
||||||
/* Clip the coordinates */
|
|
||||||
if (x < 0) {
|
|
||||||
w += x;
|
|
||||||
src -= x;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y < 0) {
|
|
||||||
h += y;
|
|
||||||
src -= y * pitch;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w > _videoMode.screenWidth - x) {
|
|
||||||
w = _videoMode.screenWidth - x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h > _videoMode.screenHeight - y) {
|
|
||||||
h = _videoMode.screenHeight - y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_cksumValid = false;
|
|
||||||
addDirtyRect(x, y, w, h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (y < 0) {
|
||||||
|
h += y;
|
||||||
|
src -= y * pitch;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w > _videoMode.screenWidth - x) {
|
||||||
|
w = _videoMode.screenWidth - x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h > _videoMode.screenHeight - y) {
|
||||||
|
h = _videoMode.screenHeight - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w <= 0 || h <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addDirtyRect(x, y, w, h);
|
||||||
|
|
||||||
// Try to lock the screen surface
|
// Try to lock the screen surface
|
||||||
if (SDL_LockSurface(_screen) == -1)
|
if (SDL_LockSurface(_screen) == -1)
|
||||||
error("SDL_LockSurface failed: %s", SDL_GetError());
|
error("SDL_LockSurface failed: %s", SDL_GetError());
|
||||||
@ -885,88 +871,6 @@ void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_GP2X::makeChecksums(const byte *buf) {
|
|
||||||
assert(buf);
|
|
||||||
uint32 *sums = _dirtyChecksums;
|
|
||||||
uint x,y;
|
|
||||||
const uint last_x = (uint)_videoMode.screenWidth / 8;
|
|
||||||
const uint last_y = (uint)_videoMode.screenHeight / 8;
|
|
||||||
|
|
||||||
const uint BASE = 65521; /* largest prime smaller than 65536 */
|
|
||||||
|
|
||||||
/* the 8x8 blocks in buf are enumerated starting in the top left corner and
|
|
||||||
* reading each line at a time from left to right */
|
|
||||||
for (y = 0; y != last_y; y++, buf += _videoMode.screenWidth * (8 - 1))
|
|
||||||
for (x = 0; x != last_x; x++, buf += 8) {
|
|
||||||
// Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
|
|
||||||
// This computes the Adler32 checksum of a 8x8 pixel block. Note
|
|
||||||
// that we can do the modulo operation (which is the slowest part)
|
|
||||||
// of the algorithm) at the end, instead of doing each iteration,
|
|
||||||
// since we only have 64 iterations in total - and thus s1 and
|
|
||||||
// s2 can't overflow anyway.
|
|
||||||
uint32 s1 = 1;
|
|
||||||
uint32 s2 = 0;
|
|
||||||
const byte *ptr = buf;
|
|
||||||
for (int subY = 0; subY < 8; subY++) {
|
|
||||||
for (int subX = 0; subX < 8; subX++) {
|
|
||||||
s1 += ptr[subX];
|
|
||||||
s2 += s1;
|
|
||||||
}
|
|
||||||
ptr += _videoMode.screenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
s1 %= BASE;
|
|
||||||
s2 %= BASE;
|
|
||||||
|
|
||||||
/* output the checksum for this block */
|
|
||||||
*sums++ = (s2 << 16) + s1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_GP2X::addDirtyRgnAuto(const byte *buf) {
|
|
||||||
assert(buf);
|
|
||||||
assert(IS_ALIGNED(buf, 4));
|
|
||||||
|
|
||||||
/* generate a table of the checksums */
|
|
||||||
makeChecksums(buf);
|
|
||||||
|
|
||||||
if (!_cksumValid) {
|
|
||||||
_forceFull = true;
|
|
||||||
_cksumValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* go through the checksum list, compare it with the previous checksums,
|
|
||||||
and add all dirty rectangles to a list. try to combine small rectangles
|
|
||||||
into bigger ones in a simple way */
|
|
||||||
if (!_forceFull) {
|
|
||||||
int x, y, w;
|
|
||||||
uint32 *ck = _dirtyChecksums;
|
|
||||||
|
|
||||||
for (y = 0; y != _videoMode.screenHeight / 8; y++) {
|
|
||||||
for (x = 0; x != _videoMode.screenWidth / 8; x++, ck++) {
|
|
||||||
if (ck[0] != ck[_cksumNum]) {
|
|
||||||
/* found a dirty 8x8 block, now go as far to the right as possible,
|
|
||||||
and at the same time, unmark the dirty status by setting old to new. */
|
|
||||||
w=0;
|
|
||||||
do {
|
|
||||||
ck[w + _cksumNum] = ck[w];
|
|
||||||
w++;
|
|
||||||
} while (x + w != _videoMode.screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
|
|
||||||
|
|
||||||
addDirtyRect(x * 8, y * 8, w * 8, 8);
|
|
||||||
|
|
||||||
if (_forceFull)
|
|
||||||
goto get_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
get_out:;
|
|
||||||
/* Copy old checksums to new */
|
|
||||||
memcpy(_dirtyChecksums + _cksumNum, _dirtyChecksums, _cksumNum * sizeof(uint32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int16 OSystem_GP2X::getHeight() {
|
int16 OSystem_GP2X::getHeight() {
|
||||||
return _videoMode.screenHeight;
|
return _videoMode.screenHeight;
|
||||||
}
|
}
|
||||||
@ -1175,7 +1079,6 @@ void OSystem_GP2X::copyRectToOverlay(const OverlayColor *buf, int pitch, int x,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Mark the modified region as dirty
|
// Mark the modified region as dirty
|
||||||
_cksumValid = false;
|
|
||||||
addDirtyRect(x, y, w, h);
|
addDirtyRect(x, y, w, h);
|
||||||
|
|
||||||
if (SDL_LockSurface(_overlayscreen) == -1)
|
if (SDL_LockSurface(_overlayscreen) == -1)
|
||||||
@ -1502,7 +1405,6 @@ void OSystem_GP2X::drawMouse() {
|
|||||||
SDL_Rect zoomdst;
|
SDL_Rect zoomdst;
|
||||||
SDL_Rect dst;
|
SDL_Rect dst;
|
||||||
int scale;
|
int scale;
|
||||||
int width, height;
|
|
||||||
int hotX, hotY;
|
int hotX, hotY;
|
||||||
int tmpScreenWidth, tmpScreenHeight;
|
int tmpScreenWidth, tmpScreenHeight;
|
||||||
|
|
||||||
@ -1523,16 +1425,12 @@ void OSystem_GP2X::drawMouse() {
|
|||||||
|
|
||||||
if (!_overlayVisible) {
|
if (!_overlayVisible) {
|
||||||
scale = _videoMode.scaleFactor;
|
scale = _videoMode.scaleFactor;
|
||||||
width = _videoMode.screenWidth;
|
|
||||||
height = _videoMode.screenHeight;
|
|
||||||
dst.w = _mouseCurState.vW;
|
dst.w = _mouseCurState.vW;
|
||||||
dst.h = _mouseCurState.vH;
|
dst.h = _mouseCurState.vH;
|
||||||
hotX = _mouseCurState.vHotX;
|
hotX = _mouseCurState.vHotX;
|
||||||
hotY = _mouseCurState.vHotY;
|
hotY = _mouseCurState.vHotY;
|
||||||
} else {
|
} else {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
width = _videoMode.overlayWidth;
|
|
||||||
height = _videoMode.overlayHeight;
|
|
||||||
dst.w = _mouseCurState.rW;
|
dst.w = _mouseCurState.rW;
|
||||||
dst.h = _mouseCurState.rH;
|
dst.h = _mouseCurState.rH;
|
||||||
hotX = _mouseCurState.rHotX;
|
hotX = _mouseCurState.rHotX;
|
||||||
|
@ -13,7 +13,7 @@ export ASFLAGS=-mfloat-abi=soft
|
|||||||
|
|
||||||
cd ../../../..
|
cd ../../../..
|
||||||
|
|
||||||
echo Building ScummVM for GP2X.
|
echo Building ScummVM for GP2X Wiz.
|
||||||
make
|
make
|
||||||
|
|
||||||
echo Build for GP2X - SDL - complete - Please check build logs.
|
echo Build for GP2X Wiz - complete - Please check build logs.
|
||||||
|
@ -35,10 +35,12 @@ loc=`dirname "$f"`
|
|||||||
cp $loc/../lib/libz.so.1.2.3 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libz.so.1
|
cp $loc/../lib/libz.so.1.2.3 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libz.so.1
|
||||||
cp $loc/../lib/libvorbisidec.so.1.0.2 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libvorbisidec.so.1
|
cp $loc/../lib/libvorbisidec.so.1.0.2 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libvorbisidec.so.1
|
||||||
|
|
||||||
|
echo Making Stripped Binary.
|
||||||
echo Making Stripped exe.
|
|
||||||
arm-open2x-linux-strip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/scummvm.wiz
|
arm-open2x-linux-strip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/scummvm.wiz
|
||||||
|
|
||||||
|
echo Making Stripped Plugins.
|
||||||
|
arm-open2x-linux-strip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins/*
|
||||||
|
|
||||||
echo Building ZIP bundle.
|
echo Building ZIP bundle.
|
||||||
if [ -f /usr/bin/zip ]
|
if [ -f /usr/bin/zip ]
|
||||||
then
|
then
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/sh
|
||||||
|
|
||||||
echo Quick script to make building all the time less painful.
|
echo Quick script to make building all the time less painful.
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/sh
|
||||||
|
|
||||||
echo Quick script to make running configure all the time less painful
|
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.
|
echo and let all the build work be done from the backend/build folder.
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h"
|
#include "backends/platform/gp2xwiz/gp2xwiz-sdl.h"
|
||||||
#include "backends/platform/gp2xwiz/gp2xwiz-hw.h"
|
#include "backends/platform/gp2xwiz/gp2xwiz-hw.h"
|
||||||
|
#include "graphics/scaler/aspect.h"
|
||||||
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/events.h"
|
#include "common/events.h"
|
||||||
|
@ -127,12 +127,7 @@ void OSystem_GP2XWIZ::initSize(uint w, uint h) {
|
|||||||
toggleMouseGrab();
|
toggleMouseGrab();
|
||||||
}
|
}
|
||||||
|
|
||||||
_cksumNum = (w * h / (8 * 8));
|
|
||||||
|
|
||||||
_transactionDetails.sizeChanged = true;
|
_transactionDetails.sizeChanged = true;
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSystem_GP2XWIZ::loadGFXMode() {
|
bool OSystem_GP2XWIZ::loadGFXMode() {
|
||||||
@ -154,7 +149,6 @@ void OSystem_GP2XWIZ::drawMouse() {
|
|||||||
|
|
||||||
SDL_Rect dst;
|
SDL_Rect dst;
|
||||||
int scale;
|
int scale;
|
||||||
int width, height;
|
|
||||||
int hotX, hotY;
|
int hotX, hotY;
|
||||||
|
|
||||||
if (_videoMode.mode == GFX_HALF && !_overlayVisible){
|
if (_videoMode.mode == GFX_HALF && !_overlayVisible){
|
||||||
@ -167,16 +161,12 @@ void OSystem_GP2XWIZ::drawMouse() {
|
|||||||
|
|
||||||
if (!_overlayVisible) {
|
if (!_overlayVisible) {
|
||||||
scale = _videoMode.scaleFactor;
|
scale = _videoMode.scaleFactor;
|
||||||
width = _videoMode.screenWidth;
|
|
||||||
height = _videoMode.screenHeight;
|
|
||||||
dst.w = _mouseCurState.vW;
|
dst.w = _mouseCurState.vW;
|
||||||
dst.h = _mouseCurState.vH;
|
dst.h = _mouseCurState.vH;
|
||||||
hotX = _mouseCurState.vHotX;
|
hotX = _mouseCurState.vHotX;
|
||||||
hotY = _mouseCurState.vHotY;
|
hotY = _mouseCurState.vHotY;
|
||||||
} else {
|
} else {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
width = _videoMode.overlayWidth;
|
|
||||||
height = _videoMode.overlayHeight;
|
|
||||||
dst.w = _mouseCurState.rW;
|
dst.w = _mouseCurState.rW;
|
||||||
dst.h = _mouseCurState.rH;
|
dst.h = _mouseCurState.rH;
|
||||||
hotX = _mouseCurState.rHotX;
|
hotX = _mouseCurState.rHotX;
|
||||||
|
@ -72,6 +72,7 @@ void iPhone_updateScreenRect(unsigned short* screen, int x1, int y1, int x2, int
|
|||||||
void iPhone_initSurface(int width, int height);
|
void iPhone_initSurface(int width, int height);
|
||||||
bool iPhone_fetchEvent(int *outEvent, float *outX, float *outY);
|
bool iPhone_fetchEvent(int *outEvent, float *outX, float *outY);
|
||||||
const char* iPhone_getDocumentsDir();
|
const char* iPhone_getDocumentsDir();
|
||||||
|
bool iPhone_isHighResDevice();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,6 @@
|
|||||||
SoftKeyboard* _keyboardView;
|
SoftKeyboard* _keyboardView;
|
||||||
CALayer* _screenLayer;
|
CALayer* _screenLayer;
|
||||||
|
|
||||||
int _fullWidth;
|
|
||||||
int _fullHeight;
|
|
||||||
int _widthOffset;
|
int _widthOffset;
|
||||||
int _heightOffset;
|
int _heightOffset;
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
static iPhoneView *sharedInstance = nil;
|
static iPhoneView *sharedInstance = nil;
|
||||||
static int _width = 0;
|
static int _width = 0;
|
||||||
static int _height = 0;
|
static int _height = 0;
|
||||||
|
static int _fullWidth;
|
||||||
|
static int _fullHeight;
|
||||||
static CGRect _screenRect;
|
static CGRect _screenRect;
|
||||||
static char* _textureBuffer = 0;
|
static char* _textureBuffer = 0;
|
||||||
static int _textureWidth = 0;
|
static int _textureWidth = 0;
|
||||||
@ -42,6 +44,10 @@ static UITouch* _secondTouch = NULL;
|
|||||||
// static long lastTick = 0;
|
// static long lastTick = 0;
|
||||||
// static int frames = 0;
|
// static int frames = 0;
|
||||||
|
|
||||||
|
bool iPhone_isHighResDevice() {
|
||||||
|
return _fullHeight > 480;
|
||||||
|
}
|
||||||
|
|
||||||
void iPhone_updateScreen() {
|
void iPhone_updateScreen() {
|
||||||
if (!_needsScreenUpdate) {
|
if (!_needsScreenUpdate) {
|
||||||
_needsScreenUpdate = 1;
|
_needsScreenUpdate = 1;
|
||||||
|
@ -57,7 +57,7 @@ OSystem_IPHONE::OSystem_IPHONE() :
|
|||||||
_overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL),
|
_overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL),
|
||||||
_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0),
|
_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0),
|
||||||
_secondaryTapped(false), _lastSecondaryTap(0), _screenOrientation(kScreenOrientationFlippedLandscape),
|
_secondaryTapped(false), _lastSecondaryTap(0), _screenOrientation(kScreenOrientationFlippedLandscape),
|
||||||
_needEventRestPeriod(false), _mouseClickAndDragEnabled(false), _touchpadModeEnabled(true),
|
_needEventRestPeriod(false), _mouseClickAndDragEnabled(false),
|
||||||
_gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false), _fullScreenOverlayIsDirty(false),
|
_gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false), _fullScreenOverlayIsDirty(false),
|
||||||
_mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1), _screenChangeCount(0)
|
_mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1), _screenChangeCount(0)
|
||||||
|
|
||||||
@ -65,6 +65,7 @@ OSystem_IPHONE::OSystem_IPHONE() :
|
|||||||
_queuedInputEvent.type = (Common::EventType)0;
|
_queuedInputEvent.type = (Common::EventType)0;
|
||||||
_lastDrawnMouseRect = Common::Rect(0, 0, 0, 0);
|
_lastDrawnMouseRect = Common::Rect(0, 0, 0, 0);
|
||||||
|
|
||||||
|
_touchpadModeEnabled = !iPhone_isHighResDevice();
|
||||||
_fsFactory = new POSIXFilesystemFactory();
|
_fsFactory = new POSIXFilesystemFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ int16 OSystem_IPHONE::getWidth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) {
|
void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) {
|
||||||
//printf("setPalette()\n");
|
assert(start + num <= 256);
|
||||||
const byte *b = colors;
|
const byte *b = colors;
|
||||||
|
|
||||||
for (uint i = start; i < start + num; ++i) {
|
for (uint i = start; i < start + num; ++i) {
|
||||||
@ -98,7 +98,14 @@ void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) {
|
void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) {
|
||||||
//printf("grabPalette()\n");
|
assert(start + num <= 256);
|
||||||
|
byte *b = colors;
|
||||||
|
|
||||||
|
for (uint i = start; i < start + num; ++i) {
|
||||||
|
Graphics::colorToRGB<Graphics::ColorMasks<565> >(_palette[i], b[0], b[1], b[2]);
|
||||||
|
b[3] = 0xFF;
|
||||||
|
b += 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_IPHONE::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
|
void OSystem_IPHONE::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
|
||||||
|
@ -128,12 +128,7 @@ void OSystem_LINUXMOTO::initSize(uint w, uint h) {
|
|||||||
toggleMouseGrab();
|
toggleMouseGrab();
|
||||||
}
|
}
|
||||||
|
|
||||||
_cksumNum = (w * h / (8 * 8));
|
|
||||||
|
|
||||||
_transactionDetails.sizeChanged = true;
|
_transactionDetails.sizeChanged = true;
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSystem_LINUXMOTO::loadGFXMode() {
|
bool OSystem_LINUXMOTO::loadGFXMode() {
|
||||||
@ -173,7 +168,6 @@ void OSystem_LINUXMOTO::drawMouse() {
|
|||||||
|
|
||||||
SDL_Rect dst;
|
SDL_Rect dst;
|
||||||
int scale;
|
int scale;
|
||||||
int width, height;
|
|
||||||
int hotX, hotY;
|
int hotX, hotY;
|
||||||
|
|
||||||
if (_videoMode.mode == GFX_HALF && !_overlayVisible) {
|
if (_videoMode.mode == GFX_HALF && !_overlayVisible) {
|
||||||
@ -186,16 +180,12 @@ void OSystem_LINUXMOTO::drawMouse() {
|
|||||||
|
|
||||||
if (!_overlayVisible) {
|
if (!_overlayVisible) {
|
||||||
scale = _videoMode.scaleFactor;
|
scale = _videoMode.scaleFactor;
|
||||||
width = _videoMode.screenWidth;
|
|
||||||
height = _videoMode.screenHeight;
|
|
||||||
dst.w = _mouseCurState.vW;
|
dst.w = _mouseCurState.vW;
|
||||||
dst.h = _mouseCurState.vH;
|
dst.h = _mouseCurState.vH;
|
||||||
hotX = _mouseCurState.vHotX;
|
hotX = _mouseCurState.vHotX;
|
||||||
hotY = _mouseCurState.vHotY;
|
hotY = _mouseCurState.vHotY;
|
||||||
} else {
|
} else {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
width = _videoMode.overlayWidth;
|
|
||||||
height = _videoMode.overlayHeight;
|
|
||||||
dst.w = _mouseCurState.rW;
|
dst.w = _mouseCurState.rW;
|
||||||
dst.h = _mouseCurState.rH;
|
dst.h = _mouseCurState.rH;
|
||||||
hotX = _mouseCurState.rHotX;
|
hotX = _mouseCurState.rHotX;
|
||||||
|
@ -624,23 +624,6 @@ void OSystem_PS2::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x,
|
|||||||
_screen->setMouseOverlay(buf, w, h, hotspot_x, hotspot_y, keycolor);
|
_screen->setMouseOverlay(buf, w, h, hotspot_x, hotspot_y, keycolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OSystem_PS2::openCD(int drive) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OSystem_PS2::pollCD(void) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_PS2::playCD(int track, int num_loops, int start_frame, int duration) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_PS2::stopCD(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_PS2::updateCD(void) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_PS2::showOverlay(void) {
|
void OSystem_PS2::showOverlay(void) {
|
||||||
_screen->showOverlay();
|
_screen->showOverlay();
|
||||||
}
|
}
|
||||||
|
@ -97,12 +97,6 @@ public:
|
|||||||
|
|
||||||
virtual Audio::Mixer *getMixer();
|
virtual Audio::Mixer *getMixer();
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
virtual MutexRef createMutex(void);
|
virtual MutexRef createMutex(void);
|
||||||
virtual void lockMutex(MutexRef mutex);
|
virtual void lockMutex(MutexRef mutex);
|
||||||
virtual void unlockMutex(MutexRef mutex);
|
virtual void unlockMutex(MutexRef mutex);
|
||||||
|
@ -129,7 +129,8 @@ SDLFLAGS := $(shell $(PSPBIN)/sdl-config --cflags)
|
|||||||
SDLLIBS := $(shell $(PSPBIN)/sdl-config --libs)
|
SDLLIBS := $(shell $(PSPBIN)/sdl-config --libs)
|
||||||
# PSP LIBS
|
# PSP LIBS
|
||||||
PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \
|
PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \
|
||||||
-lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspkernel
|
-lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \
|
||||||
|
-lpspkernel
|
||||||
|
|
||||||
# Add in PSPSDK includes and libraries.
|
# Add in PSPSDK includes and libraries.
|
||||||
CXXFLAGS += $(SDLFLAGS)
|
CXXFLAGS += $(SDLFLAGS)
|
||||||
@ -148,7 +149,9 @@ OBJS := powerman.o \
|
|||||||
trace.o \
|
trace.o \
|
||||||
psploader.o \
|
psploader.o \
|
||||||
pspkeyboard.o \
|
pspkeyboard.o \
|
||||||
audio.o
|
audio.o \
|
||||||
|
thread.o \
|
||||||
|
mp3.o
|
||||||
|
|
||||||
# Include common Scummvm makefile
|
# Include common Scummvm makefile
|
||||||
include $(srcdir)/Makefile.common
|
include $(srcdir)/Makefile.common
|
||||||
|
@ -23,12 +23,12 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
#include <pspthreadman.h>
|
#include <pspthreadman.h>
|
||||||
#include <pspaudio.h>
|
#include <pspaudio.h>
|
||||||
|
|
||||||
#include "common/scummsys.h"
|
#include "common/scummsys.h"
|
||||||
#include "backends/platform/psp/audio.h"
|
#include "backends/platform/psp/audio.h"
|
||||||
|
#include "backends/platform/psp/thread.h"
|
||||||
|
|
||||||
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
|
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
|
||||||
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
|
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
|
||||||
@ -79,7 +79,6 @@ bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, call
|
|||||||
_bufferSize = numOfSamples * numOfChannels * sizeof(uint16); // should be the right size to send the app
|
_bufferSize = numOfSamples * numOfChannels * sizeof(uint16); // should be the right size to send the app
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
_userData = userData;
|
_userData = userData;
|
||||||
_emptyBuffers = NUM_BUFFERS;
|
|
||||||
_bufferToFill = 0;
|
_bufferToFill = 0;
|
||||||
_bufferToPlay = 0;
|
_bufferToPlay = 0;
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, call
|
|||||||
|
|
||||||
bool PspAudio::createThread() {
|
bool PspAudio::createThread() {
|
||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
int threadId = sceKernelCreateThread("audioThread", thread, 30, 16*1024, THREAD_ATTR_USER, 0);
|
int threadId = sceKernelCreateThread("audioThread", thread, PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD, THREAD_ATTR_USER, 0);
|
||||||
|
|
||||||
if (threadId < 0) { // error
|
if (threadId < 0) { // error
|
||||||
PSP_ERROR("failed to create audio thread. Error code %d\n", threadId);
|
PSP_ERROR("failed to create audio thread. Error code %d\n", threadId);
|
||||||
@ -122,10 +121,7 @@ int PspAudio::thread(SceSize, void *__this) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The real thread function
|
// The real thread function
|
||||||
void PspAudio::audioThread() {
|
void PspAudio::audioThread() {
|
||||||
bool isPlaying = false;
|
|
||||||
int remainingSamples = 0;
|
|
||||||
|
|
||||||
assert(_callback);
|
assert(_callback);
|
||||||
PSP_DEBUG_PRINT_FUNC("audio thread started\n");
|
PSP_DEBUG_PRINT_FUNC("audio thread started\n");
|
||||||
|
|
||||||
@ -133,63 +129,20 @@ void PspAudio::audioThread() {
|
|||||||
if (_paused)
|
if (_paused)
|
||||||
PSP_DEBUG_PRINT("audio thread paused\n");
|
PSP_DEBUG_PRINT("audio thread paused\n");
|
||||||
while (_paused) { // delay until we stop pausing
|
while (_paused) { // delay until we stop pausing
|
||||||
SDL_Delay(100);
|
sceKernelDelayThread(100000); // 100ms
|
||||||
|
if (!_paused)
|
||||||
|
PSP_DEBUG_PRINT("audio thread unpaused\n");
|
||||||
}
|
}
|
||||||
if (!_paused)
|
|
||||||
PSP_DEBUG_PRINT("audio thread unpaused\n");
|
|
||||||
|
|
||||||
// check if the audio is playing
|
|
||||||
remainingSamples = sceAudioGetChannelRestLen(_pspChannel);
|
|
||||||
if (remainingSamples < 0) {
|
|
||||||
PSP_ERROR("failed to get remaining samples\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isPlaying = remainingSamples ? true : false;
|
|
||||||
|
|
||||||
PSP_DEBUG_PRINT("remaining samples[%d]\n", remainingSamples);
|
PSP_DEBUG_PRINT("remaining samples[%d]\n", remainingSamples);
|
||||||
|
|
||||||
|
PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill);
|
||||||
|
_callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in
|
||||||
|
nextBuffer(_bufferToFill);
|
||||||
|
|
||||||
while (true) { // really only execute once. this just helps write the logic
|
PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay);
|
||||||
if (isPlaying) {
|
playBuffer();
|
||||||
_stoppedPlayingOnceFlag = false;
|
nextBuffer(_bufferToPlay);
|
||||||
|
|
||||||
// check if a buffer is empty
|
|
||||||
if (_emptyBuffers) { // we have some empty buffers
|
|
||||||
PSP_DEBUG_PRINT("sound playing & an empty buffer. filling buffer[%d]. empty buffers[%d]\n", _bufferToFill, _emptyBuffers);
|
|
||||||
_callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in
|
|
||||||
nextBuffer(_bufferToFill);
|
|
||||||
_emptyBuffers--;
|
|
||||||
break;
|
|
||||||
} else { // we have no empty buffers
|
|
||||||
// calculate how long we need to sleep. time(us) = samples * 1000000 / freq
|
|
||||||
// since frequency is always 44100, we can do a shortcut:
|
|
||||||
// time(us) = samples * (10000 / 441)
|
|
||||||
uint32 sleepTime = (remainingSamples * 10000) / 441;
|
|
||||||
if (!sleepTime)
|
|
||||||
break;
|
|
||||||
PSP_DEBUG_PRINT("sound playing & no empty buffers. sleeping for %d samples for %dus\n", remainingSamples, sleepTime);
|
|
||||||
sceKernelDelayThread(sleepTime);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else { // we're not playing right now
|
|
||||||
if (_stoppedPlayingOnceFlag == false) { // we only want to do this when we finish playing
|
|
||||||
nextBuffer(_bufferToPlay);
|
|
||||||
_emptyBuffers++;
|
|
||||||
_stoppedPlayingOnceFlag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_emptyBuffers == NUM_BUFFERS) { // problem: we have only empty buffers!
|
|
||||||
PSP_DEBUG_PRINT("no sound playing & no full buffer. filling buffer[%d]. empty buffers[%d]\n", _bufferToFill, _emptyBuffers);
|
|
||||||
_callback(_userData, _buffers[_bufferToFill], _bufferSize);
|
|
||||||
nextBuffer(_bufferToFill);
|
|
||||||
_emptyBuffers--;
|
|
||||||
break;
|
|
||||||
} else { // we have at least one non-empty buffer
|
|
||||||
PSP_DEBUG_PRINT("no sound playing & a full buffer. playing buffer[%d]. empty buffers[%d]\n", _bufferToPlay, _emptyBuffers);
|
|
||||||
playBuffer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // while true
|
|
||||||
} // while _init
|
} // while _init
|
||||||
|
|
||||||
// destroy everything
|
// destroy everything
|
||||||
@ -211,9 +164,9 @@ inline bool PspAudio::playBuffer() {
|
|||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
int ret;
|
int ret;
|
||||||
if (_numOfChannels == 1)
|
if (_numOfChannels == 1)
|
||||||
ret = sceAudioOutput(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
|
ret = sceAudioOutputBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
|
||||||
else
|
else
|
||||||
ret = sceAudioOutputPanned(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
|
ret = sceAudioOutputPannedBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
PSP_ERROR("failed to output audio. Error[%d]\n", ret);
|
PSP_ERROR("failed to output audio. Error[%d]\n", ret);
|
||||||
|
@ -35,8 +35,8 @@ public:
|
|||||||
typedef void (* callbackFunc)(void *userData, byte *samples, int len);
|
typedef void (* callbackFunc)(void *userData, byte *samples, int len);
|
||||||
PspAudio() : _pspChannel(0),
|
PspAudio() : _pspChannel(0),
|
||||||
_numOfChannels(0), _numOfSamples(0), _callback(0),
|
_numOfChannels(0), _numOfSamples(0), _callback(0),
|
||||||
_bufferToPlay(0), _bufferToFill(0), _emptyBuffers(NUM_BUFFERS),
|
_bufferToPlay(0), _bufferToFill(0),
|
||||||
_init(false), _paused(true), _stoppedPlayingOnceFlag(true) {
|
_init(false), _paused(true) {
|
||||||
for (int i=0; i<NUM_BUFFERS; i++)
|
for (int i=0; i<NUM_BUFFERS; i++)
|
||||||
_buffers[i] = 0;
|
_buffers[i] = 0;
|
||||||
}
|
}
|
||||||
@ -62,10 +62,8 @@ private:
|
|||||||
int _bufferToPlay; // the next buffer to output
|
int _bufferToPlay; // the next buffer to output
|
||||||
int _bufferToFill;
|
int _bufferToFill;
|
||||||
int _bufferSize;
|
int _bufferSize;
|
||||||
int _emptyBuffers;
|
|
||||||
bool _init; // flag for initialization
|
bool _init; // flag for initialization
|
||||||
bool _paused;
|
bool _paused;
|
||||||
bool _stoppedPlayingOnceFlag; // used to make sure we know when the playing stopped
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PSP_AUDIO_H */
|
#endif /* PSP_AUDIO_H */
|
||||||
|
@ -686,17 +686,18 @@ void GuRenderer::fillVertices(Vertex *vertices) {
|
|||||||
uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0;
|
uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0;
|
||||||
uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0;
|
uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0;
|
||||||
|
|
||||||
|
// Save scaled offset on screen
|
||||||
|
float scaledOffsetOnScreenX = scaleSourceToOutputX(_offsetOnScreen.x);
|
||||||
|
float scaledOffsetOnScreenY = scaleSourceToOutputY(_offsetOnScreen.y);
|
||||||
|
|
||||||
float imageStartX, imageStartY, imageEndX, imageEndY;
|
float imageStartX, imageStartY, imageEndX, imageEndY;
|
||||||
|
|
||||||
imageStartX = gapX + (scaleSourceToOutputX(_maxTextureOffset.x));
|
imageStartX = gapX + scaledOffsetOnScreenX + (scaleSourceToOutputX(_maxTextureOffset.x));
|
||||||
imageStartY = gapY;
|
imageStartY = gapY + scaledOffsetOnScreenY;
|
||||||
|
|
||||||
imageStartX += scaleSourceToOutputX(_offsetOnScreen.x);
|
|
||||||
imageStartY += scaleSourceToOutputY(_offsetOnScreen.y);
|
|
||||||
|
|
||||||
if (_fullScreen) { // shortcut
|
if (_fullScreen) { // shortcut
|
||||||
imageEndX = PSP_SCREEN_WIDTH - gapX;
|
imageEndX = PSP_SCREEN_WIDTH - gapX + scaledOffsetOnScreenX;
|
||||||
imageEndY = PSP_SCREEN_HEIGHT - gapY;
|
imageEndY = PSP_SCREEN_HEIGHT - gapY + scaledOffsetOnScreenY; // needed for screen shake
|
||||||
} else { /* !fullScreen */
|
} else { /* !fullScreen */
|
||||||
imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width);
|
imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width);
|
||||||
imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height);
|
imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height);
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "backends/platform/psp/default_display_client.h"
|
#include "backends/platform/psp/default_display_client.h"
|
||||||
#include "backends/platform/psp/cursor.h"
|
#include "backends/platform/psp/cursor.h"
|
||||||
#include "backends/platform/psp/pspkeyboard.h"
|
#include "backends/platform/psp/pspkeyboard.h"
|
||||||
|
#include "backends/platform/psp/thread.h"
|
||||||
|
|
||||||
#define USE_DISPLAY_CALLBACK // to use callback for finishing the render
|
#define USE_DISPLAY_CALLBACK // to use callback for finishing the render
|
||||||
#include "backends/platform/psp/display_manager.h"
|
#include "backends/platform/psp/display_manager.h"
|
||||||
@ -64,7 +65,7 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = {
|
|||||||
|
|
||||||
void MasterGuRenderer::setupCallbackThread() {
|
void MasterGuRenderer::setupCallbackThread() {
|
||||||
DEBUG_ENTER_FUNC();
|
DEBUG_ENTER_FUNC();
|
||||||
int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, 0x11, 4*1024, THREAD_ATTR_USER, 0);
|
int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD, THREAD_ATTR_USER, 0);
|
||||||
|
|
||||||
PSP_DEBUG_PRINT("Display CB thread id is %x\n", thid);
|
PSP_DEBUG_PRINT("Display CB thread id is %x\n", thid);
|
||||||
|
|
||||||
|
@ -13,7 +13,9 @@ MODULE_OBJS := powerman.o \
|
|||||||
trace.o \
|
trace.o \
|
||||||
psploader.o \
|
psploader.o \
|
||||||
pspkeyboard.o \
|
pspkeyboard.o \
|
||||||
audio.o
|
audio.o \
|
||||||
|
thread.o \
|
||||||
|
mp3.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
backends/platform/psp/
|
backends/platform/psp/
|
||||||
|
487
backends/platform/psp/mp3.cpp
Normal file
487
backends/platform/psp/mp3.cpp
Normal file
@ -0,0 +1,487 @@
|
|||||||
|
/* ScummVM - Graphic Adventure Engine
|
||||||
|
*
|
||||||
|
* ScummVM is the legal property of its developers, whose names
|
||||||
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||||
|
* file distributed with this source distribution.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/stream.h"
|
||||||
|
#include "common/util.h"
|
||||||
|
#include "common/singleton.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
|
||||||
|
#include "sound/audiostream.h"
|
||||||
|
|
||||||
|
#include <pspaudiocodec.h>
|
||||||
|
#include <psputility_modules.h>
|
||||||
|
#include <pspthreadman.h>
|
||||||
|
#include <pspsysmem.h>
|
||||||
|
#include <pspmodulemgr.h>
|
||||||
|
#include <psputility_avmodules.h>
|
||||||
|
#include <mad.h>
|
||||||
|
#include "backends/platform/psp/mp3.h"
|
||||||
|
|
||||||
|
//#define DISABLE_PSP_MP3 // to make us use the regular MAD decoder instead
|
||||||
|
|
||||||
|
//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
|
||||||
|
//#define __PSP_DEBUG_PRINT__
|
||||||
|
#include "backends/platform/psp/trace.h"
|
||||||
|
|
||||||
|
//#define PRINT_BUFFERS /* to debug MP3 buffers */
|
||||||
|
|
||||||
|
namespace Audio {
|
||||||
|
|
||||||
|
class Mp3PspStream;
|
||||||
|
|
||||||
|
bool Mp3PspStream::_decoderInit = false; // has the decoder been initialized
|
||||||
|
#ifdef DISABLE_PSP_MP3
|
||||||
|
bool Mp3PspStream::_decoderFail = true; // pretend the decoder failed
|
||||||
|
#else
|
||||||
|
bool Mp3PspStream::_decoderFail = false; // has the decoder failed to load
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Mp3PspStream::initDecoder() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (_decoderInit) {
|
||||||
|
PSP_ERROR("Already initialized!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on PSP firmware version, we need to do different things to do Media Engine processing
|
||||||
|
uint32 firmware = sceKernelDevkitVersion();
|
||||||
|
PSP_DEBUG_PRINT("Firmware version 0x%x\n", firmware);
|
||||||
|
if (firmware == 0x01050001){
|
||||||
|
if (!loadStartAudioModule((char *)(void *)"flash0:/kd/me_for_vsh.prx",
|
||||||
|
PSP_MEMORY_PARTITION_KERNEL)) {
|
||||||
|
PSP_ERROR("failed to load me_for_vsh.prx. ME cannot start.\n");
|
||||||
|
_decoderFail = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!loadStartAudioModule((char *)(void *)"flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL)) {
|
||||||
|
PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n");
|
||||||
|
_decoderFail = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) {
|
||||||
|
PSP_ERROR("failed to load AVCODEC module.\n");
|
||||||
|
_decoderFail = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PSP_INFO_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening
|
||||||
|
|
||||||
|
_decoderInit = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mp3PspStream::stopDecoder() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (!_decoderInit)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Based on PSP firmware version, we need to do different things to do Media Engine processing
|
||||||
|
if (sceKernelDevkitVersion() == 0x01050001){
|
||||||
|
/* if (!unloadAudioModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL) ||
|
||||||
|
!unloadAudioModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL) {
|
||||||
|
PSP_ERROR("failed to unload audio module\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}else{
|
||||||
|
if (sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) < 0) {
|
||||||
|
PSP_ERROR("failed to unload avcodec module\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_decoderInit = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load a PSP audio module
|
||||||
|
bool Mp3PspStream::loadStartAudioModule(const char *modname, int partition){
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
SceKernelLMOption option;
|
||||||
|
SceUID modid;
|
||||||
|
|
||||||
|
memset(&option, 0, sizeof(option));
|
||||||
|
option.size = sizeof(option);
|
||||||
|
option.mpidtext = partition;
|
||||||
|
option.mpiddata = partition;
|
||||||
|
option.position = 0;
|
||||||
|
option.access = 1;
|
||||||
|
|
||||||
|
modid = sceKernelLoadModule(modname, 0, &option);
|
||||||
|
if (modid < 0) {
|
||||||
|
PSP_ERROR("Failed to load module %s. Got error 0x%x\n", modname, modid);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = sceKernelStartModule(modid, 0, NULL, NULL, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
PSP_ERROR("Failed to start module %s. Got error 0x%x\n", modname, ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make parallel function for unloading the 1.50 modules
|
||||||
|
|
||||||
|
Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
|
||||||
|
_inStream(inStream),
|
||||||
|
_disposeAfterUse(dispose),
|
||||||
|
_pcmLength(0),
|
||||||
|
_posInFrame(0),
|
||||||
|
_state(MP3_STATE_INIT),
|
||||||
|
_length(0, 1000),
|
||||||
|
_sampleRate(0),
|
||||||
|
_totalTime(mad_timer_zero) {
|
||||||
|
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
assert(_decoderInit); // must be initialized by now
|
||||||
|
|
||||||
|
// let's leave the buffer guard -- who knows, it may be good?
|
||||||
|
memset(_buf, 0, sizeof(_buf));
|
||||||
|
memset(_codecInBuffer, 0, sizeof(_codecInBuffer));
|
||||||
|
|
||||||
|
initStream(); // init needed stuff for the stream
|
||||||
|
|
||||||
|
while (_state != MP3_STATE_EOS)
|
||||||
|
findValidHeader(); // get a first header so we can read basic stuff
|
||||||
|
|
||||||
|
_sampleRate = _header.samplerate; // copy it before it gets destroyed
|
||||||
|
|
||||||
|
_length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate());
|
||||||
|
|
||||||
|
//initStreamME(); // init the stuff needed for the ME to work
|
||||||
|
|
||||||
|
deinitStream();
|
||||||
|
//releaseStreamME();
|
||||||
|
|
||||||
|
_state = MP3_STATE_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Mp3PspStream::initStream() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (_state != MP3_STATE_INIT)
|
||||||
|
deinitStream();
|
||||||
|
|
||||||
|
// Init MAD
|
||||||
|
mad_stream_init(&_stream);
|
||||||
|
mad_header_init(&_header);
|
||||||
|
|
||||||
|
// Reset the stream data
|
||||||
|
_inStream->seek(0, SEEK_SET);
|
||||||
|
_totalTime = mad_timer_zero;
|
||||||
|
_posInFrame = 0;
|
||||||
|
|
||||||
|
// Update state
|
||||||
|
_state = MP3_STATE_READY;
|
||||||
|
|
||||||
|
// Read the first few sample bytes into the buffer
|
||||||
|
readMP3DataIntoBuffer();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mp3PspStream::initStreamME() {
|
||||||
|
// The following will eventually go into the thread
|
||||||
|
sceAudiocodecReleaseEDRAM(_codecParams); // do we need this?
|
||||||
|
|
||||||
|
memset(_codecParams, 0, sizeof(_codecParams));
|
||||||
|
|
||||||
|
// Init the MP3 hardware
|
||||||
|
int ret = 0;
|
||||||
|
ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002);
|
||||||
|
if (ret < 0) {
|
||||||
|
PSP_ERROR("failed to init MP3 ME module. sceAudiocodecCheckNeedMem returned 0x%x.\n", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PSP_DEBUG_PRINT("sceAudiocodecCheckNeedMem returned %d\n", ret);
|
||||||
|
ret = sceAudiocodecGetEDRAM(_codecParams, 0x1002);
|
||||||
|
if (ret < 0) {
|
||||||
|
PSP_ERROR("failed to init MP3 ME module. sceAudiocodecGetEDRAM returned 0x%x.\n", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret);
|
||||||
|
|
||||||
|
PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate);
|
||||||
|
_codecParams[10] = _sampleRate;
|
||||||
|
|
||||||
|
ret = sceAudiocodecInit(_codecParams, 0x1002);
|
||||||
|
if (ret < 0) {
|
||||||
|
PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mp3PspStream::~Mp3PspStream() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
deinitStream();
|
||||||
|
releaseStreamME(); // free the memory used for this stream
|
||||||
|
|
||||||
|
if (_disposeAfterUse == DisposeAfterUse::YES)
|
||||||
|
delete _inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mp3PspStream::deinitStream() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (_state == MP3_STATE_INIT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Deinit MAD
|
||||||
|
mad_header_finish(&_header);
|
||||||
|
mad_stream_finish(&_stream);
|
||||||
|
|
||||||
|
_state = MP3_STATE_EOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mp3PspStream::releaseStreamME() {
|
||||||
|
sceAudiocodecReleaseEDRAM(_codecParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mp3PspStream::decodeMP3Data() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (_state == MP3_STATE_INIT) {
|
||||||
|
initStream();
|
||||||
|
initStreamME();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_state == MP3_STATE_EOS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
findValidHeader(); // seach for next valid header
|
||||||
|
|
||||||
|
while (_state == MP3_STATE_READY) {
|
||||||
|
_stream.error = MAD_ERROR_NONE;
|
||||||
|
|
||||||
|
uint32 frame_size = _stream.next_frame - _stream.this_frame;
|
||||||
|
uint32 samplesPerFrame = _header.layer == MAD_LAYER_III ? 576 : 1152; // Varies by layer
|
||||||
|
// calculate frame size -- try
|
||||||
|
//uint32 calc_frame_size = ((144 * _header.bitrate) / 22050) + (_header.flags & MAD_FLAG_PADDING ? 1 : 0);
|
||||||
|
|
||||||
|
// Get stereo/mono
|
||||||
|
uint32 multFactor = 1;
|
||||||
|
if (_header.mode != MAD_MODE_SINGLE_CHANNEL) // mono - x2 for 16bit
|
||||||
|
multFactor *= 2; // stereo - x4 for 16bit
|
||||||
|
|
||||||
|
PSP_DEBUG_PRINT("MP3 frame size[%d]. Samples[%d]. Multfactor[%d] pad[%d]\n", frame_size, samplesPerFrame, multFactor, _header.flags & MAD_FLAG_PADDING);
|
||||||
|
memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned
|
||||||
|
|
||||||
|
// set up parameters for ME
|
||||||
|
_codecParams[6] = (unsigned long)_codecInBuffer;
|
||||||
|
_codecParams[8] = (unsigned long)_pcmSamples;
|
||||||
|
_codecParams[7] = frame_size;
|
||||||
|
_codecParams[9] = samplesPerFrame * multFactor; // x2 for stereo
|
||||||
|
|
||||||
|
// debug
|
||||||
|
#ifdef PRINT_BUFFERS
|
||||||
|
PSP_DEBUG_PRINT("mp3 frame:\n");
|
||||||
|
for (int i=0; i < (int)frame_size; i++) {
|
||||||
|
PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]);
|
||||||
|
}
|
||||||
|
PSP_DEBUG_PRINT("\n");
|
||||||
|
#endif
|
||||||
|
// Decode the next frame
|
||||||
|
// This function blocks. We'll want to put it in a thread
|
||||||
|
int ret = sceAudiocodecDecode(_codecParams, 0x1002);
|
||||||
|
if (ret < 0) {
|
||||||
|
PSP_ERROR("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret);
|
||||||
|
// handle error here
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRINT_BUFFERS
|
||||||
|
PSP_DEBUG_PRINT("PCM frame:\n");
|
||||||
|
for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2
|
||||||
|
PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]);
|
||||||
|
}
|
||||||
|
PSP_DEBUG_PRINT("\n");
|
||||||
|
#endif
|
||||||
|
_pcmLength = samplesPerFrame;
|
||||||
|
_posInFrame = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
|
||||||
|
|
||||||
|
if (_stream.error != MAD_ERROR_NONE) // catch EOS
|
||||||
|
_state = MP3_STATE_EOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mp3PspStream::readMP3DataIntoBuffer() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
uint32 remaining = 0;
|
||||||
|
|
||||||
|
// Give up immediately if we already used up all data in the stream
|
||||||
|
if (_inStream->eos()) {
|
||||||
|
_state = MP3_STATE_EOS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stream.next_frame) {
|
||||||
|
// If there is still data in the MAD stream, we need to preserve it.
|
||||||
|
// Note that we use memmove, as we are reusing the same buffer,
|
||||||
|
// and hence the data regions we copy from and to may overlap.
|
||||||
|
remaining = _stream.bufend - _stream.next_frame;
|
||||||
|
assert(remaining < BUFFER_SIZE); // Paranoia check
|
||||||
|
memmove(_buf, _stream.next_frame, remaining); // TODO: may want another buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to read the next block
|
||||||
|
uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining);
|
||||||
|
if (size <= 0) {
|
||||||
|
_state = MP3_STATE_EOS;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feed the data we just read into the stream decoder
|
||||||
|
_stream.error = MAD_ERROR_NONE;
|
||||||
|
mad_stream_buffer(&_stream, _buf, size + remaining); // just setup the pointers
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mp3PspStream::seek(const Timestamp &where) {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (where == _length) {
|
||||||
|
_state = MP3_STATE_EOS;
|
||||||
|
return true;
|
||||||
|
} else if (where > _length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 time = where.msecs();
|
||||||
|
|
||||||
|
mad_timer_t destination;
|
||||||
|
mad_timer_set(&destination, time / 1000, time % 1000, 1000);
|
||||||
|
|
||||||
|
// Check if we need to rewind
|
||||||
|
if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) {
|
||||||
|
initStream();
|
||||||
|
initStreamME();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The ME will need clear data no matter what once we seek?
|
||||||
|
//if (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
|
||||||
|
// initStreamME();
|
||||||
|
|
||||||
|
// Skip ahead
|
||||||
|
while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS)
|
||||||
|
findValidHeader();
|
||||||
|
|
||||||
|
return (_state != MP3_STATE_EOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seek in the stream, finding the next valid header
|
||||||
|
void Mp3PspStream::findValidHeader() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (_state != MP3_STATE_READY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If necessary, load more data into the stream decoder
|
||||||
|
if (_stream.error == MAD_ERROR_BUFLEN)
|
||||||
|
readMP3DataIntoBuffer();
|
||||||
|
|
||||||
|
while (_state != MP3_STATE_EOS) {
|
||||||
|
_stream.error = MAD_ERROR_NONE;
|
||||||
|
|
||||||
|
// Decode the next header.
|
||||||
|
if (mad_header_decode(&_header, &_stream) == -1) {
|
||||||
|
if (_stream.error == MAD_ERROR_BUFLEN) {
|
||||||
|
readMP3DataIntoBuffer(); // Read more data
|
||||||
|
continue;
|
||||||
|
} else if (MAD_RECOVERABLE(_stream.error)) {
|
||||||
|
debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum up the total playback time so far
|
||||||
|
mad_timer_add(&_totalTime, _header.duration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_stream.error != MAD_ERROR_NONE)
|
||||||
|
_state = MP3_STATE_EOS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
int samples = 0;
|
||||||
|
#ifdef PRINT_BUFFERS
|
||||||
|
int16 *debugBuffer = buffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Keep going as long as we have input available
|
||||||
|
while (samples < numSamples && _state != MP3_STATE_EOS) {
|
||||||
|
const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header));
|
||||||
|
|
||||||
|
while (samples < len) {
|
||||||
|
*buffer++ = _pcmSamples[_posInFrame << 1];
|
||||||
|
samples++;
|
||||||
|
if (MAD_NCHANNELS(&_header) == 2) {
|
||||||
|
*buffer++ = _pcmSamples[(_posInFrame << 1) + 1];
|
||||||
|
samples++;
|
||||||
|
}
|
||||||
|
_posInFrame++; // always skip an extra sample since ME always outputs stereo
|
||||||
|
}
|
||||||
|
|
||||||
|
//memcpy(buffer, &_pcmSamples[_posInFrame], len << 1); // 16 bits
|
||||||
|
//_posInFrame += len; // next time we start from the middle
|
||||||
|
|
||||||
|
if (_posInFrame >= _pcmLength) {
|
||||||
|
// We used up all PCM data in the current frame -- read & decode more
|
||||||
|
decodeMP3Data();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PRINT_BUFFERS
|
||||||
|
PSP_INFO_PRINT("buffer:\n");
|
||||||
|
for (int i = 0; i<numSamples; i++)
|
||||||
|
PSP_INFO_PRINT("%d ", debugBuffer[i]);
|
||||||
|
PSP_INFO_PRINT("\n\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace Audio
|
||||||
|
|
||||||
|
|
121
backends/platform/psp/mp3.h
Normal file
121
backends/platform/psp/mp3.h
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/* ScummVM - Graphic Adventure Engine
|
||||||
|
*
|
||||||
|
* ScummVM is the legal property of its developers, whose names
|
||||||
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||||
|
* file distributed with this source distribution.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOUND_MP3_PSP_H
|
||||||
|
#define SOUND_MP3_PSP_H
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
class SeekableReadStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Audio {
|
||||||
|
|
||||||
|
class AudioStream;
|
||||||
|
class SeekableAudioStream;
|
||||||
|
|
||||||
|
class Mp3PspStream : public SeekableAudioStream {
|
||||||
|
protected:
|
||||||
|
enum State {
|
||||||
|
MP3_STATE_INIT, // Need to init the decoder
|
||||||
|
MP3_STATE_READY, // ready for processing data
|
||||||
|
MP3_STATE_EOS // end of data reached (may need to loop)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_SAMPLES_PER_FRAME 2048 * 2
|
||||||
|
int16 _pcmSamples[MAX_SAMPLES_PER_FRAME] __attribute__((aligned(64))); // samples to output PCM data into
|
||||||
|
byte _codecInBuffer[3072] __attribute__((aligned(64))); // the codec always needs alignment
|
||||||
|
unsigned long _codecParams[65]__attribute__((aligned(64))); // TODO: change to struct
|
||||||
|
|
||||||
|
Common::SeekableReadStream *_inStream;
|
||||||
|
DisposeAfterUse::Flag _disposeAfterUse;
|
||||||
|
|
||||||
|
uint32 _pcmLength; // how many pcm samples we have (/2 for mono)
|
||||||
|
|
||||||
|
uint _posInFrame; // position in frame
|
||||||
|
State _state; // what state the stream is in
|
||||||
|
|
||||||
|
Timestamp _length;
|
||||||
|
uint32 _sampleRate;
|
||||||
|
|
||||||
|
mad_timer_t _totalTime;
|
||||||
|
mad_stream _stream; //
|
||||||
|
mad_header _header; // This is all we need from libmad
|
||||||
|
|
||||||
|
static bool _decoderInit; // has the decoder been initialized
|
||||||
|
static bool _decoderFail; // has the decoder failed to load
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BUFFER_SIZE = 5 * 8192
|
||||||
|
};
|
||||||
|
|
||||||
|
// This buffer contains a slab of input data
|
||||||
|
byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
|
||||||
|
|
||||||
|
void decodeMP3Data();
|
||||||
|
void readMP3DataIntoBuffer();
|
||||||
|
|
||||||
|
static bool loadStartAudioModule(const char *modname, int partition);
|
||||||
|
int initStream();
|
||||||
|
void findValidHeader();
|
||||||
|
void deinitStream();
|
||||||
|
|
||||||
|
// to init and uninit ME decoder
|
||||||
|
static bool initDecoder();
|
||||||
|
static bool stopDecoder();
|
||||||
|
|
||||||
|
// ME functions for stream
|
||||||
|
bool initStreamME();
|
||||||
|
void releaseStreamME();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose);
|
||||||
|
~Mp3PspStream();
|
||||||
|
|
||||||
|
// This function avoids having to create streams when it's not possible
|
||||||
|
static inline bool isOkToCreateStream() {
|
||||||
|
if (_decoderFail) // fatal failure
|
||||||
|
return false;
|
||||||
|
if (!_decoderInit) // if we're not initialized
|
||||||
|
if (!initDecoder()) // check if we failed init
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readBuffer(int16 *buffer, const int numSamples);
|
||||||
|
|
||||||
|
bool endOfData() const { return _state == MP3_STATE_EOS; }
|
||||||
|
bool isStereo() const { return MAD_NCHANNELS(&_header) == 2; }
|
||||||
|
int getRate() const { return _header.samplerate; }
|
||||||
|
|
||||||
|
bool seek(const Timestamp &where);
|
||||||
|
Timestamp getLength() const { return _length; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Audio
|
||||||
|
|
||||||
|
#endif // #ifndef SOUND_MP3_PSP_H
|
@ -60,9 +60,9 @@ static int timer_handler(int t) {
|
|||||||
|
|
||||||
void OSystem_PSP::initSDL() {
|
void OSystem_PSP::initSDL() {
|
||||||
#ifdef USE_PSP_AUDIO
|
#ifdef USE_PSP_AUDIO
|
||||||
SDL_Init(SDL_INIT_TIMER);
|
SDL_Init(0);
|
||||||
#else
|
#else
|
||||||
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
|
SDL_Init(SDL_INIT_AUDIO);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ void OSystem_PSP::initBackend() {
|
|||||||
_inputHandler.init();
|
_inputHandler.init();
|
||||||
|
|
||||||
initSDL();
|
initSDL();
|
||||||
|
|
||||||
_savefile = new PSPSaveFileManager;
|
_savefile = new PSPSaveFileManager;
|
||||||
|
|
||||||
_timer = new DefaultTimerManager();
|
_timer = new DefaultTimerManager();
|
||||||
@ -298,17 +298,18 @@ bool OSystem_PSP::pollEvent(Common::Event &event) {
|
|||||||
return _inputHandler.getAllInputs(event);
|
return _inputHandler.getAllInputs(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32 OSystem_PSP::getMillis() {
|
uint32 OSystem_PSP::getMillis() {
|
||||||
return SDL_GetTicks();
|
return _pspRtc.getMillis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_PSP::delayMillis(uint msecs) {
|
void OSystem_PSP::delayMillis(uint msecs) {
|
||||||
SDL_Delay(msecs);
|
PspThread::delayMillis(msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) {
|
void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) {
|
||||||
SDL_SetTimer(interval, (SDL_TimerCallback)callback);
|
_pspTimer.setCallback((PspTimer::CallbackFunc)callback);
|
||||||
|
_pspTimer.setIntervalMs(interval);
|
||||||
|
_pspTimer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
OSystem::MutexRef OSystem_PSP::createMutex(void) {
|
OSystem::MutexRef OSystem_PSP::createMutex(void) {
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
#include "backends/platform/psp/display_manager.h"
|
#include "backends/platform/psp/display_manager.h"
|
||||||
#include "backends/platform/psp/input.h"
|
#include "backends/platform/psp/input.h"
|
||||||
#include "backends/platform/psp/audio.h"
|
#include "backends/platform/psp/audio.h"
|
||||||
|
#include "backends/timer/psp/timer.h"
|
||||||
|
#include "backends/platform/psp/thread.h"
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
@ -57,6 +59,8 @@ private:
|
|||||||
PSPKeyboard _keyboard;
|
PSPKeyboard _keyboard;
|
||||||
InputHandler _inputHandler;
|
InputHandler _inputHandler;
|
||||||
PspAudio _audio;
|
PspAudio _audio;
|
||||||
|
PspTimer _pspTimer;
|
||||||
|
PspRtc _pspRtc;
|
||||||
|
|
||||||
void initSDL();
|
void initSDL();
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
%rename lib old_lib
|
%rename lib old_lib
|
||||||
*lib:
|
*lib:
|
||||||
%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspkernel
|
%(old_lib) -lz -lstdc++ -lc -lm -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk -lpsputility -lpspuser -lpsppower -lpsphprm -lpsprtc -lpspaudio -lpspaudiocodec -lpspkernel
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <base/main.h>
|
#include <base/main.h>
|
||||||
#include <base/plugins.h>
|
#include <base/plugins.h>
|
||||||
#include "backends/platform/psp/powerman.h"
|
#include "backends/platform/psp/powerman.h"
|
||||||
|
#include "backends/platform/psp/thread.h"
|
||||||
|
|
||||||
#include "backends/plugins/psp/psp-provider.h"
|
#include "backends/plugins/psp/psp-provider.h"
|
||||||
#include "backends/platform/psp/psppixelformat.h"
|
#include "backends/platform/psp/psppixelformat.h"
|
||||||
@ -140,7 +141,7 @@ int CallbackThread(SceSize /*size*/, void *arg) {
|
|||||||
|
|
||||||
/* Sets up the callback thread and returns its thread id */
|
/* Sets up the callback thread and returns its thread id */
|
||||||
int SetupCallbacks(void) {
|
int SetupCallbacks(void) {
|
||||||
int thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, THREAD_ATTR_USER, 0);
|
int thid = sceKernelCreateThread("power_thread", CallbackThread, PRIORITY_POWER_THREAD, STACK_POWER_THREAD, THREAD_ATTR_USER, 0);
|
||||||
if (thid >= 0) {
|
if (thid >= 0) {
|
||||||
sceKernelStartThread(thid, 0, 0);
|
sceKernelStartThread(thid, 0, 0);
|
||||||
}
|
}
|
||||||
|
87
backends/platform/psp/thread.cpp
Normal file
87
backends/platform/psp/thread.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* 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.h $
|
||||||
|
* $Id: osys_psp.h 49173 2010-05-24 03:05:17Z bluddy $
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <psptypes.h>
|
||||||
|
#include <psprtc.h>
|
||||||
|
#include <pspthreadman.h>
|
||||||
|
|
||||||
|
#include "backends/platform/psp/thread.h"
|
||||||
|
#include "backends/platform/psp/trace.h"
|
||||||
|
|
||||||
|
void PspThread::delayMillis(uint32 ms) {
|
||||||
|
sceKernelDelayThread(ms * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PspThread::delayMicros(uint32 us) {
|
||||||
|
sceKernelDelayThread(us);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PspRtc::init() { // init our starting ticks
|
||||||
|
uint32 ticks[2];
|
||||||
|
sceRtcGetCurrentTick((u64 *)ticks);
|
||||||
|
|
||||||
|
_startMillis = ticks[0]/1000;
|
||||||
|
_startMicros = ticks[0];
|
||||||
|
//_lastMillis = ticks[0]/1000; //debug - only when we don't subtract startMillis
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MS_LOOP_AROUND 4294967 /* We loop every 2^32 / 1000 = 71 minutes */
|
||||||
|
#define MS_LOOP_CHECK 60000 /* Threading can cause weird mixups without this */
|
||||||
|
|
||||||
|
// Note that after we fill up 32 bits ie 50 days we'll loop back to 0, which may cause
|
||||||
|
// unpredictable results
|
||||||
|
uint32 PspRtc::getMillis() {
|
||||||
|
uint32 ticks[2];
|
||||||
|
|
||||||
|
sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays
|
||||||
|
|
||||||
|
uint32 millis = ticks[0]/1000;
|
||||||
|
millis -= _startMillis; // get ms since start of program
|
||||||
|
|
||||||
|
if ((int)_lastMillis - (int)millis > MS_LOOP_CHECK) { // we must have looped around
|
||||||
|
if (_looped == false) { // check to make sure threads do this once
|
||||||
|
_looped = true;
|
||||||
|
_milliOffset += MS_LOOP_AROUND; // add the needed offset
|
||||||
|
PSP_DEBUG_PRINT("looping around. last ms[%d], curr ms[%d]\n", _lastMillis, millis);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_looped = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_lastMillis = millis;
|
||||||
|
|
||||||
|
return millis + _milliOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 PspRtc::getMicros() {
|
||||||
|
uint32 ticks[2];
|
||||||
|
|
||||||
|
sceRtcGetCurrentTick((u64 *)ticks);
|
||||||
|
ticks[0] -= _startMicros;
|
||||||
|
|
||||||
|
return ticks[0];
|
||||||
|
}
|
||||||
|
|
68
backends/platform/psp/thread.h
Normal file
68
backends/platform/psp/thread.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* ScummVM - Graphic Adventure Engine
|
||||||
|
*
|
||||||
|
* ScummVM is the legal property of its developers, whose names
|
||||||
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||||
|
* file distributed with this source distribution.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/portdefs.h $
|
||||||
|
* $Id: portdefs.h 38687 2009-02-21 12:08:52Z joostp $
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PSP_THREAD_H
|
||||||
|
#define PSP_THREAD_H
|
||||||
|
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
|
||||||
|
class PspThread {
|
||||||
|
public:
|
||||||
|
static void delayMillis(uint32 ms);
|
||||||
|
static void delayMicros(uint32 us);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PspRtc {
|
||||||
|
private:
|
||||||
|
uint32 _startMillis;
|
||||||
|
uint32 _startMicros;
|
||||||
|
uint32 _lastMillis;
|
||||||
|
uint32 _milliOffset; // to prevent looping around of millis
|
||||||
|
bool _looped; // make sure we only loop once
|
||||||
|
public:
|
||||||
|
PspRtc() : _startMillis(0), _startMicros(0), _lastMillis(0), _milliOffset(0), _looped(false) { init(); }
|
||||||
|
void init();
|
||||||
|
uint32 getMillis();
|
||||||
|
uint32 getMicros();
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ThreadPriority {
|
||||||
|
PRIORITY_MAIN_THREAD = 36,
|
||||||
|
PRIORITY_TIMER_THREAD = 30,
|
||||||
|
PRIORITY_AUDIO_THREAD = 25, // must be higher than timer or we get stuttering
|
||||||
|
PRIORITY_POWER_THREAD = 20, // quite a light thread
|
||||||
|
PRIORITY_DISPLAY_THREAD = 17 // very light thread for callbacks only
|
||||||
|
};
|
||||||
|
|
||||||
|
enum StackSizes {
|
||||||
|
STACK_AUDIO_THREAD = 16 * 1024,
|
||||||
|
STACK_TIMER_THREAD = 32 * 1024,
|
||||||
|
STACK_DISPLAY_THREAD = 2 * 1024,
|
||||||
|
STACK_POWER_THREAD = 4 * 1024
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PSP_THREADS_H */
|
||||||
|
|
||||||
|
|
@ -30,7 +30,6 @@
|
|||||||
bool OSystem_SDL_SamsungTV::hasFeature(Feature f) {
|
bool OSystem_SDL_SamsungTV::hasFeature(Feature f) {
|
||||||
return
|
return
|
||||||
(f == kFeatureAspectRatioCorrection) ||
|
(f == kFeatureAspectRatioCorrection) ||
|
||||||
(f == kFeatureAutoComputeDirtyRects) ||
|
|
||||||
(f == kFeatureCursorHasPalette);
|
(f == kFeatureCursorHasPalette);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,12 +38,6 @@ void OSystem_SDL_SamsungTV::setFeatureState(Feature f, bool enable) {
|
|||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
setAspectRatioCorrection(enable);
|
setAspectRatioCorrection(enable);
|
||||||
break;
|
break;
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
if (enable)
|
|
||||||
_modeFlags |= DF_WANT_RECT_OPTIM;
|
|
||||||
else
|
|
||||||
_modeFlags &= ~DF_WANT_RECT_OPTIM;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -56,8 +49,6 @@ bool OSystem_SDL_SamsungTV::getFeatureState(Feature f) {
|
|||||||
switch (f) {
|
switch (f) {
|
||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
return _videoMode.aspectRatioCorrection;
|
return _videoMode.aspectRatioCorrection;
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
return _modeFlags & DF_WANT_RECT_OPTIM;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -469,12 +469,7 @@ void OSystem_SDL::initSize(uint w, uint h, const Graphics::PixelFormat *format)
|
|||||||
_videoMode.screenWidth = w;
|
_videoMode.screenWidth = w;
|
||||||
_videoMode.screenHeight = h;
|
_videoMode.screenHeight = h;
|
||||||
|
|
||||||
_cksumNum = (w * h / (8 * 8));
|
|
||||||
|
|
||||||
_transactionDetails.sizeChanged = true;
|
_transactionDetails.sizeChanged = true;
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int OSystem_SDL::effectiveScreenHeight() const {
|
int OSystem_SDL::effectiveScreenHeight() const {
|
||||||
@ -976,16 +971,7 @@ void OSystem_SDL::copyRectToScreen(const byte *src, int pitch, int x, int y, int
|
|||||||
assert(h > 0 && y + h <= _videoMode.screenHeight);
|
assert(h > 0 && y + h <= _videoMode.screenHeight);
|
||||||
assert(w > 0 && x + w <= _videoMode.screenWidth);
|
assert(w > 0 && x + w <= _videoMode.screenWidth);
|
||||||
|
|
||||||
if (IS_ALIGNED(src, 4) && pitch == _videoMode.screenWidth && x == 0 && y == 0 &&
|
addDirtyRect(x, y, w, h);
|
||||||
w == _videoMode.screenWidth && h == _videoMode.screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
|
|
||||||
/* Special, optimized case for full screen updates.
|
|
||||||
* It tries to determine what areas were actually changed,
|
|
||||||
* and just updates those, on the actual display. */
|
|
||||||
addDirtyRgnAuto(src);
|
|
||||||
} else {
|
|
||||||
_cksumValid = false;
|
|
||||||
addDirtyRect(x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to lock the screen surface
|
// Try to lock the screen surface
|
||||||
if (SDL_LockSurface(_screen) == -1)
|
if (SDL_LockSurface(_screen) == -1)
|
||||||
@ -1131,89 +1117,6 @@ void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool realCoordinates)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OSystem_SDL::makeChecksums(const byte *buf) {
|
|
||||||
assert(buf);
|
|
||||||
uint32 *sums = _dirtyChecksums;
|
|
||||||
uint x,y;
|
|
||||||
const uint last_x = (uint)_videoMode.screenWidth / 8;
|
|
||||||
const uint last_y = (uint)_videoMode.screenHeight / 8;
|
|
||||||
|
|
||||||
const uint BASE = 65521; /* largest prime smaller than 65536 */
|
|
||||||
|
|
||||||
/* the 8x8 blocks in buf are enumerated starting in the top left corner and
|
|
||||||
* reading each line at a time from left to right */
|
|
||||||
for (y = 0; y != last_y; y++, buf += _videoMode.screenWidth * (8 - 1))
|
|
||||||
for (x = 0; x != last_x; x++, buf += 8) {
|
|
||||||
// Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
|
|
||||||
// This computes the Adler32 checksum of a 8x8 pixel block. Note
|
|
||||||
// that we can do the modulo operation (which is the slowest part)
|
|
||||||
// of the algorithm) at the end, instead of doing each iteration,
|
|
||||||
// since we only have 64 iterations in total - and thus s1 and
|
|
||||||
// s2 can't overflow anyway.
|
|
||||||
uint32 s1 = 1;
|
|
||||||
uint32 s2 = 0;
|
|
||||||
const byte *ptr = buf;
|
|
||||||
for (int subY = 0; subY < 8; subY++) {
|
|
||||||
for (int subX = 0; subX < 8; subX++) {
|
|
||||||
s1 += ptr[subX];
|
|
||||||
s2 += s1;
|
|
||||||
}
|
|
||||||
ptr += _videoMode.screenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
s1 %= BASE;
|
|
||||||
s2 %= BASE;
|
|
||||||
|
|
||||||
/* output the checksum for this block */
|
|
||||||
*sums++ = (s2 << 16) + s1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OSystem_SDL::addDirtyRgnAuto(const byte *buf) {
|
|
||||||
assert(buf);
|
|
||||||
assert(IS_ALIGNED(buf, 4));
|
|
||||||
|
|
||||||
/* generate a table of the checksums */
|
|
||||||
makeChecksums(buf);
|
|
||||||
|
|
||||||
if (!_cksumValid) {
|
|
||||||
_forceFull = true;
|
|
||||||
_cksumValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* go through the checksum list, compare it with the previous checksums,
|
|
||||||
and add all dirty rectangles to a list. try to combine small rectangles
|
|
||||||
into bigger ones in a simple way */
|
|
||||||
if (!_forceFull) {
|
|
||||||
int x, y, w;
|
|
||||||
uint32 *ck = _dirtyChecksums;
|
|
||||||
|
|
||||||
for (y = 0; y != _videoMode.screenHeight / 8; y++) {
|
|
||||||
for (x = 0; x != _videoMode.screenWidth / 8; x++, ck++) {
|
|
||||||
if (ck[0] != ck[_cksumNum]) {
|
|
||||||
/* found a dirty 8x8 block, now go as far to the right as possible,
|
|
||||||
and at the same time, unmark the dirty status by setting old to new. */
|
|
||||||
w=0;
|
|
||||||
do {
|
|
||||||
ck[w + _cksumNum] = ck[w];
|
|
||||||
w++;
|
|
||||||
} while (x + w != _videoMode.screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
|
|
||||||
|
|
||||||
addDirtyRect(x * 8, y * 8, w * 8, 8);
|
|
||||||
|
|
||||||
if (_forceFull)
|
|
||||||
goto get_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
get_out:;
|
|
||||||
/* Copy old checksums to new */
|
|
||||||
memcpy(_dirtyChecksums + _cksumNum, _dirtyChecksums, _cksumNum * sizeof(uint32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int16 OSystem_SDL::getHeight() {
|
int16 OSystem_SDL::getHeight() {
|
||||||
return _videoMode.screenHeight;
|
return _videoMode.screenHeight;
|
||||||
}
|
}
|
||||||
@ -1432,7 +1335,6 @@ void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, i
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Mark the modified region as dirty
|
// Mark the modified region as dirty
|
||||||
_cksumValid = false;
|
|
||||||
addDirtyRect(x, y, w, h);
|
addDirtyRect(x, y, w, h);
|
||||||
|
|
||||||
if (SDL_LockSurface(_overlayscreen) == -1)
|
if (SDL_LockSurface(_overlayscreen) == -1)
|
||||||
@ -1771,7 +1673,6 @@ void OSystem_SDL::drawMouse() {
|
|||||||
|
|
||||||
SDL_Rect dst;
|
SDL_Rect dst;
|
||||||
int scale;
|
int scale;
|
||||||
int width, height;
|
|
||||||
int hotX, hotY;
|
int hotX, hotY;
|
||||||
|
|
||||||
dst.x = _mouseCurState.x;
|
dst.x = _mouseCurState.x;
|
||||||
@ -1779,16 +1680,12 @@ void OSystem_SDL::drawMouse() {
|
|||||||
|
|
||||||
if (!_overlayVisible) {
|
if (!_overlayVisible) {
|
||||||
scale = _videoMode.scaleFactor;
|
scale = _videoMode.scaleFactor;
|
||||||
width = _videoMode.screenWidth;
|
|
||||||
height = _videoMode.screenHeight;
|
|
||||||
dst.w = _mouseCurState.vW;
|
dst.w = _mouseCurState.vW;
|
||||||
dst.h = _mouseCurState.vH;
|
dst.h = _mouseCurState.vH;
|
||||||
hotX = _mouseCurState.vHotX;
|
hotX = _mouseCurState.vHotX;
|
||||||
hotY = _mouseCurState.vHotY;
|
hotY = _mouseCurState.vHotY;
|
||||||
} else {
|
} else {
|
||||||
scale = 1;
|
scale = 1;
|
||||||
width = _videoMode.overlayWidth;
|
|
||||||
height = _videoMode.overlayHeight;
|
|
||||||
dst.w = _mouseCurState.rW;
|
dst.w = _mouseCurState.rW;
|
||||||
dst.h = _mouseCurState.rH;
|
dst.h = _mouseCurState.rH;
|
||||||
hotX = _mouseCurState.rHotX;
|
hotX = _mouseCurState.rHotX;
|
||||||
|
@ -149,7 +149,6 @@ void OSystem_SDL::initBackend() {
|
|||||||
memset(&_videoMode, 0, sizeof(_videoMode));
|
memset(&_videoMode, 0, sizeof(_videoMode));
|
||||||
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
|
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
|
||||||
|
|
||||||
_cksumValid = false;
|
|
||||||
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS)
|
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS)
|
||||||
_videoMode.mode = GFX_DOUBLESIZE;
|
_videoMode.mode = GFX_DOUBLESIZE;
|
||||||
_videoMode.scaleFactor = 2;
|
_videoMode.scaleFactor = 2;
|
||||||
@ -163,7 +162,6 @@ void OSystem_SDL::initBackend() {
|
|||||||
_scalerProc = Normal1x;
|
_scalerProc = Normal1x;
|
||||||
#endif
|
#endif
|
||||||
_scalerType = 0;
|
_scalerType = 0;
|
||||||
_modeFlags = 0;
|
|
||||||
|
|
||||||
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
|
#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
|
||||||
_videoMode.fullscreen = ConfMan.getBool("fullscreen");
|
_videoMode.fullscreen = ConfMan.getBool("fullscreen");
|
||||||
@ -233,7 +231,7 @@ OSystem_SDL::OSystem_SDL()
|
|||||||
#endif
|
#endif
|
||||||
_overlayVisible(false),
|
_overlayVisible(false),
|
||||||
_overlayscreen(0), _tmpscreen2(0),
|
_overlayscreen(0), _tmpscreen2(0),
|
||||||
_cdrom(0), _scalerProc(0), _modeChanged(false), _screenChangeCount(0), _dirtyChecksums(0),
|
_cdrom(0), _scalerProc(0), _modeChanged(false), _screenChangeCount(0),
|
||||||
_scrollLock(false),
|
_scrollLock(false),
|
||||||
_mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0),
|
_mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0),
|
||||||
_mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true),
|
_mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true),
|
||||||
@ -251,9 +249,9 @@ OSystem_SDL::OSystem_SDL()
|
|||||||
_screenIsLocked(false),
|
_screenIsLocked(false),
|
||||||
_graphicsMutex(0), _transactionMode(kTransactionNone) {
|
_graphicsMutex(0), _transactionMode(kTransactionNone) {
|
||||||
|
|
||||||
// allocate palette storage
|
// clear palette storage
|
||||||
_currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
|
memset(_currentPalette, 0, sizeof(_currentPalette));
|
||||||
_cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
|
memset(_cursorPalette, 0, sizeof(_cursorPalette));
|
||||||
|
|
||||||
_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
|
_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
|
||||||
|
|
||||||
@ -281,9 +279,6 @@ OSystem_SDL::~OSystem_SDL() {
|
|||||||
SDL_RemoveTimer(_timerID);
|
SDL_RemoveTimer(_timerID);
|
||||||
closeMixer();
|
closeMixer();
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
free(_currentPalette);
|
|
||||||
free(_cursorPalette);
|
|
||||||
free(_mouseData);
|
free(_mouseData);
|
||||||
|
|
||||||
delete _savefile;
|
delete _savefile;
|
||||||
@ -453,7 +448,6 @@ bool OSystem_SDL::hasFeature(Feature f) {
|
|||||||
return
|
return
|
||||||
(f == kFeatureFullscreenMode) ||
|
(f == kFeatureFullscreenMode) ||
|
||||||
(f == kFeatureAspectRatioCorrection) ||
|
(f == kFeatureAspectRatioCorrection) ||
|
||||||
(f == kFeatureAutoComputeDirtyRects) ||
|
|
||||||
(f == kFeatureCursorHasPalette) ||
|
(f == kFeatureCursorHasPalette) ||
|
||||||
(f == kFeatureIconifyWindow);
|
(f == kFeatureIconifyWindow);
|
||||||
}
|
}
|
||||||
@ -466,12 +460,6 @@ void OSystem_SDL::setFeatureState(Feature f, bool enable) {
|
|||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
setAspectRatioCorrection(enable);
|
setAspectRatioCorrection(enable);
|
||||||
break;
|
break;
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
if (enable)
|
|
||||||
_modeFlags |= DF_WANT_RECT_OPTIM;
|
|
||||||
else
|
|
||||||
_modeFlags &= ~DF_WANT_RECT_OPTIM;
|
|
||||||
break;
|
|
||||||
case kFeatureIconifyWindow:
|
case kFeatureIconifyWindow:
|
||||||
if (enable)
|
if (enable)
|
||||||
SDL_WM_IconifyWindow();
|
SDL_WM_IconifyWindow();
|
||||||
@ -489,8 +477,6 @@ bool OSystem_SDL::getFeatureState(Feature f) {
|
|||||||
return _videoMode.fullscreen;
|
return _videoMode.fullscreen;
|
||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
return _videoMode.aspectRatioCorrection;
|
return _videoMode.aspectRatioCorrection;
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
return _modeFlags & DF_WANT_RECT_OPTIM;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -512,9 +498,6 @@ void OSystem_SDL::deinit() {
|
|||||||
SDL_RemoveTimer(_timerID);
|
SDL_RemoveTimer(_timerID);
|
||||||
closeMixer();
|
closeMixer();
|
||||||
|
|
||||||
free(_dirtyChecksums);
|
|
||||||
free(_currentPalette);
|
|
||||||
free(_cursorPalette);
|
|
||||||
free(_mouseData);
|
free(_mouseData);
|
||||||
|
|
||||||
delete _timer;
|
delete _timer;
|
||||||
|
@ -290,10 +290,6 @@ protected:
|
|||||||
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
|
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
|
||||||
uint32 _cdEndTime, _cdStopTime;
|
uint32 _cdEndTime, _cdStopTime;
|
||||||
|
|
||||||
enum {
|
|
||||||
DF_WANT_RECT_OPTIM = 1 << 0
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kTransactionNone = 0,
|
kTransactionNone = 0,
|
||||||
kTransactionActive = 1,
|
kTransactionActive = 1,
|
||||||
@ -342,7 +338,6 @@ protected:
|
|||||||
Graphics::Surface _framebuffer;
|
Graphics::Surface _framebuffer;
|
||||||
|
|
||||||
/** Current video mode flags (see DF_* constants) */
|
/** Current video mode flags (see DF_* constants) */
|
||||||
uint32 _modeFlags;
|
|
||||||
bool _modeChanged;
|
bool _modeChanged;
|
||||||
int _screenChangeCount;
|
int _screenChangeCount;
|
||||||
|
|
||||||
@ -354,9 +349,6 @@ protected:
|
|||||||
// Dirty rect management
|
// Dirty rect management
|
||||||
SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];
|
SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];
|
||||||
int _numDirtyRects;
|
int _numDirtyRects;
|
||||||
uint32 *_dirtyChecksums;
|
|
||||||
bool _cksumValid;
|
|
||||||
int _cksumNum;
|
|
||||||
|
|
||||||
// Keyboard mouse emulation. Disabled by fingolfin 2004-12-18.
|
// Keyboard mouse emulation. Disabled by fingolfin 2004-12-18.
|
||||||
// I am keeping the rest of the code in for now, since the joystick
|
// I am keeping the rest of the code in for now, since the joystick
|
||||||
@ -422,11 +414,11 @@ protected:
|
|||||||
int _newShakePos;
|
int _newShakePos;
|
||||||
|
|
||||||
// Palette data
|
// Palette data
|
||||||
SDL_Color *_currentPalette;
|
SDL_Color _currentPalette[256];
|
||||||
uint _paletteDirtyStart, _paletteDirtyEnd;
|
uint _paletteDirtyStart, _paletteDirtyEnd;
|
||||||
|
|
||||||
// Cursor palette data
|
// Cursor palette data
|
||||||
SDL_Color *_cursorPalette;
|
SDL_Color _cursorPalette[256];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutex which prevents multiple threads from interfering with each other
|
* Mutex which prevents multiple threads from interfering with each other
|
||||||
@ -459,9 +451,6 @@ protected:
|
|||||||
Common::TimerManager *_timer;
|
Common::TimerManager *_timer;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addDirtyRgnAuto(const byte *buf);
|
|
||||||
void makeChecksums(const byte *buf);
|
|
||||||
|
|
||||||
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); // overloaded by CE backend
|
virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); // overloaded by CE backend
|
||||||
|
|
||||||
virtual void drawMouse(); // overloaded by CE backend
|
virtual void drawMouse(); // overloaded by CE backend
|
||||||
|
@ -83,7 +83,6 @@ bool OSystem_SDL_Symbian::hasFeature(Feature f) {
|
|||||||
switch (f) {
|
switch (f) {
|
||||||
case kFeatureFullscreenMode:
|
case kFeatureFullscreenMode:
|
||||||
case kFeatureAspectRatioCorrection:
|
case kFeatureAspectRatioCorrection:
|
||||||
case kFeatureAutoComputeDirtyRects:
|
|
||||||
case kFeatureCursorHasPalette:
|
case kFeatureCursorHasPalette:
|
||||||
#ifdef USE_VIBRA_SE_PXXX
|
#ifdef USE_VIBRA_SE_PXXX
|
||||||
case kFeatureVibration:
|
case kFeatureVibration:
|
||||||
|
@ -926,7 +926,7 @@ const OSystem::GraphicsMode *OSystem_WINCE3::getSupportedGraphicsModes() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OSystem_WINCE3::hasFeature(Feature f) {
|
bool OSystem_WINCE3::hasFeature(Feature f) {
|
||||||
return (f == kFeatureAutoComputeDirtyRects || f == kFeatureVirtualKeyboard);
|
return (f == kFeatureVirtualKeyboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSystem_WINCE3::setFeatureState(Feature f, bool enable) {
|
void OSystem_WINCE3::setFeatureState(Feature f, bool enable) {
|
||||||
@ -1151,14 +1151,12 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 1;
|
_scaleFactorYm = 1;
|
||||||
_scaleFactorYd = 1;
|
_scaleFactorYd = 1;
|
||||||
_scalerProc = DownscaleHorizByThreeQuarters;
|
_scalerProc = DownscaleHorizByThreeQuarters;
|
||||||
_modeFlags = 0;
|
|
||||||
} else {
|
} else {
|
||||||
_scaleFactorXm = 1;
|
_scaleFactorXm = 1;
|
||||||
_scaleFactorXd = 1;
|
_scaleFactorXd = 1;
|
||||||
_scaleFactorYm = 1;
|
_scaleFactorYm = 1;
|
||||||
_scaleFactorYd = 1;
|
_scaleFactorYd = 1;
|
||||||
_scalerProc = Normal1x;
|
_scalerProc = Normal1x;
|
||||||
_modeFlags = 0;
|
|
||||||
}
|
}
|
||||||
} else if ( _orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
|
} else if ( _orientationLandscape && (_videoMode.screenWidth == 320 || !_videoMode.screenWidth)) {
|
||||||
if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) {
|
if (!_panelVisible && !_hasSmartphoneResolution && !_overlayVisible && _canBeAspectScaled) {
|
||||||
@ -1167,7 +1165,6 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 6;
|
_scaleFactorYm = 6;
|
||||||
_scaleFactorYd = 5;
|
_scaleFactorYd = 5;
|
||||||
_scalerProc = Normal1xAspect;
|
_scalerProc = Normal1xAspect;
|
||||||
_modeFlags = 0;
|
|
||||||
_videoMode.aspectRatioCorrection = true;
|
_videoMode.aspectRatioCorrection = true;
|
||||||
} else {
|
} else {
|
||||||
_scaleFactorXm = 1;
|
_scaleFactorXm = 1;
|
||||||
@ -1175,7 +1172,6 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 1;
|
_scaleFactorYm = 1;
|
||||||
_scaleFactorYd = 1;
|
_scaleFactorYd = 1;
|
||||||
_scalerProc = Normal1x;
|
_scalerProc = Normal1x;
|
||||||
_modeFlags = 0;
|
|
||||||
}
|
}
|
||||||
} else if (_videoMode.screenWidth == 640 && !(isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
|
} else if (_videoMode.screenWidth == 640 && !(isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
|
||||||
_scaleFactorXm = 1;
|
_scaleFactorXm = 1;
|
||||||
@ -1183,14 +1179,12 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 1;
|
_scaleFactorYm = 1;
|
||||||
_scaleFactorYd = 2;
|
_scaleFactorYd = 2;
|
||||||
_scalerProc = DownscaleAllByHalf;
|
_scalerProc = DownscaleAllByHalf;
|
||||||
_modeFlags = 0;
|
|
||||||
} else if (_videoMode.screenWidth == 640 && (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
|
} else if (_videoMode.screenWidth == 640 && (isOzone() && (getScreenWidth() >= 640 || getScreenHeight() >= 640))) {
|
||||||
_scaleFactorXm = 1;
|
_scaleFactorXm = 1;
|
||||||
_scaleFactorXd = 1;
|
_scaleFactorXd = 1;
|
||||||
_scaleFactorYm = 1;
|
_scaleFactorYm = 1;
|
||||||
_scaleFactorYd = 1;
|
_scaleFactorYd = 1;
|
||||||
_scalerProc = Normal1x;
|
_scalerProc = Normal1x;
|
||||||
_modeFlags = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1203,7 +1197,6 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 12;
|
_scaleFactorYm = 12;
|
||||||
_scaleFactorYd = 5;
|
_scaleFactorYd = 5;
|
||||||
_scalerProc = Normal2xAspect;
|
_scalerProc = Normal2xAspect;
|
||||||
_modeFlags = 0;
|
|
||||||
_videoMode.aspectRatioCorrection = true;
|
_videoMode.aspectRatioCorrection = true;
|
||||||
} else if ( (_panelVisible || _overlayVisible) && _canBeAspectScaled ) {
|
} else if ( (_panelVisible || _overlayVisible) && _canBeAspectScaled ) {
|
||||||
_scaleFactorXm = 2;
|
_scaleFactorXm = 2;
|
||||||
@ -1211,7 +1204,6 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 2;
|
_scaleFactorYm = 2;
|
||||||
_scaleFactorYd = 1;
|
_scaleFactorYd = 1;
|
||||||
_scalerProc = Normal2x;
|
_scalerProc = Normal2x;
|
||||||
_modeFlags = 0;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1232,7 +1224,6 @@ bool OSystem_WINCE3::update_scalers() {
|
|||||||
_scaleFactorYm = 7;
|
_scaleFactorYm = 7;
|
||||||
_scaleFactorYd = 8;
|
_scaleFactorYd = 8;
|
||||||
_scalerProc = SmartphoneLandscape;
|
_scalerProc = SmartphoneLandscape;
|
||||||
_modeFlags = 0;
|
|
||||||
initZones();
|
initZones();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1824,7 +1815,6 @@ void OSystem_WINCE3::copyRectToOverlay(const OverlayColor *buf, int pitch, int x
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Mark the modified region as dirty
|
// Mark the modified region as dirty
|
||||||
_cksumValid = false;
|
|
||||||
addDirtyRect(x, y, w, h);
|
addDirtyRect(x, y, w, h);
|
||||||
|
|
||||||
undrawMouse();
|
undrawMouse();
|
||||||
@ -1851,41 +1841,32 @@ void OSystem_WINCE3::copyRectToScreen(const byte *src, int pitch, int x, int y,
|
|||||||
|
|
||||||
Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
|
Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
|
||||||
|
|
||||||
if (((long)src & 3) == 0 && pitch == _videoMode.screenWidth && x == 0 && y == 0 &&
|
/* Clip the coordinates */
|
||||||
w == _videoMode.screenWidth && h == _videoMode.screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
|
if (x < 0) {
|
||||||
/* Special, optimized case for full screen updates.
|
w += x;
|
||||||
* It tries to determine what areas were actually changed,
|
src -= x;
|
||||||
* and just updates those, on the actual display. */
|
x = 0;
|
||||||
addDirtyRgnAuto(src);
|
|
||||||
} else {
|
|
||||||
/* Clip the coordinates */
|
|
||||||
if (x < 0) {
|
|
||||||
w += x;
|
|
||||||
src -= x;
|
|
||||||
x = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y < 0) {
|
|
||||||
h += y;
|
|
||||||
src -= y * pitch;
|
|
||||||
y = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w > _videoMode.screenWidth - x) {
|
|
||||||
w = _videoMode.screenWidth - x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h > _videoMode.screenHeight - y) {
|
|
||||||
h = _videoMode.screenHeight - y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_cksumValid = false;
|
|
||||||
addDirtyRect(x, y, w, h);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (y < 0) {
|
||||||
|
h += y;
|
||||||
|
src -= y * pitch;
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w > _videoMode.screenWidth - x) {
|
||||||
|
w = _videoMode.screenWidth - x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h > _videoMode.screenHeight - y) {
|
||||||
|
h = _videoMode.screenHeight - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w <= 0 || h <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
addDirtyRect(x, y, w, h);
|
||||||
|
|
||||||
undrawMouse();
|
undrawMouse();
|
||||||
|
|
||||||
// Try to lock the screen surface
|
// Try to lock the screen surface
|
||||||
|
83
backends/timer/psp/timer.cpp
Normal file
83
backends/timer/psp/timer.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* 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 $
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (__PSP__)
|
||||||
|
#include <pspthreadman.h>
|
||||||
|
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
#include "common/timer.h"
|
||||||
|
#include "backends/platform/psp/thread.h"
|
||||||
|
#include "backends/timer/psp/timer.h"
|
||||||
|
|
||||||
|
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
|
||||||
|
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
|
||||||
|
|
||||||
|
#include "backends/platform/psp/trace.h"
|
||||||
|
|
||||||
|
bool PspTimer::start() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
if (!_interval || !_callback)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_threadId = sceKernelCreateThread("timerThread", thread, PRIORITY_TIMER_THREAD, STACK_TIMER_THREAD, THREAD_ATTR_USER, 0);
|
||||||
|
|
||||||
|
if (_threadId < 0) { // error
|
||||||
|
PSP_ERROR("failed to create timer thread. Error code %d\n", _threadId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PspTimer *_this = this; // trick to get into context when the thread starts
|
||||||
|
_init = true;
|
||||||
|
|
||||||
|
if (sceKernelStartThread(_threadId, sizeof(uint32 *), &_this) < 0) {
|
||||||
|
PSP_ERROR("failed to start thread %d\n", _threadId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PSP_DEBUG_PRINT("created timer thread[%x]\n", _threadId);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PspTimer::thread(SceSize, void *__this) {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
PspTimer *_this = *(PspTimer **)__this; // get our this for the context
|
||||||
|
|
||||||
|
_this->timerThread();
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void PspTimer::timerThread() {
|
||||||
|
DEBUG_ENTER_FUNC();
|
||||||
|
|
||||||
|
while (_init) {
|
||||||
|
sceKernelDelayThread(_interval);
|
||||||
|
PSP_DEBUG_PRINT("calling callback!\n");
|
||||||
|
_callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __PSP__ */
|
47
backends/timer/psp/timer.h
Normal file
47
backends/timer/psp/timer.h
Normal file
@ -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: 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_TIMER_H
|
||||||
|
#define PSP_TIMER_H
|
||||||
|
|
||||||
|
class PspTimer {
|
||||||
|
public:
|
||||||
|
typedef void (* CallbackFunc)(void);
|
||||||
|
PspTimer() : _callback(0), _interval(0), _threadId(-1), _init(false) {}
|
||||||
|
void stop() { _init = false; }
|
||||||
|
bool start();
|
||||||
|
~PspTimer() { stop(); }
|
||||||
|
void setCallback(CallbackFunc cb) { _callback = cb; }
|
||||||
|
void setIntervalMs(uint32 interval) { _interval = interval * 1000; }
|
||||||
|
static int thread(SceSize, void *__this); // static thread to use as bridge
|
||||||
|
void timerThread();
|
||||||
|
private:
|
||||||
|
CallbackFunc _callback; // pointer to timer callback
|
||||||
|
uint32 _interval;
|
||||||
|
int _threadId;
|
||||||
|
bool _init;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -51,7 +51,7 @@ static const char USAGE_STRING[] =
|
|||||||
;
|
;
|
||||||
|
|
||||||
// DONT FIXME: DO NOT ORDER ALPHABETICALLY, THIS IS ORDERED BY IMPORTANCE/CATEGORY! :)
|
// DONT FIXME: DO NOT ORDER ALPHABETICALLY, THIS IS ORDERED BY IMPORTANCE/CATEGORY! :)
|
||||||
#if defined(PALMOS_MODE) || defined(__SYMBIAN32__) || defined(__GP32__)
|
#if defined(PALMOS_MODE) || defined(__SYMBIAN32__) || defined(__GP32__) || defined(ANDROID)
|
||||||
static const char HELP_STRING[] = "NoUsageString"; // save more data segment space
|
static const char HELP_STRING[] = "NoUsageString"; // save more data segment space
|
||||||
#else
|
#else
|
||||||
static const char HELP_STRING[] =
|
static const char HELP_STRING[] =
|
||||||
@ -948,7 +948,7 @@ Common::Error processSettings(Common::String &command, Common::StringMap &settin
|
|||||||
// environment variable. This is weaker than a --savepath on the
|
// environment variable. This is weaker than a --savepath on the
|
||||||
// command line, but overrides the default savepath, hence it is
|
// command line, but overrides the default savepath, hence it is
|
||||||
// handled here, just before the command line gets parsed.
|
// handled here, just before the command line gets parsed.
|
||||||
#if !defined(MACOS_CARBON) && !defined(_WIN32_WCE) && !defined(PALMOS_MODE) && !defined(__GP32__)
|
#if !defined(MACOS_CARBON) && !defined(_WIN32_WCE) && !defined(PALMOS_MODE) && !defined(__GP32__) && !defined(ANDROID)
|
||||||
if (!settings.contains("savepath")) {
|
if (!settings.contains("savepath")) {
|
||||||
const char *dir = getenv("SCUMMVM_SAVEPATH");
|
const char *dir = getenv("SCUMMVM_SAVEPATH");
|
||||||
if (dir && *dir && strlen(dir) < MAXPATHLEN) {
|
if (dir && *dir && strlen(dir) < MAXPATHLEN) {
|
||||||
|
@ -439,6 +439,11 @@ Common::SeekableReadStream *MacResManager::getResource(uint32 typeID, uint16 res
|
|||||||
|
|
||||||
_stream->seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
|
_stream->seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
|
||||||
uint32 len = _stream->readUint32BE();
|
uint32 len = _stream->readUint32BE();
|
||||||
|
|
||||||
|
// Ignore resources with 0 length
|
||||||
|
if (!len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return _stream->readStream(len);
|
return _stream->readStream(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -448,6 +453,11 @@ Common::SeekableReadStream *MacResManager::getResource(const Common::String &fil
|
|||||||
if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) {
|
if (_resLists[i][j].nameOffset != -1 && filename.equalsIgnoreCase(_resLists[i][j].name)) {
|
||||||
_stream->seek(_dataOffset + _resLists[i][j].dataOffset);
|
_stream->seek(_dataOffset + _resLists[i][j].dataOffset);
|
||||||
uint32 len = _stream->readUint32BE();
|
uint32 len = _stream->readUint32BE();
|
||||||
|
|
||||||
|
// Ignore resources with 0 length
|
||||||
|
if (!len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return _stream->readStream(len);
|
return _stream->readStream(len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,6 +222,12 @@ public:
|
|||||||
typedef const char * const_iterator;
|
typedef const char * const_iterator;
|
||||||
|
|
||||||
iterator begin() {
|
iterator begin() {
|
||||||
|
// Since the user could potentially
|
||||||
|
// change the string via the returned
|
||||||
|
// iterator we have to assure we are
|
||||||
|
// pointing to a unique storage.
|
||||||
|
makeUnique();
|
||||||
|
|
||||||
return _str;
|
return _str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ public:
|
|||||||
class ReadStream : virtual public Stream {
|
class ReadStream : virtual public Stream {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Returns true if a read failed because the stream has been reached.
|
* Returns true if a read failed because the stream end has been reached.
|
||||||
* This flag is cleared by clearErr().
|
* This flag is cleared by clearErr().
|
||||||
* For a SeekableReadStream, it is also cleared by a successful seek.
|
* For a SeekableReadStream, it is also cleared by a successful seek.
|
||||||
*/
|
*/
|
||||||
|
@ -150,18 +150,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
kFeatureVirtualKeyboard,
|
kFeatureVirtualKeyboard,
|
||||||
|
|
||||||
/**
|
|
||||||
* This flag is a bit more obscure: it gives a hint to the backend that
|
|
||||||
* the frontend code is very inefficient in doing screen updates. So
|
|
||||||
* the frontend might do a lot of fullscreen blits even though only a
|
|
||||||
* tiny portion of the actual screen data changed. In that case, it
|
|
||||||
* might pay off for the backend to compute which parts actually changed,
|
|
||||||
* and then only mark those as dirty.
|
|
||||||
* Implementing this is purely optional, and no harm should arise
|
|
||||||
* when not doing so (except for decreased speed in said frontends).
|
|
||||||
*/
|
|
||||||
kFeatureAutoComputeDirtyRects,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This flag determines whether or not the cursor can have its own palette.
|
* This flag determines whether or not the cursor can have its own palette.
|
||||||
* It is currently used only by some Macintosh versions of Humongous
|
* It is currently used only by some Macintosh versions of Humongous
|
||||||
|
@ -43,6 +43,10 @@ extern bool isSmartphone();
|
|||||||
#define fputs(str, file) DS::std_fwrite(str, strlen(str), 1, file)
|
#define fputs(str, file) DS::std_fwrite(str, strlen(str), 1, file)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include <android/log.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
static OutputFormatter s_errorOutputFormatter = 0;
|
static OutputFormatter s_errorOutputFormatter = 0;
|
||||||
@ -71,7 +75,9 @@ void warning(const char *s, ...) {
|
|||||||
vsnprintf(buf, STRINGBUFLEN, s, va);
|
vsnprintf(buf, STRINGBUFLEN, s, va);
|
||||||
va_end(va);
|
va_end(va);
|
||||||
|
|
||||||
#if !defined (__SYMBIAN32__)
|
#if defined( ANDROID )
|
||||||
|
__android_log_write(ANDROID_LOG_WARN, "ScummVM", buf);
|
||||||
|
#elif !defined (__SYMBIAN32__)
|
||||||
fputs("WARNING: ", stderr);
|
fputs("WARNING: ", stderr);
|
||||||
fputs(buf, stderr);
|
fputs(buf, stderr);
|
||||||
fputs("!\n", stderr);
|
fputs("!\n", stderr);
|
||||||
@ -141,6 +147,10 @@ void NORETURN_PRE error(const char *s, ...) {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
__android_log_assert("Fatal error", "ScummVM", "%s", buf_output);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PALMOS_MODE
|
#ifdef PALMOS_MODE
|
||||||
extern void PalmFatalError(const char *err);
|
extern void PalmFatalError(const char *err);
|
||||||
PalmFatalError(buf_output);
|
PalmFatalError(buf_output);
|
||||||
|
@ -1433,11 +1433,11 @@ Common::SeekableReadStream *ZipArchive::createReadStreamForMember(const Common::
|
|||||||
unz_file_info fileInfo;
|
unz_file_info fileInfo;
|
||||||
unzOpenCurrentFile(_zipFile);
|
unzOpenCurrentFile(_zipFile);
|
||||||
unzGetCurrentFileInfo(_zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
|
unzGetCurrentFileInfo(_zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
|
||||||
byte *buffer = (byte *)calloc(fileInfo.uncompressed_size+1, 1);
|
byte *buffer = (byte *)malloc(fileInfo.uncompressed_size);
|
||||||
assert(buffer);
|
assert(buffer);
|
||||||
unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size);
|
unzReadCurrentFile(_zipFile, buffer, fileInfo.uncompressed_size);
|
||||||
unzCloseCurrentFile(_zipFile);
|
unzCloseCurrentFile(_zipFile);
|
||||||
return new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size+1, DisposeAfterUse::YES);
|
return new Common::MemoryReadStream(buffer, fileInfo.uncompressed_size, DisposeAfterUse::YES);
|
||||||
|
|
||||||
// FIXME: instead of reading all into a memory stream, we could
|
// FIXME: instead of reading all into a memory stream, we could
|
||||||
// instead create a new ZipStream class. But then we have to be
|
// instead create a new ZipStream class. But then we have to be
|
||||||
|
47
configure
vendored
47
configure
vendored
@ -1000,6 +1000,11 @@ wince)
|
|||||||
_host_cpu=arm
|
_host_cpu=arm
|
||||||
_host_alias=arm-wince-mingw32ce
|
_host_alias=arm-wince-mingw32ce
|
||||||
;;
|
;;
|
||||||
|
android)
|
||||||
|
_host_os=android
|
||||||
|
_host_cpu=arm
|
||||||
|
_host_alias=arm-android-eabi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if test -n "$_host"; then
|
if test -n "$_host"; then
|
||||||
guessed_host=`$_srcdir/config.sub $_host`
|
guessed_host=`$_srcdir/config.sub $_host`
|
||||||
@ -1078,6 +1083,12 @@ psp)
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
android)
|
||||||
|
if test -z "$ANDROID_SDK"; then
|
||||||
|
echo "Please set ANDROID_SDK in your environment. export ANDROID_SDK=<path to Android SDK>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@ -1400,6 +1411,11 @@ case $_host_os in
|
|||||||
DEFINES="$DEFINES -D_WIN32_WCE=300 -D__ARM__ -D_ARM_ -DUNICODE -DFPM_DEFAULT -DNONSTANDARD_PORT"
|
DEFINES="$DEFINES -D_WIN32_WCE=300 -D__ARM__ -D_ARM_ -DUNICODE -DFPM_DEFAULT -DNONSTANDARD_PORT"
|
||||||
DEFINES="$DEFINES -DWIN32 -Dcdecl= -D__cdecl__="
|
DEFINES="$DEFINES -DWIN32 -Dcdecl= -D__cdecl__="
|
||||||
;;
|
;;
|
||||||
|
android)
|
||||||
|
DEFINES="$DEFINES -DUNIX"
|
||||||
|
CXXFLAGS="$CXXFLAGS -Os -msoft-float -mtune=xscale -march=armv5te -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5TE__"
|
||||||
|
add_line_to_config_mk "ANDROID_SDK = $ANDROID_SDK"
|
||||||
|
;;
|
||||||
# given this is a shell script assume some type of unix
|
# given this is a shell script assume some type of unix
|
||||||
*)
|
*)
|
||||||
echo "WARNING: could not establish system type, assuming unix like"
|
echo "WARNING: could not establish system type, assuming unix like"
|
||||||
@ -1507,6 +1523,10 @@ if test -n "$_host"; then
|
|||||||
_ar="$_host-ar cru"
|
_ar="$_host-ar cru"
|
||||||
_ranlib=$_host-ranlib
|
_ranlib=$_host-ranlib
|
||||||
;;
|
;;
|
||||||
|
mips-sgi*)
|
||||||
|
_endian=big
|
||||||
|
_need_memalign=yes
|
||||||
|
;;
|
||||||
motoezx)
|
motoezx)
|
||||||
DEFINES="$DEFINES -DUNIX -DMOTOEZX"
|
DEFINES="$DEFINES -DUNIX -DMOTOEZX"
|
||||||
ASFLAGS="$ASFLAGS -mfpu=vfp"
|
ASFLAGS="$ASFLAGS -mfpu=vfp"
|
||||||
@ -1644,6 +1664,19 @@ if test -n "$_host"; then
|
|||||||
_mt32emu="no"
|
_mt32emu="no"
|
||||||
_port_mk="backends/platform/wince/wince.mk"
|
_port_mk="backends/platform/wince/wince.mk"
|
||||||
;;
|
;;
|
||||||
|
android)
|
||||||
|
DEFINES="$DEFINES -DANDROID -DUNIX -DUSE_ARM_SMUSH_ASM"
|
||||||
|
_endian=little
|
||||||
|
_need_memalign=yes
|
||||||
|
add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_GFX_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1'
|
||||||
|
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
|
||||||
|
_backend="android"
|
||||||
|
_port_mk="backends/platform/android/android.mk"
|
||||||
|
_build_hq_scalers="no"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "WARNING: Unknown target, continuing with auto-detected values"
|
echo "WARNING: Unknown target, continuing with auto-detected values"
|
||||||
;;
|
;;
|
||||||
@ -1822,7 +1855,7 @@ POST_OBJS_FLAGS := -Wl,-no-whole-archive
|
|||||||
LIBS += -ldl
|
LIBS += -ldl
|
||||||
'
|
'
|
||||||
;;
|
;;
|
||||||
linux*)
|
linux*|android)
|
||||||
_def_plugin='
|
_def_plugin='
|
||||||
#define PLUGIN_PREFIX "lib"
|
#define PLUGIN_PREFIX "lib"
|
||||||
#define PLUGIN_SUFFIX ".so"
|
#define PLUGIN_SUFFIX ".so"
|
||||||
@ -2429,6 +2462,14 @@ case $_backend in
|
|||||||
INCLUDES="$INCLUDES "'-I$(srcdir) -I$(srcdir)/backends/platform/wince -I$(srcdir)/engines -I$(srcdir)/backends/platform/wince/missing/gcc -I$(srcdir)/backends/platform/wince/CEgui -I$(srcdir)/backends/platform/wince/CEkeys'
|
INCLUDES="$INCLUDES "'-I$(srcdir) -I$(srcdir)/backends/platform/wince -I$(srcdir)/engines -I$(srcdir)/backends/platform/wince/missing/gcc -I$(srcdir)/backends/platform/wince/CEgui -I$(srcdir)/backends/platform/wince/CEkeys'
|
||||||
LIBS="$LIBS -static -lSDL"
|
LIBS="$LIBS -static -lSDL"
|
||||||
;;
|
;;
|
||||||
|
android)
|
||||||
|
# -lgcc is carefully placed here - we want to catch
|
||||||
|
# all toolchain symbols in *our* libraries rather
|
||||||
|
# than pick up anything unhygenic from the Android libs.
|
||||||
|
LIBS="$LIBS -lgcc -lstdc++ -llog -lGLESv1_CM -lEGL"
|
||||||
|
DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE"
|
||||||
|
add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic'
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "support for $_backend backend not implemented in configure script yet"
|
echo "support for $_backend backend not implemented in configure script yet"
|
||||||
exit 1
|
exit 1
|
||||||
@ -2444,7 +2485,7 @@ if test "$have_gcc" = yes ; then
|
|||||||
case $_host_os in
|
case $_host_os in
|
||||||
# newlib-based system include files suppress non-C89 function
|
# newlib-based system include files suppress non-C89 function
|
||||||
# declarations under __STRICT_ANSI__
|
# declarations under __STRICT_ANSI__
|
||||||
mingw* | dreamcast | wii | gamecube | psp | wince | amigaos*)
|
mingw* | dreamcast | wii | gamecube | psp | wince | amigaos* | android)
|
||||||
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
|
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@ -2465,7 +2506,7 @@ fi;
|
|||||||
|
|
||||||
# Some platforms use certain GNU extensions in header files
|
# Some platforms use certain GNU extensions in header files
|
||||||
case $_host_os in
|
case $_host_os in
|
||||||
gamecube | psp | wii)
|
gamecube | psp | wii | android)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
CXXFLAGS="$CXXFLAGS -pedantic"
|
CXXFLAGS="$CXXFLAGS -pedantic"
|
||||||
|
169
dists/android/mkmanifest.pl
Normal file
169
dists/android/mkmanifest.pl
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
#!/usr/bin/perl
|
||||||
|
|
||||||
|
use File::Basename qw(dirname);
|
||||||
|
use File::Path qw(mkpath);
|
||||||
|
use IO::File;
|
||||||
|
use XML::Writer;
|
||||||
|
use XML::Parser;
|
||||||
|
use Getopt::Long;
|
||||||
|
|
||||||
|
use warnings;
|
||||||
|
use strict;
|
||||||
|
|
||||||
|
use constant ANDROID => 'http://schemas.android.com/apk/res/android';
|
||||||
|
|
||||||
|
my $id;
|
||||||
|
my $package_versionName;
|
||||||
|
my $package_versionCode;
|
||||||
|
my $configure = 'configure';
|
||||||
|
my $stringres = 'res/string/values.xml';
|
||||||
|
my $manifest = 'AndroidManifest.xml';
|
||||||
|
my $master_manifest;
|
||||||
|
my @unpack_libs;
|
||||||
|
GetOptions('id=s' => \$id,
|
||||||
|
'version-name=s' => \$package_versionName,
|
||||||
|
'version-code=i' => \$package_versionCode,
|
||||||
|
'configure=s' => \$configure,
|
||||||
|
'stringres=s' => \$stringres,
|
||||||
|
'manifest=s' => \$manifest,
|
||||||
|
'master-manifest=s' => \$master_manifest,
|
||||||
|
'unpacklib=s' => \@unpack_libs,
|
||||||
|
) or die;
|
||||||
|
die "Missing required arg"
|
||||||
|
unless $id and $package_versionName and $package_versionCode;
|
||||||
|
|
||||||
|
|
||||||
|
sub grope_engine_info {
|
||||||
|
my $configure = shift;
|
||||||
|
my @ret;
|
||||||
|
while (<$configure>) {
|
||||||
|
m/^add_engine \s+ (\w+) \s+ "(.*?)" \s+ \w+ (?:\s+ "([\w\s]*)")?/x
|
||||||
|
or next;
|
||||||
|
my $subengines = $3 || '';
|
||||||
|
my %info = (id => $1, name => $2,
|
||||||
|
subengines => [split / /, $subengines]);
|
||||||
|
push @ret, \%info;
|
||||||
|
}
|
||||||
|
return @ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub read_constraints {
|
||||||
|
my $manifest = shift;
|
||||||
|
my @constraints;
|
||||||
|
my $parser = new XML::Parser Handlers => {
|
||||||
|
Start => sub {
|
||||||
|
my $expat = shift;
|
||||||
|
my $elem = shift;
|
||||||
|
return if $elem !~
|
||||||
|
/^(uses-configuration|supports-screens|uses-sdk)$/;
|
||||||
|
my @constraint = ($elem);
|
||||||
|
while (@_) {
|
||||||
|
my $attr = shift;
|
||||||
|
my $value = shift;
|
||||||
|
$attr = [ANDROID, $attr] if $attr =~ s/^android://;
|
||||||
|
push @constraint, $attr, $value;
|
||||||
|
}
|
||||||
|
push @constraints, \@constraint;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
$parser->parse($manifest);
|
||||||
|
return @constraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub print_stringres {
|
||||||
|
my $output = shift;
|
||||||
|
my $info = shift;
|
||||||
|
|
||||||
|
my $writer = new XML::Writer(OUTPUT => $output, ENCODING => 'utf-8',
|
||||||
|
DATA_MODE => 1, DATA_INDENT => 2);
|
||||||
|
|
||||||
|
$writer->xmlDecl();
|
||||||
|
$writer->startTag('resources');
|
||||||
|
|
||||||
|
while (my ($k,$v) = each %$info) {
|
||||||
|
$writer->dataElement('string', $v, name => $k);
|
||||||
|
}
|
||||||
|
|
||||||
|
$writer->endTag('resources');
|
||||||
|
$writer->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
sub print_manifest {
|
||||||
|
my $output = shift;
|
||||||
|
my $info = shift;
|
||||||
|
my $constraints = shift;
|
||||||
|
|
||||||
|
my $writer = new XML::Writer(OUTPUT => $output, ENCODING => 'utf-8',
|
||||||
|
DATA_MODE => 1, DATA_INDENT => 2,
|
||||||
|
NAMESPACES => 1,
|
||||||
|
PREFIX_MAP => {ANDROID, 'android'});
|
||||||
|
|
||||||
|
$writer->xmlDecl();
|
||||||
|
|
||||||
|
$writer->startTag(
|
||||||
|
'manifest',
|
||||||
|
'package' => "org.inodes.gus.scummvm.plugin.$info->{name}",
|
||||||
|
[ANDROID, 'versionCode'] => $package_versionCode,
|
||||||
|
[ANDROID, 'versionName'] => $package_versionName,
|
||||||
|
);
|
||||||
|
|
||||||
|
$writer->startTag(
|
||||||
|
'application',
|
||||||
|
[ANDROID, 'label'] => '@string/app_name',
|
||||||
|
[ANDROID, 'description'] => '@string/app_desc',
|
||||||
|
[ANDROID, 'icon'] => '@drawable/scummvm',
|
||||||
|
);
|
||||||
|
|
||||||
|
$writer->startTag(
|
||||||
|
'receiver',
|
||||||
|
[ANDROID, 'name'] => 'org.inodes.gus.scummvm.PluginProvider',
|
||||||
|
[ANDROID, 'process'] => 'org.inodes.gus.scummvm');
|
||||||
|
|
||||||
|
$writer->startTag('intent-filter');
|
||||||
|
$writer->emptyTag('action', [ANDROID, 'name'] =>
|
||||||
|
'org.inodes.gus.scummvm.action.PLUGIN_QUERY');
|
||||||
|
$writer->emptyTag('category', [ANDROID, 'name'] =>
|
||||||
|
'android.intent.category.INFO');
|
||||||
|
$writer->endTag('intent-filter');
|
||||||
|
$writer->emptyTag(
|
||||||
|
'meta-data',
|
||||||
|
[ANDROID, 'name'] => 'org.inodes.gus.scummvm.meta.UNPACK_LIB',
|
||||||
|
[ANDROID, 'value'] => $_)
|
||||||
|
for @{$info->{unpack_libs}};
|
||||||
|
|
||||||
|
$writer->endTag('receiver');
|
||||||
|
$writer->endTag('application');
|
||||||
|
|
||||||
|
$writer->emptyTag('uses-permission', [ANDROID, 'name'] =>
|
||||||
|
'org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN');
|
||||||
|
|
||||||
|
$writer->emptyTag(@$_) foreach @$constraints;
|
||||||
|
|
||||||
|
$writer->endTag('manifest');
|
||||||
|
$writer->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
my %engines;
|
||||||
|
for my $engine (grope_engine_info(new IO::File $configure, 'r')) {
|
||||||
|
$engines{$engine->{id}} = $engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @games = ($id, @{$engines{$id}{subengines}});
|
||||||
|
my $games_desc = join('; ', map $engines{$_}{name}, @games);
|
||||||
|
|
||||||
|
my @constraints = read_constraints(new IO::File $master_manifest, 'r');
|
||||||
|
|
||||||
|
print "Writing $stringres ...\n";
|
||||||
|
mkpath(dirname($stringres));
|
||||||
|
print_stringres(IO::File->new($stringres, 'w'),
|
||||||
|
{app_name => qq{ScummVM plugin: "$id"},
|
||||||
|
app_desc => "Game engine for: $games_desc",
|
||||||
|
});
|
||||||
|
|
||||||
|
print "Writing $manifest ...\n";
|
||||||
|
mkpath(dirname($manifest));
|
||||||
|
print_manifest(IO::File->new($manifest, 'w'),
|
||||||
|
{name => $id, unpack_libs => \@unpack_libs}, \@constraints);
|
||||||
|
|
||||||
|
exit 0;
|
7
dists/android/res/drawable/gradient.xml
Normal file
7
dists/android/res/drawable/gradient.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<gradient
|
||||||
|
android:startColor="#e9bb8b"
|
||||||
|
android:endColor="#d16e09"
|
||||||
|
android:angle="315" />
|
||||||
|
</shape>
|
10
dists/android/res/layout/main.xml
Normal file
10
dists/android/res/layout/main.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.inodes.gus.scummvm.EditableSurfaceView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="fill_parent" android:layout_height="fill_parent"
|
||||||
|
android:id="@+id/main_surface"
|
||||||
|
android:gravity="center"
|
||||||
|
android:keepScreenOn="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"
|
||||||
|
/>
|
19
dists/android/res/layout/splash.xml
Normal file
19
dists/android/res/layout/splash.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center"
|
||||||
|
android:background="@drawable/gradient"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent">
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="fitCenter"
|
||||||
|
android:src="@drawable/scummvm_big" />
|
||||||
|
<ProgressBar android:id="@+id/progress"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="300dip"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="20dip"/>
|
||||||
|
</LinearLayout>
|
22
dists/android/res/values/strings.xml
Normal file
22
dists/android/res/values/strings.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">ScummVM</string>
|
||||||
|
<string name="app_desc">Graphic adventure game engine</string>
|
||||||
|
<string name="quit">Quit</string>
|
||||||
|
<string name="scummvm_perm_plugin_label">ScummVM plugin</string>
|
||||||
|
<string name="scummvm_perm_plugin_desc">Allows the application to
|
||||||
|
provide a ScummVM loadable plugin: code that will be executed in the
|
||||||
|
ScummVM application. Malicious plugins may do anything ScummVM
|
||||||
|
itself could do: write to your SD card, delete your savegames,
|
||||||
|
change the ScummVM background to puce, replace menu labels with rude
|
||||||
|
words, etc.</string>
|
||||||
|
<string name="no_sdcard_title">No SD card?</string>
|
||||||
|
<string name="no_sdcard">Unable to read your SD card. This usually
|
||||||
|
means you still have it mounted on your PC. Unmount, reinsert,
|
||||||
|
whatever and then try again.</string>
|
||||||
|
<string name="no_plugins_title">No plugins found</string>
|
||||||
|
<string name="no_plugins_found">ScummVM requires at least one <i>game
|
||||||
|
engine</i> to be useful. Engines are available as separate plugin
|
||||||
|
packages, from wherever you found ScummVM.</string>
|
||||||
|
<string name="to_market">To Market</string>
|
||||||
|
</resources>
|
@ -735,7 +735,6 @@
|
|||||||
DF09418A0F63CB26002D821E /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; };
|
DF09418A0F63CB26002D821E /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; };
|
||||||
DF09418B0F63CB26002D821E /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; };
|
DF09418B0F63CB26002D821E /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; };
|
||||||
DF09418C0F63CB26002D821E /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; };
|
DF09418C0F63CB26002D821E /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; };
|
||||||
DF0941910F63CB26002D821E /* video_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA70F485D950006E566 /* video_player.cpp */; };
|
|
||||||
DF0941920F63CB26002D821E /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; };
|
DF0941920F63CB26002D821E /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; };
|
||||||
DF0941930F63CB26002D821E /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; };
|
DF0941930F63CB26002D821E /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; };
|
||||||
DF0941940F63CB26002D821E /* posix-saves.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBF80F4860A60006E566 /* posix-saves.cpp */; };
|
DF0941940F63CB26002D821E /* posix-saves.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBF80F4860A60006E566 /* posix-saves.cpp */; };
|
||||||
@ -875,7 +874,6 @@
|
|||||||
DF2EC51910E64EE600765801 /* wave6581.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2EC51710E64EE600765801 /* wave6581.cpp */; };
|
DF2EC51910E64EE600765801 /* wave6581.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2EC51710E64EE600765801 /* wave6581.cpp */; };
|
||||||
DF2EC51A10E64EE600765801 /* wave6581.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2EC51710E64EE600765801 /* wave6581.cpp */; };
|
DF2EC51A10E64EE600765801 /* wave6581.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2EC51710E64EE600765801 /* wave6581.cpp */; };
|
||||||
DF2FFB930F485D890006E566 /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; };
|
DF2FFB930F485D890006E566 /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; };
|
||||||
DF2FFBB70F485D950006E566 /* video_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA70F485D950006E566 /* video_player.cpp */; };
|
|
||||||
DF2FFBD30F485DFB0006E566 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; };
|
DF2FFBD30F485DFB0006E566 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; };
|
||||||
DF2FFBD90F485E360006E566 /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; };
|
DF2FFBD90F485E360006E566 /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; };
|
||||||
DF2FFBFC0F4860A60006E566 /* posix-saves.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBF80F4860A60006E566 /* posix-saves.cpp */; };
|
DF2FFBFC0F4860A60006E566 /* posix-saves.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBF80F4860A60006E566 /* posix-saves.cpp */; };
|
||||||
@ -1915,6 +1913,33 @@
|
|||||||
DFAAAFFC0F0112DF003E9390 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; };
|
DFAAAFFC0F0112DF003E9390 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; };
|
||||||
DFAAB0020F011392003E9390 /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; };
|
DFAAB0020F011392003E9390 /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; };
|
||||||
DFAAD23D0F50120E00C3A4E2 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAD2390F50120E00C3A4E2 /* console.cpp */; };
|
DFAAD23D0F50120E00C3A4E2 /* console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAD2390F50120E00C3A4E2 /* console.cpp */; };
|
||||||
|
DFB0576811B753AF0015AE65 /* mpeg_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576211B753AF0015AE65 /* mpeg_player.cpp */; };
|
||||||
|
DFB0576911B753AF0015AE65 /* qt_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576411B753AF0015AE65 /* qt_decoder.cpp */; };
|
||||||
|
DFB0576A11B753AF0015AE65 /* video_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576611B753AF0015AE65 /* video_decoder.cpp */; };
|
||||||
|
DFB0576B11B753AF0015AE65 /* mpeg_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576211B753AF0015AE65 /* mpeg_player.cpp */; };
|
||||||
|
DFB0576C11B753AF0015AE65 /* qt_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576411B753AF0015AE65 /* qt_decoder.cpp */; };
|
||||||
|
DFB0576D11B753AF0015AE65 /* video_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576611B753AF0015AE65 /* video_decoder.cpp */; };
|
||||||
|
DFB0576E11B753AF0015AE65 /* mpeg_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576211B753AF0015AE65 /* mpeg_player.cpp */; };
|
||||||
|
DFB0576F11B753AF0015AE65 /* qt_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576411B753AF0015AE65 /* qt_decoder.cpp */; };
|
||||||
|
DFB0577011B753AF0015AE65 /* video_decoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0576611B753AF0015AE65 /* video_decoder.cpp */; };
|
||||||
|
DFB0577611B753DA0015AE65 /* rational.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577411B753DA0015AE65 /* rational.cpp */; };
|
||||||
|
DFB0577711B753DA0015AE65 /* rational.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577411B753DA0015AE65 /* rational.cpp */; };
|
||||||
|
DFB0577811B753DA0015AE65 /* rational.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577411B753DA0015AE65 /* rational.cpp */; };
|
||||||
|
DFB0578011B7541F0015AE65 /* resource_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577D11B7541F0015AE65 /* resource_audio.cpp */; };
|
||||||
|
DFB0578111B7541F0015AE65 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577E11B7541F0015AE65 /* util.cpp */; };
|
||||||
|
DFB0578211B7541F0015AE65 /* resource_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577D11B7541F0015AE65 /* resource_audio.cpp */; };
|
||||||
|
DFB0578311B7541F0015AE65 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577E11B7541F0015AE65 /* util.cpp */; };
|
||||||
|
DFB0578411B7541F0015AE65 /* resource_audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577D11B7541F0015AE65 /* resource_audio.cpp */; };
|
||||||
|
DFB0578511B7541F0015AE65 /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0577E11B7541F0015AE65 /* util.cpp */; };
|
||||||
|
DFB0578A11B754570015AE65 /* maciconbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0578811B754570015AE65 /* maciconbar.cpp */; };
|
||||||
|
DFB0578B11B754570015AE65 /* maciconbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0578811B754570015AE65 /* maciconbar.cpp */; };
|
||||||
|
DFB0578C11B754570015AE65 /* maciconbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0578811B754570015AE65 /* maciconbar.cpp */; };
|
||||||
|
DFB0579111B7547D0015AE65 /* pict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0578F11B7547D0015AE65 /* pict.cpp */; };
|
||||||
|
DFB0579211B7547D0015AE65 /* pict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0578F11B7547D0015AE65 /* pict.cpp */; };
|
||||||
|
DFB0579311B7547D0015AE65 /* pict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0578F11B7547D0015AE65 /* pict.cpp */; };
|
||||||
|
DFB0579811B7549C0015AE65 /* cinepak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0579611B7549C0015AE65 /* cinepak.cpp */; };
|
||||||
|
DFB0579911B7549C0015AE65 /* cinepak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0579611B7549C0015AE65 /* cinepak.cpp */; };
|
||||||
|
DFB0579A11B7549C0015AE65 /* cinepak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFB0579611B7549C0015AE65 /* cinepak.cpp */; };
|
||||||
DFC831210F48AF19005EF03C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301A0F48AF18005EF03C /* detection.cpp */; };
|
DFC831210F48AF19005EF03C /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301A0F48AF18005EF03C /* detection.cpp */; };
|
||||||
DFC831230F48AF19005EF03C /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301D0F48AF18005EF03C /* game.cpp */; };
|
DFC831230F48AF19005EF03C /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301D0F48AF18005EF03C /* game.cpp */; };
|
||||||
DFC831240F48AF19005EF03C /* gc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301E0F48AF18005EF03C /* gc.cpp */; };
|
DFC831240F48AF19005EF03C /* gc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFC8301E0F48AF18005EF03C /* gc.cpp */; };
|
||||||
@ -2796,7 +2821,6 @@
|
|||||||
DFF95C1F0FB22D5700A3EC78 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; };
|
DFF95C1F0FB22D5700A3EC78 /* detection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAAFFB0F0112DF003E9390 /* detection.cpp */; };
|
||||||
DFF95C200FB22D5700A3EC78 /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; };
|
DFF95C200FB22D5700A3EC78 /* thumbnail_intern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */; };
|
||||||
DFF95C210FB22D5700A3EC78 /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; };
|
DFF95C210FB22D5700A3EC78 /* dither.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFB900F485D890006E566 /* dither.cpp */; };
|
||||||
DFF95C260FB22D5700A3EC78 /* video_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBA70F485D950006E566 /* video_player.cpp */; };
|
|
||||||
DFF95C270FB22D5700A3EC78 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; };
|
DFF95C270FB22D5700A3EC78 /* debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD10F485DFB0006E566 /* debug.cpp */; };
|
||||||
DFF95C280FB22D5700A3EC78 /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; };
|
DFF95C280FB22D5700A3EC78 /* GuiManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBD50F485E360006E566 /* GuiManager.cpp */; };
|
||||||
DFF95C290FB22D5700A3EC78 /* posix-saves.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBF80F4860A60006E566 /* posix-saves.cpp */; };
|
DFF95C290FB22D5700A3EC78 /* posix-saves.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DF2FFBF80F4860A60006E566 /* posix-saves.cpp */; };
|
||||||
@ -2985,8 +3009,6 @@
|
|||||||
DF2FFB900F485D890006E566 /* dither.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dither.cpp; sourceTree = "<group>"; };
|
DF2FFB900F485D890006E566 /* dither.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dither.cpp; sourceTree = "<group>"; };
|
||||||
DF2FFB910F485D890006E566 /* dither.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dither.h; sourceTree = "<group>"; };
|
DF2FFB910F485D890006E566 /* dither.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dither.h; sourceTree = "<group>"; };
|
||||||
DF2FFB920F485D890006E566 /* pixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixelformat.h; sourceTree = "<group>"; };
|
DF2FFB920F485D890006E566 /* pixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pixelformat.h; sourceTree = "<group>"; };
|
||||||
DF2FFBA70F485D950006E566 /* video_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_player.cpp; sourceTree = "<group>"; };
|
|
||||||
DF2FFBA80F485D950006E566 /* video_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = video_player.h; sourceTree = "<group>"; };
|
|
||||||
DF2FFBD10F485DFB0006E566 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; };
|
DF2FFBD10F485DFB0006E566 /* debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = debug.cpp; sourceTree = "<group>"; };
|
||||||
DF2FFBD20F485DFB0006E566 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
|
DF2FFBD20F485DFB0006E566 /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = "<group>"; };
|
||||||
DF2FFBD50F485E360006E566 /* GuiManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GuiManager.cpp; sourceTree = "<group>"; };
|
DF2FFBD50F485E360006E566 /* GuiManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GuiManager.cpp; sourceTree = "<group>"; };
|
||||||
@ -4358,6 +4380,24 @@
|
|||||||
DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thumbnail_intern.cpp; sourceTree = "<group>"; };
|
DFAAB0010F011392003E9390 /* thumbnail_intern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thumbnail_intern.cpp; sourceTree = "<group>"; };
|
||||||
DFAAD2390F50120E00C3A4E2 /* console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = console.cpp; sourceTree = "<group>"; };
|
DFAAD2390F50120E00C3A4E2 /* console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = console.cpp; sourceTree = "<group>"; };
|
||||||
DFAAD23A0F50120E00C3A4E2 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = "<group>"; };
|
DFAAD23A0F50120E00C3A4E2 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = "<group>"; };
|
||||||
|
DFB0576211B753AF0015AE65 /* mpeg_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mpeg_player.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0576311B753AF0015AE65 /* mpeg_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpeg_player.h; sourceTree = "<group>"; };
|
||||||
|
DFB0576411B753AF0015AE65 /* qt_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = qt_decoder.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0576511B753AF0015AE65 /* qt_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qt_decoder.h; sourceTree = "<group>"; };
|
||||||
|
DFB0576611B753AF0015AE65 /* video_decoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = video_decoder.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0576711B753AF0015AE65 /* video_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = video_decoder.h; sourceTree = "<group>"; };
|
||||||
|
DFB0577311B753DA0015AE65 /* debug-channels.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "debug-channels.h"; sourceTree = "<group>"; };
|
||||||
|
DFB0577411B753DA0015AE65 /* rational.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rational.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0577511B753DA0015AE65 /* rational.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rational.h; sourceTree = "<group>"; };
|
||||||
|
DFB0577D11B7541F0015AE65 /* resource_audio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resource_audio.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0577E11B7541F0015AE65 /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0577F11B7541F0015AE65 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = "<group>"; };
|
||||||
|
DFB0578811B754570015AE65 /* maciconbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = maciconbar.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0578911B754570015AE65 /* maciconbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maciconbar.h; sourceTree = "<group>"; };
|
||||||
|
DFB0578F11B7547D0015AE65 /* pict.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pict.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0579011B7547D0015AE65 /* pict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pict.h; sourceTree = "<group>"; };
|
||||||
|
DFB0579611B7549C0015AE65 /* cinepak.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cinepak.cpp; sourceTree = "<group>"; };
|
||||||
|
DFB0579711B7549C0015AE65 /* cinepak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cinepak.h; sourceTree = "<group>"; };
|
||||||
DFC8301A0F48AF18005EF03C /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = "<group>"; };
|
DFC8301A0F48AF18005EF03C /* detection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detection.cpp; sourceTree = "<group>"; };
|
||||||
DFC8301D0F48AF18005EF03C /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game.cpp; sourceTree = "<group>"; };
|
DFC8301D0F48AF18005EF03C /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = game.cpp; sourceTree = "<group>"; };
|
||||||
DFC8301E0F48AF18005EF03C /* gc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gc.cpp; sourceTree = "<group>"; };
|
DFC8301E0F48AF18005EF03C /* gc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gc.cpp; sourceTree = "<group>"; };
|
||||||
@ -4776,6 +4816,12 @@
|
|||||||
DF2FFB940F485D950006E566 /* video */ = {
|
DF2FFB940F485D950006E566 /* video */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DFB0576211B753AF0015AE65 /* mpeg_player.cpp */,
|
||||||
|
DFB0576311B753AF0015AE65 /* mpeg_player.h */,
|
||||||
|
DFB0576411B753AF0015AE65 /* qt_decoder.cpp */,
|
||||||
|
DFB0576511B753AF0015AE65 /* qt_decoder.h */,
|
||||||
|
DFB0576611B753AF0015AE65 /* video_decoder.cpp */,
|
||||||
|
DFB0576711B753AF0015AE65 /* video_decoder.h */,
|
||||||
DF90EABF10B023F300C8F93F /* codecs */,
|
DF90EABF10B023F300C8F93F /* codecs */,
|
||||||
DF90EAB610B023D100C8F93F /* avi_decoder.cpp */,
|
DF90EAB610B023D100C8F93F /* avi_decoder.cpp */,
|
||||||
DF90EAB710B023D100C8F93F /* avi_decoder.h */,
|
DF90EAB710B023D100C8F93F /* avi_decoder.h */,
|
||||||
@ -4786,8 +4832,6 @@
|
|||||||
DF6118630FE3A9410042AD3F /* flic_decoder.h */,
|
DF6118630FE3A9410042AD3F /* flic_decoder.h */,
|
||||||
DF6118640FE3A9410042AD3F /* smk_decoder.cpp */,
|
DF6118640FE3A9410042AD3F /* smk_decoder.cpp */,
|
||||||
DF6118650FE3A9410042AD3F /* smk_decoder.h */,
|
DF6118650FE3A9410042AD3F /* smk_decoder.h */,
|
||||||
DF2FFBA70F485D950006E566 /* video_player.cpp */,
|
|
||||||
DF2FFBA80F485D950006E566 /* video_player.h */,
|
|
||||||
);
|
);
|
||||||
path = video;
|
path = video;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -4884,6 +4928,8 @@
|
|||||||
DF45B175116628A5009B85CC /* graphics */ = {
|
DF45B175116628A5009B85CC /* graphics */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DFB0578811B754570015AE65 /* maciconbar.cpp */,
|
||||||
|
DFB0578911B754570015AE65 /* maciconbar.h */,
|
||||||
DF9B924F118E46A00069C19D /* fontsjis.cpp */,
|
DF9B924F118E46A00069C19D /* fontsjis.cpp */,
|
||||||
DF9B9250118E46A00069C19D /* fontsjis.h */,
|
DF9B9250118E46A00069C19D /* fontsjis.h */,
|
||||||
DF45B176116628A5009B85CC /* animate.cpp */,
|
DF45B176116628A5009B85CC /* animate.cpp */,
|
||||||
@ -6388,6 +6434,8 @@
|
|||||||
DF90EABF10B023F300C8F93F /* codecs */ = {
|
DF90EABF10B023F300C8F93F /* codecs */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DFB0579611B7549C0015AE65 /* cinepak.cpp */,
|
||||||
|
DFB0579711B7549C0015AE65 /* cinepak.h */,
|
||||||
DFCDC6FC11662AD700A7D2A0 /* msrle.cpp */,
|
DFCDC6FC11662AD700A7D2A0 /* msrle.cpp */,
|
||||||
DFCDC6FD11662AD700A7D2A0 /* msrle.h */,
|
DFCDC6FD11662AD700A7D2A0 /* msrle.h */,
|
||||||
DF90EAC010B023F400C8F93F /* codec.h */,
|
DF90EAC010B023F400C8F93F /* codec.h */,
|
||||||
@ -6414,6 +6462,9 @@
|
|||||||
DFC830190F48AF18005EF03C /* sci */ = {
|
DFC830190F48AF18005EF03C /* sci */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DFB0577D11B7541F0015AE65 /* resource_audio.cpp */,
|
||||||
|
DFB0577E11B7541F0015AE65 /* util.cpp */,
|
||||||
|
DFB0577F11B7541F0015AE65 /* util.h */,
|
||||||
DF45B175116628A5009B85CC /* graphics */,
|
DF45B175116628A5009B85CC /* graphics */,
|
||||||
DF45B1A5116628A5009B85CC /* parser */,
|
DF45B1A5116628A5009B85CC /* parser */,
|
||||||
DF45B1AB116628A5009B85CC /* sound */,
|
DF45B1AB116628A5009B85CC /* sound */,
|
||||||
@ -6685,6 +6736,9 @@
|
|||||||
DFE473950D81F4E800B6D1FB /* common */ = {
|
DFE473950D81F4E800B6D1FB /* common */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DFB0577311B753DA0015AE65 /* debug-channels.h */,
|
||||||
|
DFB0577411B753DA0015AE65 /* rational.cpp */,
|
||||||
|
DFB0577511B753DA0015AE65 /* rational.h */,
|
||||||
DF9B9261118E46FE0069C19D /* error.cpp */,
|
DF9B9261118E46FE0069C19D /* error.cpp */,
|
||||||
DFEC5D0A1166C5CF00C90552 /* random.cpp */,
|
DFEC5D0A1166C5CF00C90552 /* random.cpp */,
|
||||||
DFEC5D0B1166C5CF00C90552 /* random.h */,
|
DFEC5D0B1166C5CF00C90552 /* random.h */,
|
||||||
@ -6767,6 +6821,8 @@
|
|||||||
DFE477520D81F4E900B6D1FB /* graphics */ = {
|
DFE477520D81F4E900B6D1FB /* graphics */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DFB0578F11B7547D0015AE65 /* pict.cpp */,
|
||||||
|
DFB0579011B7547D0015AE65 /* pict.h */,
|
||||||
DF6BF4C010529DA50069811F /* conversion.cpp */,
|
DF6BF4C010529DA50069811F /* conversion.cpp */,
|
||||||
DF6BF4C110529DA50069811F /* conversion.h */,
|
DF6BF4C110529DA50069811F /* conversion.h */,
|
||||||
DF6BF4C210529DA50069811F /* jpeg.cpp */,
|
DF6BF4C210529DA50069811F /* jpeg.cpp */,
|
||||||
@ -7834,7 +7890,6 @@
|
|||||||
DFAAAFFC0F0112DF003E9390 /* detection.cpp in Sources */,
|
DFAAAFFC0F0112DF003E9390 /* detection.cpp in Sources */,
|
||||||
DFAAB0020F011392003E9390 /* thumbnail_intern.cpp in Sources */,
|
DFAAB0020F011392003E9390 /* thumbnail_intern.cpp in Sources */,
|
||||||
DF2FFB930F485D890006E566 /* dither.cpp in Sources */,
|
DF2FFB930F485D890006E566 /* dither.cpp in Sources */,
|
||||||
DF2FFBB70F485D950006E566 /* video_player.cpp in Sources */,
|
|
||||||
DF2FFBD30F485DFB0006E566 /* debug.cpp in Sources */,
|
DF2FFBD30F485DFB0006E566 /* debug.cpp in Sources */,
|
||||||
DF2FFBD90F485E360006E566 /* GuiManager.cpp in Sources */,
|
DF2FFBD90F485E360006E566 /* GuiManager.cpp in Sources */,
|
||||||
DF2FFBFC0F4860A60006E566 /* posix-saves.cpp in Sources */,
|
DF2FFBFC0F4860A60006E566 /* posix-saves.cpp in Sources */,
|
||||||
@ -8055,6 +8110,15 @@
|
|||||||
DF9B9249118E46730069C19D /* error.cpp in Sources */,
|
DF9B9249118E46730069C19D /* error.cpp in Sources */,
|
||||||
DF9B9254118E46A00069C19D /* fontsjis.cpp in Sources */,
|
DF9B9254118E46A00069C19D /* fontsjis.cpp in Sources */,
|
||||||
DF9B9263118E46FE0069C19D /* error.cpp in Sources */,
|
DF9B9263118E46FE0069C19D /* error.cpp in Sources */,
|
||||||
|
DFB0576B11B753AF0015AE65 /* mpeg_player.cpp in Sources */,
|
||||||
|
DFB0576C11B753AF0015AE65 /* qt_decoder.cpp in Sources */,
|
||||||
|
DFB0576D11B753AF0015AE65 /* video_decoder.cpp in Sources */,
|
||||||
|
DFB0577711B753DA0015AE65 /* rational.cpp in Sources */,
|
||||||
|
DFB0578211B7541F0015AE65 /* resource_audio.cpp in Sources */,
|
||||||
|
DFB0578311B7541F0015AE65 /* util.cpp in Sources */,
|
||||||
|
DFB0578B11B754570015AE65 /* maciconbar.cpp in Sources */,
|
||||||
|
DFB0579211B7547D0015AE65 /* pict.cpp in Sources */,
|
||||||
|
DFB0579911B7549C0015AE65 /* cinepak.cpp in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -8781,7 +8845,6 @@
|
|||||||
DF09418A0F63CB26002D821E /* detection.cpp in Sources */,
|
DF09418A0F63CB26002D821E /* detection.cpp in Sources */,
|
||||||
DF09418B0F63CB26002D821E /* thumbnail_intern.cpp in Sources */,
|
DF09418B0F63CB26002D821E /* thumbnail_intern.cpp in Sources */,
|
||||||
DF09418C0F63CB26002D821E /* dither.cpp in Sources */,
|
DF09418C0F63CB26002D821E /* dither.cpp in Sources */,
|
||||||
DF0941910F63CB26002D821E /* video_player.cpp in Sources */,
|
|
||||||
DF0941920F63CB26002D821E /* debug.cpp in Sources */,
|
DF0941920F63CB26002D821E /* debug.cpp in Sources */,
|
||||||
DF0941930F63CB26002D821E /* GuiManager.cpp in Sources */,
|
DF0941930F63CB26002D821E /* GuiManager.cpp in Sources */,
|
||||||
DF0941940F63CB26002D821E /* posix-saves.cpp in Sources */,
|
DF0941940F63CB26002D821E /* posix-saves.cpp in Sources */,
|
||||||
@ -9006,6 +9069,15 @@
|
|||||||
DF9B924A118E46730069C19D /* error.cpp in Sources */,
|
DF9B924A118E46730069C19D /* error.cpp in Sources */,
|
||||||
DF9B9256118E46A00069C19D /* fontsjis.cpp in Sources */,
|
DF9B9256118E46A00069C19D /* fontsjis.cpp in Sources */,
|
||||||
DF9B9264118E46FE0069C19D /* error.cpp in Sources */,
|
DF9B9264118E46FE0069C19D /* error.cpp in Sources */,
|
||||||
|
DFB0576E11B753AF0015AE65 /* mpeg_player.cpp in Sources */,
|
||||||
|
DFB0576F11B753AF0015AE65 /* qt_decoder.cpp in Sources */,
|
||||||
|
DFB0577011B753AF0015AE65 /* video_decoder.cpp in Sources */,
|
||||||
|
DFB0577811B753DA0015AE65 /* rational.cpp in Sources */,
|
||||||
|
DFB0578411B7541F0015AE65 /* resource_audio.cpp in Sources */,
|
||||||
|
DFB0578511B7541F0015AE65 /* util.cpp in Sources */,
|
||||||
|
DFB0578C11B754570015AE65 /* maciconbar.cpp in Sources */,
|
||||||
|
DFB0579311B7547D0015AE65 /* pict.cpp in Sources */,
|
||||||
|
DFB0579A11B7549C0015AE65 /* cinepak.cpp in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -9737,7 +9809,6 @@
|
|||||||
DFF95C1F0FB22D5700A3EC78 /* detection.cpp in Sources */,
|
DFF95C1F0FB22D5700A3EC78 /* detection.cpp in Sources */,
|
||||||
DFF95C200FB22D5700A3EC78 /* thumbnail_intern.cpp in Sources */,
|
DFF95C200FB22D5700A3EC78 /* thumbnail_intern.cpp in Sources */,
|
||||||
DFF95C210FB22D5700A3EC78 /* dither.cpp in Sources */,
|
DFF95C210FB22D5700A3EC78 /* dither.cpp in Sources */,
|
||||||
DFF95C260FB22D5700A3EC78 /* video_player.cpp in Sources */,
|
|
||||||
DFF95C270FB22D5700A3EC78 /* debug.cpp in Sources */,
|
DFF95C270FB22D5700A3EC78 /* debug.cpp in Sources */,
|
||||||
DFF95C280FB22D5700A3EC78 /* GuiManager.cpp in Sources */,
|
DFF95C280FB22D5700A3EC78 /* GuiManager.cpp in Sources */,
|
||||||
DFF95C290FB22D5700A3EC78 /* posix-saves.cpp in Sources */,
|
DFF95C290FB22D5700A3EC78 /* posix-saves.cpp in Sources */,
|
||||||
@ -9958,6 +10029,15 @@
|
|||||||
DF9B9248118E46730069C19D /* error.cpp in Sources */,
|
DF9B9248118E46730069C19D /* error.cpp in Sources */,
|
||||||
DF9B9252118E46A00069C19D /* fontsjis.cpp in Sources */,
|
DF9B9252118E46A00069C19D /* fontsjis.cpp in Sources */,
|
||||||
DF9B9262118E46FE0069C19D /* error.cpp in Sources */,
|
DF9B9262118E46FE0069C19D /* error.cpp in Sources */,
|
||||||
|
DFB0576811B753AF0015AE65 /* mpeg_player.cpp in Sources */,
|
||||||
|
DFB0576911B753AF0015AE65 /* qt_decoder.cpp in Sources */,
|
||||||
|
DFB0576A11B753AF0015AE65 /* video_decoder.cpp in Sources */,
|
||||||
|
DFB0577611B753DA0015AE65 /* rational.cpp in Sources */,
|
||||||
|
DFB0578011B7541F0015AE65 /* resource_audio.cpp in Sources */,
|
||||||
|
DFB0578111B7541F0015AE65 /* util.cpp in Sources */,
|
||||||
|
DFB0578A11B754570015AE65 /* maciconbar.cpp in Sources */,
|
||||||
|
DFB0579111B7547D0015AE65 /* pict.cpp in Sources */,
|
||||||
|
DFB0579811B7549C0015AE65 /* cinepak.cpp in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -10061,6 +10141,8 @@
|
|||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
FRAMEWORK_SEARCH_PATHS = "";
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
GCC_C_LANGUAGE_STANDARD = c99;
|
GCC_C_LANGUAGE_STANDARD = c99;
|
||||||
|
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||||
|
GCC_ENABLE_CPP_RTTI = NO;
|
||||||
GCC_INPUT_FILETYPE = automatic;
|
GCC_INPUT_FILETYPE = automatic;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
XCODE,
|
XCODE,
|
||||||
@ -10128,6 +10210,8 @@
|
|||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
FRAMEWORK_SEARCH_PATHS = "";
|
FRAMEWORK_SEARCH_PATHS = "";
|
||||||
|
GCC_ENABLE_CPP_EXCEPTIONS = NO;
|
||||||
|
GCC_ENABLE_CPP_RTTI = NO;
|
||||||
GCC_INPUT_FILETYPE = automatic;
|
GCC_INPUT_FILETYPE = automatic;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
XCODE,
|
XCODE,
|
||||||
|
13
dists/os2/readme.os2
Normal file
13
dists/os2/readme.os2
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This is an OS/2 & eComStation build of ScummVM 1.1.1
|
||||||
|
|
||||||
|
To run, it requires:
|
||||||
|
* The libc063 runtime dll, available from ftp://ftp.netlabs.org/pub/gcc/libc-0.6.3-csd3.zip
|
||||||
|
* The gcc444 runtime dll, available from http://download.smedley.info/gcc444.zip
|
||||||
|
* The SDL dll's available from ftp://ftp.netlabs.org/pub/sdl/sdl-1.2.10-bin-20080804.zip
|
||||||
|
|
||||||
|
All feedback is appreciated!
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
|
||||||
|
Paul Smedley
|
||||||
|
5th May, 2010
|
BIN
dists/os2/scummvm.ico
Normal file
BIN
dists/os2/scummvm.ico
Normal file
Binary file not shown.
@ -35,8 +35,9 @@
|
|||||||
#include "gui/GuiManager.h"
|
#include "gui/GuiManager.h"
|
||||||
#include "gui/launcher.h"
|
#include "gui/launcher.h"
|
||||||
#include "gui/ListWidget.h"
|
#include "gui/ListWidget.h"
|
||||||
#include "gui/ThemeEval.h"
|
#include "gui/options.h"
|
||||||
#include "gui/saveload.h"
|
#include "gui/saveload.h"
|
||||||
|
#include "gui/ThemeEval.h"
|
||||||
|
|
||||||
#include "engines/dialogs.h"
|
#include "engines/dialogs.h"
|
||||||
#include "engines/engine.h"
|
#include "engines/engine.h"
|
||||||
@ -49,16 +50,17 @@
|
|||||||
using GUI::CommandSender;
|
using GUI::CommandSender;
|
||||||
using GUI::StaticTextWidget;
|
using GUI::StaticTextWidget;
|
||||||
|
|
||||||
enum {
|
class ConfigDialog : public GUI::OptionsDialog {
|
||||||
kSaveCmd = 'SAVE',
|
protected:
|
||||||
kLoadCmd = 'LOAD',
|
#ifdef SMALL_SCREEN_DEVICE
|
||||||
kPlayCmd = 'PLAY',
|
GUI::Dialog *_keysDialog;
|
||||||
kOptionsCmd = 'OPTN',
|
#endif
|
||||||
kHelpCmd = 'HELP',
|
|
||||||
kAboutCmd = 'ABOU',
|
public:
|
||||||
kQuitCmd = 'QUIT',
|
ConfigDialog(bool subtitleControls);
|
||||||
kRTLCmd = 'RTL ',
|
~ConfigDialog();
|
||||||
kChooseCmd = 'CHOS'
|
|
||||||
|
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
|
||||||
};
|
};
|
||||||
|
|
||||||
MainMenuDialog::MainMenuDialog(Engine *engine)
|
MainMenuDialog::MainMenuDialog(Engine *engine)
|
||||||
@ -95,6 +97,12 @@ MainMenuDialog::MainMenuDialog(Engine *engine)
|
|||||||
|
|
||||||
new GUI::ButtonWidget(this, "GlobalMenu.Options", "Options", kOptionsCmd, 'O');
|
new GUI::ButtonWidget(this, "GlobalMenu.Options", "Options", kOptionsCmd, 'O');
|
||||||
|
|
||||||
|
// The help button is disabled by default.
|
||||||
|
// To enable "Help", an engine needs to use a subclass of MainMenuDialog
|
||||||
|
// (at least for now, we might change how this works in the future).
|
||||||
|
_helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", "Help", kHelpCmd, 'H');
|
||||||
|
_helpButton->setEnabled(false);
|
||||||
|
|
||||||
new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A');
|
new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A');
|
||||||
|
|
||||||
_rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R');
|
_rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R');
|
||||||
@ -135,6 +143,9 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
|
|||||||
case kAboutCmd:
|
case kAboutCmd:
|
||||||
_aboutDialog->runModal();
|
_aboutDialog->runModal();
|
||||||
break;
|
break;
|
||||||
|
case kHelpCmd:
|
||||||
|
// Not handled here -- needs to be handled by a subclass (for now)
|
||||||
|
break;
|
||||||
case kRTLCmd: {
|
case kRTLCmd: {
|
||||||
Common::Event eventRTL;
|
Common::Event eventRTL;
|
||||||
eventRTL.type = Common::EVENT_RTL;
|
eventRTL.type = Common::EVENT_RTL;
|
||||||
@ -263,13 +274,13 @@ enum {
|
|||||||
// "" as value for the domain, and in fact provide a somewhat better user
|
// "" as value for the domain, and in fact provide a somewhat better user
|
||||||
// experience at the same time.
|
// experience at the same time.
|
||||||
ConfigDialog::ConfigDialog(bool subtitleControls)
|
ConfigDialog::ConfigDialog(bool subtitleControls)
|
||||||
: GUI::OptionsDialog("", "ScummConfig") {
|
: GUI::OptionsDialog("", "GlobalConfig") {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sound controllers
|
// Sound controllers
|
||||||
//
|
//
|
||||||
|
|
||||||
addVolumeControls(this, "ScummConfig.");
|
addVolumeControls(this, "GlobalConfig.");
|
||||||
setVolumeSettingsState(true); // could disable controls by GUI options
|
setVolumeSettingsState(true); // could disable controls by GUI options
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -278,7 +289,7 @@ ConfigDialog::ConfigDialog(bool subtitleControls)
|
|||||||
|
|
||||||
if (subtitleControls) {
|
if (subtitleControls) {
|
||||||
// Global talkspeed range of 0-255
|
// Global talkspeed range of 0-255
|
||||||
addSubtitleControls(this, "ScummConfig.", 255);
|
addSubtitleControls(this, "GlobalConfig.", 255);
|
||||||
setSubtitleSettingsState(true); // could disable controls by GUI options
|
setSubtitleSettingsState(true); // could disable controls by GUI options
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,11 +297,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls)
|
|||||||
// Add the buttons
|
// Add the buttons
|
||||||
//
|
//
|
||||||
|
|
||||||
new GUI::ButtonWidget(this, "ScummConfig.Ok", "OK", GUI::kOKCmd, 'O');
|
new GUI::ButtonWidget(this, "GlobalConfig.Ok", "OK", GUI::kOKCmd, 'O');
|
||||||
new GUI::ButtonWidget(this, "ScummConfig.Cancel", "Cancel", GUI::kCloseCmd, 'C');
|
new GUI::ButtonWidget(this, "GlobalConfig.Cancel", "Cancel", GUI::kCloseCmd, 'C');
|
||||||
|
|
||||||
#ifdef SMALL_SCREEN_DEVICE
|
#ifdef SMALL_SCREEN_DEVICE
|
||||||
new GUI::ButtonWidget(this, "ScummConfig.Keys", "Keys", kKeysCmd, 'K');
|
new GUI::ButtonWidget(this, "GlobalConfig.Keys", "Keys", kKeysCmd, 'K');
|
||||||
_keysDialog = NULL;
|
_keysDialog = NULL;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#include "common/str.h"
|
#include "common/str.h"
|
||||||
#include "gui/dialog.h"
|
#include "gui/dialog.h"
|
||||||
#include "gui/options.h"
|
|
||||||
|
|
||||||
class Engine;
|
class Engine;
|
||||||
|
|
||||||
@ -38,6 +37,19 @@ namespace GUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class MainMenuDialog : public GUI::Dialog {
|
class MainMenuDialog : public GUI::Dialog {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
kSaveCmd = 'SAVE',
|
||||||
|
kLoadCmd = 'LOAD',
|
||||||
|
kPlayCmd = 'PLAY',
|
||||||
|
kOptionsCmd = 'OPTN',
|
||||||
|
kHelpCmd = 'HELP',
|
||||||
|
kAboutCmd = 'ABOU',
|
||||||
|
kQuitCmd = 'QUIT',
|
||||||
|
kRTLCmd = 'RTL ',
|
||||||
|
kChooseCmd = 'CHOS'
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MainMenuDialog(Engine *engine);
|
MainMenuDialog(Engine *engine);
|
||||||
~MainMenuDialog();
|
~MainMenuDialog();
|
||||||
@ -51,29 +63,20 @@ protected:
|
|||||||
void load();
|
void load();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Engine *_engine;
|
Engine *_engine;
|
||||||
|
|
||||||
GUI::GraphicsWidget *_logo;
|
GUI::GraphicsWidget *_logo;
|
||||||
GUI::ButtonWidget *_rtlButton;
|
|
||||||
GUI::ButtonWidget *_loadButton;
|
|
||||||
GUI::ButtonWidget *_saveButton;
|
|
||||||
GUI::Dialog *_aboutDialog;
|
|
||||||
GUI::Dialog *_optionsDialog;
|
|
||||||
GUI::SaveLoadChooser *_loadDialog;
|
|
||||||
GUI::SaveLoadChooser *_saveDialog;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConfigDialog : public GUI::OptionsDialog {
|
GUI::ButtonWidget *_rtlButton;
|
||||||
protected:
|
GUI::ButtonWidget *_loadButton;
|
||||||
#ifdef SMALL_SCREEN_DEVICE
|
GUI::ButtonWidget *_saveButton;
|
||||||
GUI::Dialog *_keysDialog;
|
GUI::ButtonWidget *_helpButton;
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
GUI::Dialog *_aboutDialog;
|
||||||
ConfigDialog(bool subtitleControls);
|
GUI::Dialog *_optionsDialog;
|
||||||
~ConfigDialog();
|
|
||||||
|
|
||||||
virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
|
GUI::SaveLoadChooser *_loadDialog;
|
||||||
|
GUI::SaveLoadChooser *_saveDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1602,7 +1602,7 @@ void DrasculaEngine::animation_9_6() {
|
|||||||
// We set the room number to -1 for the same purpose.
|
// We set the room number to -1 for the same purpose.
|
||||||
// Also check animation_2_1(), where the same hack was used
|
// Also check animation_2_1(), where the same hack was used
|
||||||
// by the original
|
// by the original
|
||||||
roomNumber = -1;
|
roomNumber = -2;
|
||||||
loadPic("nota2.alg", bgSurface, HALF_PAL);
|
loadPic("nota2.alg", bgSurface, HALF_PAL);
|
||||||
black();
|
black();
|
||||||
trackProtagonist = 1;
|
trackProtagonist = 1;
|
||||||
|
@ -87,6 +87,7 @@ DrasculaEngine::DrasculaEngine(OSystem *syst, const DrasculaGameDescription *gam
|
|||||||
_textverbs = 0;
|
_textverbs = 0;
|
||||||
_textmisc = 0;
|
_textmisc = 0;
|
||||||
_textd1 = 0;
|
_textd1 = 0;
|
||||||
|
_talkSequences = 0;
|
||||||
|
|
||||||
_color = 0;
|
_color = 0;
|
||||||
blinking = 0;
|
blinking = 0;
|
||||||
|
@ -89,7 +89,8 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) {
|
|||||||
updateRoom();
|
updateRoom();
|
||||||
updateScreen();
|
updateScreen();
|
||||||
|
|
||||||
if (cursorVisible)
|
// roomNumber -2 is end credits. Do not show cursor there
|
||||||
|
if (cursorVisible && roomNumber != -2)
|
||||||
showCursor();
|
showCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,181 +26,463 @@
|
|||||||
#include "m4/assets.h"
|
#include "m4/assets.h"
|
||||||
#include "m4/animation.h"
|
#include "m4/animation.h"
|
||||||
#include "m4/compression.h"
|
#include "m4/compression.h"
|
||||||
|
#include "m4/mads_scene.h"
|
||||||
|
|
||||||
namespace M4 {
|
namespace M4 {
|
||||||
|
|
||||||
// TODO: this code needs cleanup
|
// TODO: this code needs cleanup
|
||||||
|
|
||||||
Animation::Animation(MadsM4Engine *vm) {
|
MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _view(view) {
|
||||||
_vm = vm;
|
_font = NULL;
|
||||||
_playing = false;
|
_resetFlag = false;
|
||||||
|
_freeFlag = false;
|
||||||
|
_skipLoad = false;
|
||||||
|
_unkIndex = -1;
|
||||||
|
_messageCtr= 0;
|
||||||
|
_field12 = 0;
|
||||||
|
|
||||||
|
_currentFrame = 0;
|
||||||
|
_oldFrameEntry = 0;
|
||||||
|
_nextFrameTimer = _madsVm->_currentTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::loadFullScreen(const char *filename) {
|
MadsAnimation::~MadsAnimation() {
|
||||||
_vm->_palette->deleteAllRanges();
|
for (uint i = 0; i < _messages.size(); ++i) {
|
||||||
load(filename);
|
if (_messages[i].kernelMsgIndex >= 0)
|
||||||
|
_view->_kernelMessages.remove(_messages[i].kernelMsgIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Further deletion logic
|
||||||
|
if (_field12) {
|
||||||
|
_view->_spriteSlots.deleteSprites(_spriteListIndexes[_spriteListIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete _font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::load(const char *filename) {
|
/**
|
||||||
MadsPack anim(filename, _vm);
|
* Initialises and loads the data of an animation
|
||||||
|
*/
|
||||||
|
void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface) {
|
||||||
|
MadsPack anim(filename.c_str(), _vm);
|
||||||
|
bool madsRes = filename[0] == '*';
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
|
int streamIndex = 1;
|
||||||
|
|
||||||
// Chunk 1: header
|
// Chunk 1: header
|
||||||
// header
|
// header
|
||||||
// TODO: there are some unknown fields here, plus we don't read
|
|
||||||
// the entire chunk
|
|
||||||
Common::SeekableReadStream *animStream = anim.getItemStream(0);
|
Common::SeekableReadStream *animStream = anim.getItemStream(0);
|
||||||
Common::SeekableReadStream *spriteSeriesStream;
|
|
||||||
//printf("Chunk 0, size %i\n", animStream->size());
|
|
||||||
_seriesCount = animStream->readUint16LE();
|
|
||||||
_frameCount = animStream->readUint16LE();
|
|
||||||
_frameEntryCount = animStream->readUint16LE();
|
|
||||||
|
|
||||||
// Unknown
|
int spriteListCount = animStream->readUint16LE();
|
||||||
for (int i = 0; i < 43; i++)
|
int miscEntriesCount = animStream->readUint16LE();
|
||||||
animStream->readByte();
|
int frameEntryCount = animStream->readUint16LE();
|
||||||
|
int messagesCount = animStream->readUint16LE();
|
||||||
|
animStream->skip(1);
|
||||||
|
_flags = animStream->readByte();
|
||||||
|
|
||||||
_spriteSeriesNames = new Common::String[_seriesCount];
|
animStream->skip(2);
|
||||||
printf("%i sprite series\n", _seriesCount);
|
_animMode = animStream->readUint16LE();
|
||||||
|
_roomNumber = animStream->readUint16LE();
|
||||||
|
animStream->skip(2);
|
||||||
|
_field12 = animStream->readUint16LE() != 0;
|
||||||
|
_spriteListIndex = animStream->readUint16LE();
|
||||||
|
_scrollX = animStream->readUint16LE();
|
||||||
|
_scrollY = animStream->readSint16LE();
|
||||||
|
animStream->skip(10);
|
||||||
|
|
||||||
|
animStream->read(buffer, 13);
|
||||||
|
_interfaceFile = Common::String(buffer, 13);
|
||||||
|
|
||||||
// TODO: for now, we only load the first sprite series
|
for (int i = 0; i < 10; ++i) {
|
||||||
if (_seriesCount > 1)
|
|
||||||
printf("TODO: Anim has %i sprite series, for now, we only load the first one\n", _seriesCount);
|
|
||||||
_seriesCount = 1; // TODO
|
|
||||||
|
|
||||||
for (int i = 0; i < _seriesCount; i++) {
|
|
||||||
animStream->read(buffer, 13);
|
animStream->read(buffer, 13);
|
||||||
_spriteSeriesNames[i] = Common::String(buffer);
|
_spriteSetNames[i] = Common::String(buffer, 13);
|
||||||
//printf("%03d: %s\n", i, _spriteSeriesNames[i].c_str());
|
}
|
||||||
|
|
||||||
spriteSeriesStream = _vm->res()->get(_spriteSeriesNames[i].c_str());
|
animStream->skip(81);
|
||||||
_spriteSeries = new SpriteAsset(_vm, spriteSeriesStream,
|
animStream->read(buffer, 13);
|
||||||
spriteSeriesStream->size(), _spriteSeriesNames[i].c_str());
|
_lbmFilename = Common::String(buffer, 13);
|
||||||
_vm->res()->toss(_spriteSeriesNames[i].c_str());
|
animStream->read(buffer, 13);
|
||||||
|
_spritesFilename = Common::String(buffer, 13);
|
||||||
|
animStream->skip(48);
|
||||||
|
animStream->read(buffer, 13);
|
||||||
|
_soundName = Common::String(buffer, 13);
|
||||||
|
animStream->skip(26);
|
||||||
|
animStream->read(buffer, 13);
|
||||||
|
Common::String fontResource(buffer, 13);
|
||||||
|
|
||||||
// Adjust the palette of the sprites in the sprite series
|
if (_animMode == 4)
|
||||||
// so that they can be displayed on screen correctly
|
flags |= 0x4000;
|
||||||
RGBList *palData = new RGBList(_spriteSeries->getColorCount(), _spriteSeries->getPalette(), true);
|
if (flags & 0x100)
|
||||||
_vm->_palette->addRange(palData);
|
loadInterface(interfaceSurface, sceneSurface);
|
||||||
|
|
||||||
for (int k = 0; k < _spriteSeries->getCount(); k++) {
|
// Initialise the reference list
|
||||||
M4Sprite *spr = _spriteSeries->getFrame(k);
|
for (int i = 0; i < spriteListCount; ++i)
|
||||||
spr->translate(palData); // sprite pixel translation
|
_spriteListIndexes.push_back(-1);
|
||||||
|
|
||||||
|
delete animStream;
|
||||||
|
|
||||||
|
if (messagesCount > 0) {
|
||||||
|
// Chunk 2
|
||||||
|
// Following is a list of any messages for the animation
|
||||||
|
|
||||||
|
animStream = anim.getItemStream(streamIndex++);
|
||||||
|
|
||||||
|
for (int i = 0; i < messagesCount; ++i) {
|
||||||
|
AnimMessage rec;
|
||||||
|
animStream->read(rec.msg, 70);
|
||||||
|
rec.pos.x = animStream->readUint16LE();
|
||||||
|
rec.pos.y = animStream->readUint16LE();
|
||||||
|
animStream->readUint16LE();
|
||||||
|
rec.rgb1.r = animStream->readByte();
|
||||||
|
rec.rgb1.g = animStream->readByte();
|
||||||
|
rec.rgb1.b = animStream->readByte();
|
||||||
|
rec.rgb2.r = animStream->readByte();
|
||||||
|
rec.rgb2.g = animStream->readByte();
|
||||||
|
rec.rgb2.b = animStream->readByte();
|
||||||
|
rec.kernelMsgIndex = animStream->readUint16LE();
|
||||||
|
animStream->skip(6);
|
||||||
|
rec.startFrame = animStream->readUint16LE();
|
||||||
|
rec.endFrame = animStream->readUint16LE();
|
||||||
|
animStream->readUint16LE();
|
||||||
|
|
||||||
|
_messages.push_back(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete animStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameEntryCount > 0) {
|
||||||
|
// Chunk 3: animation frame info
|
||||||
|
animStream = anim.getItemStream(streamIndex++);
|
||||||
|
|
||||||
|
for (int i = 0; i < frameEntryCount; i++) {
|
||||||
|
AnimFrameEntry rec;
|
||||||
|
rec.frameNumber = animStream->readUint16LE();
|
||||||
|
rec.seqIndex = animStream->readByte();
|
||||||
|
rec.spriteSlot.spriteListIndex = animStream->readByte();
|
||||||
|
rec.spriteSlot.frameNumber = animStream->readUint16LE();
|
||||||
|
rec.spriteSlot.xp = animStream->readUint16LE();
|
||||||
|
rec.spriteSlot.yp = animStream->readUint16LE();
|
||||||
|
rec.spriteSlot.depth = animStream->readByte();
|
||||||
|
rec.spriteSlot.scale = (int8)animStream->readByte();
|
||||||
|
|
||||||
|
_frameEntries.push_back(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete animStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (miscEntriesCount > 0) {
|
||||||
|
// Chunk 4: Misc Data
|
||||||
|
animStream = anim.getItemStream(streamIndex);
|
||||||
|
|
||||||
|
for (int i = 0; i < miscEntriesCount; ++i) {
|
||||||
|
AnimMiscEntry rec;
|
||||||
|
rec.soundNum = animStream->readByte();
|
||||||
|
animStream->skip(1);
|
||||||
|
rec.numTicks = animStream->readUint16LE();
|
||||||
|
rec.posAdjust.x = animStream->readUint16LE();
|
||||||
|
rec.posAdjust.y = animStream->readUint16LE();
|
||||||
|
animStream->readUint16LE();
|
||||||
|
|
||||||
|
_miscEntries.push_back(rec);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete animStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the animation specifies a font, then load it for access
|
||||||
|
if (_flags & ANIM_CUSTOM_FONT) {
|
||||||
|
Common::String fontName;
|
||||||
|
if (madsRes)
|
||||||
|
fontName += "*";
|
||||||
|
fontName += fontResource;
|
||||||
|
|
||||||
|
_font = _vm->_font->getFont(fontName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load all the sprite sets for the animation
|
||||||
|
for (int i = 0; i < spriteListCount; ++i) {
|
||||||
|
if (_field12 && (i == _spriteListIndex))
|
||||||
|
// Skip over field, since it's manually loaded
|
||||||
|
continue;
|
||||||
|
|
||||||
|
_spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_field12) {
|
||||||
|
Common::String resName;
|
||||||
|
if (madsRes)
|
||||||
|
resName += "*";
|
||||||
|
resName += _spriteSetNames[_spriteListIndex];
|
||||||
|
|
||||||
|
_spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Unknown section about handling sprite set list combined with messages size
|
||||||
|
|
||||||
|
// TODO: The original has two separate loops for the loop below based on _animMode == 4. Is it
|
||||||
|
// perhaps that in that mode the sprite frames has a different format..?
|
||||||
|
|
||||||
|
// Remap the sprite list index fields from the initial value to the indexes of the loaded
|
||||||
|
// sprite sets for the animation
|
||||||
|
for (uint i = 0; i < _frameEntries.size(); ++i) {
|
||||||
|
int idx = _frameEntries[i].spriteSlot.spriteListIndex;
|
||||||
|
_frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an animation file for display
|
||||||
|
*/
|
||||||
|
void MadsAnimation::load(const Common::String &filename, int abortTimers) {
|
||||||
|
initialise(filename, 0, NULL, NULL);
|
||||||
|
_messageCtr = 0;
|
||||||
|
_skipLoad = true;
|
||||||
|
|
||||||
|
/* TODO: figure out extra stuff in this routine
|
||||||
|
if (_field12) {
|
||||||
|
_unkIndex = -1;
|
||||||
|
int listIndex = _spriteListIndexes[_spriteListIndex];
|
||||||
|
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex);
|
||||||
|
..?..
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Initialise miscellaneous fields
|
||||||
|
_currentFrame = 0;
|
||||||
|
_oldFrameEntry = 0;
|
||||||
|
_nextFrameTimer = _madsVm->_currentTimer;
|
||||||
|
_abortTimers = abortTimers;
|
||||||
|
_abortMode = _madsVm->scene()->_abortTimersMode2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
_actionNouns[i] = _madsVm->scene()->actionNouns[i];
|
||||||
|
|
||||||
|
// Initialise kernel message list
|
||||||
|
for (uint i = 0; i < _messages.size(); ++i)
|
||||||
|
_messages[i].kernelMsgIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MadsAnimation::update() {
|
||||||
|
if (_field12) {
|
||||||
|
int spriteListIndex = _spriteListIndexes[_spriteListIndex];
|
||||||
|
int newIndex = -1;
|
||||||
|
|
||||||
|
for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) {
|
||||||
|
if (_frameEntries[idx].frameNumber > _currentFrame)
|
||||||
|
break;
|
||||||
|
if (_frameEntries[idx].spriteSlot.spriteListIndex == spriteListIndex)
|
||||||
|
newIndex = _frameEntries[idx].spriteSlot.frameNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newIndex >= 0)
|
||||||
|
load1(newIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's not time for the next frame, then exit
|
||||||
|
if (_madsVm->_currentTimer < _nextFrameTimer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Loop checks for any prior animation sprite slots to be expired
|
||||||
|
for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) {
|
||||||
|
if (_view->_spriteSlots[slotIndex].seqIndex >= 0x80) {
|
||||||
|
// Flag the frame as animation sprite slot
|
||||||
|
_view->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("End pos: %i\n", animStream->pos());
|
// Validate the current frame
|
||||||
|
if (_currentFrame >= (int)_miscEntries.size()) {
|
||||||
delete animStream;
|
// Is the animation allowed to be repeated?
|
||||||
|
if (_resetFlag) {
|
||||||
// ------------------
|
_currentFrame = 0;
|
||||||
|
_oldFrameEntry = 0;
|
||||||
// Chunk 2: anim info
|
} else {
|
||||||
AnimationFrame frame;
|
_freeFlag = true;
|
||||||
animStream = anim.getItemStream(1);
|
return;
|
||||||
//printf("Chunk 1, size %i\n", animStream->size());
|
}
|
||||||
|
|
||||||
_frameEntries = new AnimationFrame[_frameEntryCount];
|
|
||||||
|
|
||||||
for (int i = 0; i < _frameEntryCount; i++) {
|
|
||||||
|
|
||||||
frame.animFrameIndex = animStream->readUint16LE();
|
|
||||||
frame.u = animStream->readByte();
|
|
||||||
frame.seriesIndex = animStream->readByte();
|
|
||||||
frame.seriesFrameIndex = animStream->readUint16LE();
|
|
||||||
frame.x = animStream->readUint16LE();
|
|
||||||
frame.y = animStream->readUint16LE();
|
|
||||||
frame.v = animStream->readByte();
|
|
||||||
frame.w = animStream->readByte();
|
|
||||||
|
|
||||||
_frameEntries[i] = frame;
|
|
||||||
|
|
||||||
/*
|
|
||||||
printf(
|
|
||||||
"animFrameIndex = %4d, "
|
|
||||||
"u = %3d, "
|
|
||||||
"seriesIndex = %3d, "
|
|
||||||
"seriesFrameIndex = %6d, "
|
|
||||||
"x = %3d, "
|
|
||||||
"y = %3d, "
|
|
||||||
"v = %3d, "
|
|
||||||
"w = %3d\n",
|
|
||||||
|
|
||||||
frame.animFrameIndex,
|
|
||||||
frame.u,
|
|
||||||
frame.seriesIndex,
|
|
||||||
frame.seriesFrameIndex,
|
|
||||||
frame.x,
|
|
||||||
frame.y,
|
|
||||||
frame.v,
|
|
||||||
frame.w
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
//printf("End pos: %i\n", animStream->pos());
|
|
||||||
|
|
||||||
delete animStream;
|
|
||||||
|
|
||||||
// Chunk 3: unknown (seems to be sound data?)
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
Animation::~Animation() {
|
|
||||||
//delete[] _spriteSeriesNames;
|
|
||||||
//delete[] _spriteSeries;
|
|
||||||
//delete[] _frameEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Animation::start() {
|
|
||||||
_curFrame = 0;
|
|
||||||
_curFrameEntry = 0;
|
|
||||||
//for (int i = 0; i < _seriesCount; i++) {
|
|
||||||
//_spriteSeries[i] = new SpriteSeries((char*)_spriteSeriesNames[i].c_str());
|
|
||||||
//}
|
|
||||||
_playing = true;
|
|
||||||
updateAnim();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Animation::updateAnim() {
|
|
||||||
if (!_playing)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Get the scene background surface
|
|
||||||
M4Surface *bg = _vm->_scene->getBackgroundSurface();
|
|
||||||
|
|
||||||
while (_frameEntries[_curFrameEntry].animFrameIndex == _curFrame) {
|
|
||||||
AnimationFrame *frame = &_frameEntries[_curFrameEntry];
|
|
||||||
int seriesFrameIndex = (frame->seriesFrameIndex & 0x7FFF) - 1;
|
|
||||||
|
|
||||||
// Write the sprite onto the screen
|
|
||||||
M4Sprite *spr = _spriteSeries->getFrame(seriesFrameIndex);
|
|
||||||
|
|
||||||
// FIXME: correct x, y
|
|
||||||
spr->copyTo(bg, frame->x, frame->y, (int)spr->getTransparentColor());
|
|
||||||
|
|
||||||
// HACK: wait a bit
|
|
||||||
g_system->delayMillis(100);
|
|
||||||
|
|
||||||
//printf("_curFrameEntry = %d\n", _curFrameEntry);
|
|
||||||
_curFrameEntry++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("_curFrame = %d\n", _curFrame);
|
// Handle starting any sound for this frame
|
||||||
|
AnimMiscEntry &misc = _miscEntries[_currentFrame];
|
||||||
|
if (misc.soundNum)
|
||||||
|
_vm->_sound->playSound(misc.soundNum);
|
||||||
|
|
||||||
_curFrame++;
|
bool screenChanged = false;
|
||||||
if (_curFrame >= _frameCount) // anim done
|
|
||||||
stop();
|
|
||||||
|
|
||||||
return _curFrame >= _frameCount;
|
// Handle any scrolling of the screen surface
|
||||||
|
if ((_scrollX != 0) || (_scrollY != 0)) {
|
||||||
|
_view->_bgSurface->scrollX(_scrollX);
|
||||||
|
_view->_bgSurface->scrollY(_scrollY);
|
||||||
|
|
||||||
|
screenChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle any offset adjustment for sprites as of this frame
|
||||||
|
if (_view->_posAdjust.x != misc.posAdjust.x) {
|
||||||
|
misc.posAdjust.x = _view->_posAdjust.x;
|
||||||
|
screenChanged = true;
|
||||||
|
}
|
||||||
|
if (_view->_posAdjust.y != misc.posAdjust.y) {
|
||||||
|
misc.posAdjust.y = _view->_posAdjust.y;
|
||||||
|
screenChanged = true;
|
||||||
|
}
|
||||||
|
if (screenChanged) {
|
||||||
|
// Signal the entire screen needs refreshing
|
||||||
|
_view->_spriteSlots.fullRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
int spriteSlotsMax = _view->_spriteSlots.startIndex;
|
||||||
|
|
||||||
|
// Main frame animation loop - frames get animated by being placed, as necessary, into the
|
||||||
|
// main sprite slot array
|
||||||
|
while ((uint)_oldFrameEntry < _frameEntries.size()) {
|
||||||
|
if (_frameEntries[_oldFrameEntry].frameNumber > _currentFrame)
|
||||||
|
break;
|
||||||
|
else if (_frameEntries[_oldFrameEntry].frameNumber == _currentFrame) {
|
||||||
|
// Found the correct frame
|
||||||
|
int spriteSlotIndex = 0;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((spriteSlotIndex == 0) && (index < spriteSlotsMax)) {
|
||||||
|
int seqIndex = _frameEntries[_oldFrameEntry].seqIndex - _view->_spriteSlots[index].seqIndex;
|
||||||
|
if (seqIndex == 0x80) {
|
||||||
|
if (_view->_spriteSlots[index] == _frameEntries[_oldFrameEntry].spriteSlot) {
|
||||||
|
_view->_spriteSlots[index].spriteType = SPRITE_ZERO;
|
||||||
|
spriteSlotIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spriteSlotIndex == 0) {
|
||||||
|
int slotIndex = _view->_spriteSlots.getIndex();
|
||||||
|
MadsSpriteSlot &slot = _view->_spriteSlots[slotIndex];
|
||||||
|
slot.copy(_frameEntries[_oldFrameEntry].spriteSlot);
|
||||||
|
slot.seqIndex = _frameEntries[_oldFrameEntry].seqIndex + 0x80;
|
||||||
|
|
||||||
|
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(
|
||||||
|
_view->_spriteSlots[slotIndex].spriteListIndex);
|
||||||
|
slot.spriteType = spriteSet.isBackground() ? BACKGROUND_SPRITE : FOREGROUND_SPRITE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++_oldFrameEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the display of any messages
|
||||||
|
for (uint idx = 0; idx < _messages.size(); ++idx) {
|
||||||
|
if (_messages[idx].kernelMsgIndex >= 0) {
|
||||||
|
// Handle currently active message
|
||||||
|
if ((_currentFrame < _messages[idx].startFrame) || (_currentFrame > _messages[idx].endFrame)) {
|
||||||
|
_view->_kernelMessages.remove(_messages[idx].kernelMsgIndex);
|
||||||
|
_messages[idx].kernelMsgIndex = -1;
|
||||||
|
--_messageCtr;
|
||||||
|
}
|
||||||
|
} else if ((_currentFrame >= _messages[idx].startFrame) && (_currentFrame <= _messages[idx].endFrame)) {
|
||||||
|
// Start displaying the message
|
||||||
|
AnimMessage &me = _messages[idx];
|
||||||
|
|
||||||
|
// The colour index to use is dependant on how many messages are currently on-screen
|
||||||
|
uint8 colIndex;
|
||||||
|
switch (_messageCtr) {
|
||||||
|
case 1:
|
||||||
|
colIndex = 252;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
colIndex = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
colIndex = 250;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_vm->_palette->setEntry(colIndex, me.rgb1.r, me.rgb1.g, me.rgb1.b);
|
||||||
|
_vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b);
|
||||||
|
|
||||||
|
// Add a kernel message to display the given text
|
||||||
|
me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg);
|
||||||
|
++_messageCtr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move to the next frame
|
||||||
|
_currentFrame++;
|
||||||
|
if (_currentFrame >= (int)_miscEntries.size()) {
|
||||||
|
// Animation is complete
|
||||||
|
if (_abortTimers != 0) {
|
||||||
|
_view->_abortTimers = _abortTimers;
|
||||||
|
_view->_abortTimersMode = _abortMode;
|
||||||
|
|
||||||
|
if (_abortMode != ABORTMODE_1) {
|
||||||
|
// Copy the noun list
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
_madsVm->scene()->actionNouns[i] = _actionNouns[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1);
|
||||||
|
_nextFrameTimer = _madsVm->_currentTimer + _miscEntries[frameNum].numTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::stop() {
|
void MadsAnimation::setCurrentFrame(int frameNumber) {
|
||||||
_playing = false;
|
_currentFrame = frameNumber;
|
||||||
|
_oldFrameEntry = 0;
|
||||||
|
_freeFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _seriesCount; i++) {
|
void MadsAnimation::load1(int frameNumber) {
|
||||||
// TODO: cleanup
|
if (_skipLoad)
|
||||||
//delete _spriteSeries[i];
|
return;
|
||||||
//_spriteSeries[i] = NULL;
|
|
||||||
|
Common::Point pt;
|
||||||
|
int listIndex = _spriteListIndexes[_spriteListIndex];
|
||||||
|
SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex);
|
||||||
|
|
||||||
|
if (_unkIndex < 0) {
|
||||||
|
M4Surface *frame = spriteSet.getFrame(0);
|
||||||
|
pt.x = frame->bounds().left;
|
||||||
|
pt.y = frame->bounds().top;
|
||||||
|
} else {
|
||||||
|
pt.x = _unkList[_unkIndex].x;
|
||||||
|
pt.y = _unkList[_unkIndex].y;
|
||||||
|
_unkIndex = 1 - _unkIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proc1(spriteSet, pt, frameNumber))
|
||||||
|
error("proc1 failure");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MadsAnimation::loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface) {
|
||||||
|
if (_animMode <= 2) {
|
||||||
|
MadsSceneResources sceneResources;
|
||||||
|
sceneResources.load(_roomNumber, _interfaceFile.c_str(), 0, depthSurface, interfaceSurface);
|
||||||
|
|
||||||
|
} else if (_animMode == 4) {
|
||||||
|
// Load a scene interface
|
||||||
|
interfaceSurface->madsLoadInterface(_interfaceFile);
|
||||||
|
} else {
|
||||||
|
// This mode allocates two large surfaces for the animation
|
||||||
|
// TODO: Are these ever properly freed?
|
||||||
|
error("Anim mode %d - need to check free logic", _animMode);
|
||||||
|
assert(!interfaceSurface);
|
||||||
|
assert(!depthSurface);
|
||||||
|
depthSurface = new M4Surface(MADS_SURFACE_WIDTH, MADS_SCREEN_HEIGHT);
|
||||||
|
interfaceSurface = new M4Surface(MADS_SURFACE_WIDTH, MADS_SCREEN_HEIGHT);
|
||||||
|
depthSurface->clear();
|
||||||
|
interfaceSurface->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,39 +29,92 @@
|
|||||||
#include "m4/m4.h"
|
#include "m4/m4.h"
|
||||||
#include "m4/graphics.h"
|
#include "m4/graphics.h"
|
||||||
#include "m4/assets.h"
|
#include "m4/assets.h"
|
||||||
|
#include "m4/mads_views.h"
|
||||||
|
#include "common/array.h"
|
||||||
|
|
||||||
namespace M4 {
|
namespace M4 {
|
||||||
|
|
||||||
struct AnimationFrame {
|
class MadsView;
|
||||||
uint16 animFrameIndex;
|
class SpriteSlotSubset;
|
||||||
byte u;
|
|
||||||
byte seriesIndex;
|
class AnimMessage {
|
||||||
uint16 seriesFrameIndex;
|
public:
|
||||||
uint16 x, y;
|
char msg[70];
|
||||||
byte v, w;
|
Common::Point pos;
|
||||||
|
RGB8 rgb1, rgb2;
|
||||||
|
int kernelMsgIndex;
|
||||||
|
|
||||||
|
int startFrame, endFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Animation {
|
class AnimFrameEntry {
|
||||||
public:
|
public:
|
||||||
Animation(MadsM4Engine *vm);
|
int frameNumber;
|
||||||
~Animation();
|
int seqIndex;
|
||||||
|
SpriteSlotSubset spriteSlot;
|
||||||
|
};
|
||||||
|
|
||||||
void load(const char *filename);
|
class AnimMiscEntry {
|
||||||
void loadFullScreen(const char *filename);
|
public:
|
||||||
void start();
|
int soundNum;
|
||||||
bool updateAnim();
|
int numTicks;
|
||||||
void stop();
|
Common::Point posAdjust;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
#define ANIM_SPRITE_SET_SIZE 50
|
||||||
bool _playing;
|
|
||||||
MadsM4Engine *_vm;
|
enum MadsAnimationFlags {ANIM_CUSTOM_FONT = 0x20, ANIM_HAS_SOUND = 0x8000};
|
||||||
int _seriesCount;
|
|
||||||
int _frameCount;
|
class MadsAnimation: public Animation {
|
||||||
int _frameEntryCount;
|
private:
|
||||||
AnimationFrame *_frameEntries;
|
MadsView *_view;
|
||||||
Common::String *_spriteSeriesNames;
|
|
||||||
SpriteAsset *_spriteSeries;
|
int _spriteListCount;
|
||||||
int _curFrame, _curFrameEntry;
|
Common::Array<AnimMessage> _messages;
|
||||||
|
Common::Array<AnimFrameEntry> _frameEntries;
|
||||||
|
Common::Array<AnimMiscEntry> _miscEntries;
|
||||||
|
Font *_font;
|
||||||
|
|
||||||
|
uint8 _flags;
|
||||||
|
int _animMode;
|
||||||
|
int _roomNumber;
|
||||||
|
bool _field12;
|
||||||
|
int _spriteListIndex;
|
||||||
|
int _scrollX;
|
||||||
|
int _scrollY;
|
||||||
|
Common::String _interfaceFile;
|
||||||
|
Common::String _spriteSetNames[10];
|
||||||
|
Common::String _lbmFilename;
|
||||||
|
Common::String _spritesFilename;
|
||||||
|
Common::String _soundName;
|
||||||
|
Common::Array<int> _spriteListIndexes;
|
||||||
|
|
||||||
|
int _currentFrame, _oldFrameEntry;
|
||||||
|
bool _resetFlag;
|
||||||
|
bool _freeFlag;
|
||||||
|
bool _skipLoad;
|
||||||
|
int _unkIndex;
|
||||||
|
Common::Point _unkList[2];
|
||||||
|
uint32 _nextFrameTimer;
|
||||||
|
int _messageCtr;
|
||||||
|
int _abortTimers;
|
||||||
|
AbortTimerMode _abortMode;
|
||||||
|
uint16 _actionNouns[3];
|
||||||
|
|
||||||
|
void load1(int frameNumber);
|
||||||
|
bool proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
|
||||||
|
void loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface);
|
||||||
|
public:
|
||||||
|
MadsAnimation(MadsM4Engine *vm, MadsView *view);
|
||||||
|
virtual ~MadsAnimation();
|
||||||
|
|
||||||
|
virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface);
|
||||||
|
virtual void load(const Common::String &filename, int abortTimers);
|
||||||
|
virtual void update();
|
||||||
|
virtual void setCurrentFrame(int frameNumber);
|
||||||
|
|
||||||
|
bool freeFlag() const { return _freeFlag; }
|
||||||
|
int roomNumber() const { return _roomNumber; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace M4
|
} // End of namespace M4
|
||||||
|
@ -30,13 +30,13 @@
|
|||||||
|
|
||||||
namespace M4 {
|
namespace M4 {
|
||||||
|
|
||||||
BaseAsset::BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : _vm(vm) {
|
BaseAsset::BaseAsset(MadsM4Engine *vm) : _vm(vm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseAsset::~BaseAsset() {
|
BaseAsset::~BaseAsset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
|
MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
|
||||||
uint32 stateCount = stream->readUint32LE();
|
uint32 stateCount = stream->readUint32LE();
|
||||||
for (uint32 curState = 0; curState < stateCount; curState++) {
|
for (uint32 curState = 0; curState < stateCount; curState++) {
|
||||||
uint32 stateOffset = stream->readUint32LE();
|
uint32 stateOffset = stream->readUint32LE();
|
||||||
@ -61,7 +61,7 @@ uint32 MachineAsset::getStateOffset(uint32 state) {
|
|||||||
return _stateTable[state];
|
return _stateTable[state];
|
||||||
}
|
}
|
||||||
|
|
||||||
SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
|
SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
|
||||||
_localVarCount = stream->readUint32LE();
|
_localVarCount = stream->readUint32LE();
|
||||||
_codeSize = size - 4;
|
_codeSize = size - 4;
|
||||||
_code = new byte[_codeSize];
|
_code = new byte[_codeSize];
|
||||||
@ -78,7 +78,7 @@ void SequenceAsset::getCode(byte *&code, uint32 &codeSize) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
|
DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) {
|
||||||
|
|
||||||
_recCount = stream->readUint32LE();
|
_recCount = stream->readUint32LE();
|
||||||
_recSize = stream->readUint32LE();
|
_recSize = stream->readUint32LE();
|
||||||
@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) {
|
|||||||
return &_data[_recSize * index];
|
return &_data[_recSize * index];
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : BaseAsset(vm, stream, size, name) {
|
SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) :
|
||||||
|
BaseAsset(vm) {
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
_palInterface = NULL;
|
_palInterface = NULL;
|
||||||
_paletteData = NULL;
|
_paletteData = NULL;
|
||||||
@ -110,6 +111,20 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) {
|
||||||
|
_stream = vm->res()->get(name);
|
||||||
|
_palInterface = NULL;
|
||||||
|
_paletteData = NULL;
|
||||||
|
|
||||||
|
if (_vm->isM4()) {
|
||||||
|
loadM4SpriteAsset(vm, _stream, true);
|
||||||
|
} else {
|
||||||
|
loadMadsSpriteAsset(vm, _stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->res()->toss(name);
|
||||||
|
}
|
||||||
|
|
||||||
SpriteAsset::~SpriteAsset() {
|
SpriteAsset::~SpriteAsset() {
|
||||||
if (_palInterface) {
|
if (_palInterface) {
|
||||||
// Internally stored palette translation data, so release it
|
// Internally stored palette translation data, so release it
|
||||||
@ -195,11 +210,12 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre
|
|||||||
_maxHeight = 0;
|
_maxHeight = 0;
|
||||||
|
|
||||||
Common::SeekableReadStream *spriteStream = sprite.getItemStream(0);
|
Common::SeekableReadStream *spriteStream = sprite.getItemStream(0);
|
||||||
|
_mode = spriteStream->readByte();
|
||||||
_assetType = spriteStream->readUint16LE();
|
spriteStream->skip(1);
|
||||||
for (int i = 0; i < 18; i++) {
|
int type1 = spriteStream->readUint16LE();
|
||||||
spriteStream->readUint16LE();
|
int type2 = spriteStream->readUint16LE();
|
||||||
}
|
_isBackground = (type1 != 0) && (type2 < 4);
|
||||||
|
spriteStream->skip(32);
|
||||||
_frameCount = spriteStream->readUint16LE();
|
_frameCount = spriteStream->readUint16LE();
|
||||||
// we skip the rest of the data
|
// we skip the rest of the data
|
||||||
delete spriteStream;
|
delete spriteStream;
|
||||||
|
@ -49,7 +49,7 @@ class Palette;
|
|||||||
|
|
||||||
class BaseAsset {
|
class BaseAsset {
|
||||||
public:
|
public:
|
||||||
BaseAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
|
BaseAsset(MadsM4Engine *vm);
|
||||||
~BaseAsset();
|
~BaseAsset();
|
||||||
const Common::String getName() const { return _name; }
|
const Common::String getName() const { return _name; }
|
||||||
protected:
|
protected:
|
||||||
@ -103,6 +103,7 @@ struct SpriteAssetFrame {
|
|||||||
class SpriteAsset : public BaseAsset {
|
class SpriteAsset : public BaseAsset {
|
||||||
public:
|
public:
|
||||||
SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false);
|
SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false);
|
||||||
|
SpriteAsset(MadsM4Engine *vm, const char *name);
|
||||||
~SpriteAsset();
|
~SpriteAsset();
|
||||||
void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream);
|
void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream);
|
||||||
void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream);
|
void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream);
|
||||||
@ -113,7 +114,7 @@ public:
|
|||||||
int32 getFrameHeight(int index);
|
int32 getFrameHeight(int index);
|
||||||
int32 getMaxFrameWidth() const { return _maxWidth; }
|
int32 getMaxFrameWidth() const { return _maxWidth; }
|
||||||
int32 getMaxFrameHeight() const { return _maxHeight; }
|
int32 getMaxFrameHeight() const { return _maxHeight; }
|
||||||
uint16 getAssetType() const { return _assetType; }
|
bool isBackground() const { return _isBackground; }
|
||||||
M4Sprite *getFrame(int frameIndex);
|
M4Sprite *getFrame(int frameIndex);
|
||||||
void loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY);
|
void loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY);
|
||||||
RGB8* getPalette() { return _palette; }
|
RGB8* getPalette() { return _palette; }
|
||||||
@ -136,7 +137,8 @@ protected:
|
|||||||
uint32 _frameStartOffset;
|
uint32 _frameStartOffset;
|
||||||
|
|
||||||
// MADS sprite set fields
|
// MADS sprite set fields
|
||||||
uint16 _assetType;
|
uint8 _mode;
|
||||||
|
bool _isBackground;
|
||||||
|
|
||||||
int32 parseSprite(bool isBigEndian = false);
|
int32 parseSprite(bool isBigEndian = false);
|
||||||
void loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian = false);
|
void loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian = false);
|
||||||
|
@ -66,8 +66,8 @@ public:
|
|||||||
|
|
||||||
class FabDecompressor {
|
class FabDecompressor {
|
||||||
private:
|
private:
|
||||||
int _bitsLeft;
|
int _bitsLeft;
|
||||||
uint32 _bitBuffer;
|
uint32 _bitBuffer;
|
||||||
const byte *_srcData, *_srcP;
|
const byte *_srcData, *_srcP;
|
||||||
int _srcSize;
|
int _srcSize;
|
||||||
|
|
||||||
|
@ -47,7 +47,6 @@ Console::Console(MadsM4Engine *vm) : GUI::Debugger() {
|
|||||||
DCmd_Register("start_conv", WRAP_METHOD(Console, cmdStartConversation));
|
DCmd_Register("start_conv", WRAP_METHOD(Console, cmdStartConversation));
|
||||||
DCmd_Register("textview", WRAP_METHOD(Console, cmdShowTextview));
|
DCmd_Register("textview", WRAP_METHOD(Console, cmdShowTextview));
|
||||||
DCmd_Register("animview", WRAP_METHOD(Console, cmdShowAnimview));
|
DCmd_Register("animview", WRAP_METHOD(Console, cmdShowAnimview));
|
||||||
DCmd_Register("anim", WRAP_METHOD(Console, cmdPlayAnimation));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::~Console() {
|
Console::~Console() {
|
||||||
@ -247,33 +246,6 @@ bool Console::cmdShowAnimview(int argc, const char **argv) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Console::cmdPlayAnimation(int argc, const char **argv) {
|
|
||||||
View *view = _vm->_viewManager->getView(VIEWID_SCENE);
|
|
||||||
if (view == NULL) {
|
|
||||||
DebugPrintf("The scene view isn't currently active\n");
|
|
||||||
} else if (argc != 2 && argc != 3) {
|
|
||||||
DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
|
|
||||||
DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
|
|
||||||
} else {
|
|
||||||
char resourceName[20];
|
|
||||||
strncpy(resourceName, argv[1], 15);
|
|
||||||
resourceName[15] = '\0';
|
|
||||||
if (!strchr(resourceName, '.'))
|
|
||||||
strcat(resourceName, ".AA");
|
|
||||||
|
|
||||||
_vm->_viewManager->moveToFront(view);
|
|
||||||
if (argc == 3 && atoi(argv[2]) == 1)
|
|
||||||
_vm->_animation->loadFullScreen(resourceName);
|
|
||||||
else
|
|
||||||
_vm->_animation->load(resourceName);
|
|
||||||
_vm->_animation->start();
|
|
||||||
view->restore(0, 0, view->width(), view->height());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
|
MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
|
||||||
@ -282,6 +254,7 @@ MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) {
|
|||||||
DCmd_Register("object", WRAP_METHOD(MadsConsole, cmdObject));
|
DCmd_Register("object", WRAP_METHOD(MadsConsole, cmdObject));
|
||||||
DCmd_Register("message", WRAP_METHOD(MadsConsole, cmdMessage));
|
DCmd_Register("message", WRAP_METHOD(MadsConsole, cmdMessage));
|
||||||
DCmd_Register("scene_info", WRAP_METHOD(MadsConsole, cmdSceneInfo));
|
DCmd_Register("scene_info", WRAP_METHOD(MadsConsole, cmdSceneInfo));
|
||||||
|
DCmd_Register("anim", WRAP_METHOD(MadsConsole, cmdPlayAnimation));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MadsConsole::cmdObject(int argc, const char **argv) {
|
bool MadsConsole::cmdObject(int argc, const char **argv) {
|
||||||
@ -386,6 +359,33 @@ bool MadsConsole::cmdSceneInfo(int argc, const char **argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MadsConsole::cmdPlayAnimation(int argc, const char **argv) {
|
||||||
|
View *view = _vm->_viewManager->getView(VIEWID_SCENE);
|
||||||
|
if (view == NULL) {
|
||||||
|
DebugPrintf("The scene view isn't currently active\n");
|
||||||
|
} else if (argc != 2 && argc != 3) {
|
||||||
|
DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
|
||||||
|
DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
|
||||||
|
} else {
|
||||||
|
char resourceName[20];
|
||||||
|
strncpy(resourceName, argv[1], 15);
|
||||||
|
resourceName[15] = '\0';
|
||||||
|
if (!strchr(resourceName, '.'))
|
||||||
|
strcat(resourceName, ".AA");
|
||||||
|
|
||||||
|
_vm->_viewManager->moveToFront(view);
|
||||||
|
if (argc == 3 && atoi(argv[2]) == 1)
|
||||||
|
_madsVm->_palette->deleteAllRanges();
|
||||||
|
|
||||||
|
_madsVm->scene()->_sceneAnimation->load(resourceName, 0);
|
||||||
|
|
||||||
|
view->restore(0, 0, view->width(), view->height());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
M4Console::M4Console(M4Engine *vm): Console(vm) {
|
M4Console::M4Console(M4Engine *vm): Console(vm) {
|
||||||
|
@ -50,7 +50,6 @@ private:
|
|||||||
bool cmdStartConversation(int argc, const char **argv);
|
bool cmdStartConversation(int argc, const char **argv);
|
||||||
bool cmdShowTextview(int argc, const char **argv);
|
bool cmdShowTextview(int argc, const char **argv);
|
||||||
bool cmdShowAnimview(int argc, const char **argv);
|
bool cmdShowAnimview(int argc, const char **argv);
|
||||||
bool cmdPlayAnimation(int argc, const char **argv);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Console(MadsM4Engine *vm);
|
Console(MadsM4Engine *vm);
|
||||||
@ -64,6 +63,8 @@ private:
|
|||||||
bool cmdObject(int argc, const char **argv);
|
bool cmdObject(int argc, const char **argv);
|
||||||
bool cmdMessage(int argc, const char **argv);
|
bool cmdMessage(int argc, const char **argv);
|
||||||
bool cmdSceneInfo(int argc, const char **argv);
|
bool cmdSceneInfo(int argc, const char **argv);
|
||||||
|
bool cmdPlayAnimation(int argc, const char **argv);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MadsConsole(MadsEngine *vm);
|
MadsConsole(MadsEngine *vm);
|
||||||
virtual ~MadsConsole() {}
|
virtual ~MadsConsole() {}
|
||||||
|
@ -96,7 +96,7 @@ void ConversationView::setNode(int32 nodeIndex) {
|
|||||||
_vm->_font->setFont(FONT_CONVERSATION);
|
_vm->_font->setFont(FONT_CONVERSATION);
|
||||||
|
|
||||||
// TODO: Conversation styles and colors
|
// TODO: Conversation styles and colors
|
||||||
_vm->_font->setColors(2, 1, 3);
|
_vm->_font->current()->setColours(2, 1, 3);
|
||||||
|
|
||||||
_currentNodeIndex = nodeIndex;
|
_currentNodeIndex = nodeIndex;
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ void ConversationView::setNode(int32 nodeIndex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out the longest string to determine where option highlighting ends
|
// Figure out the longest string to determine where option highlighting ends
|
||||||
int tempX = _vm->_font->getWidth(node->entries[i]->text, 0) +
|
int tempX = _vm->_font->current()->getWidth(node->entries[i]->text, 0) +
|
||||||
CONV_ENTRIES_X_OFFSET + 10;
|
CONV_ENTRIES_X_OFFSET + 10;
|
||||||
_xEnd = MAX(_xEnd, tempX);
|
_xEnd = MAX(_xEnd, tempX);
|
||||||
}
|
}
|
||||||
@ -163,10 +163,10 @@ void ConversationView::onRefresh(RectList *rects, M4Surface *destSurface) {
|
|||||||
if (i > CONV_MAX_SHOWN_ENTRIES - 1)
|
if (i > CONV_MAX_SHOWN_ENTRIES - 1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
_vm->_font->setColor((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
|
_vm->_font->current()->setColour((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
|
||||||
CONVERSATION_ENTRY_NORMAL);
|
CONVERSATION_ENTRY_NORMAL);
|
||||||
|
|
||||||
_vm->_font->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET,
|
_vm->_font->current()->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET,
|
||||||
CONV_ENTRIES_Y_OFFSET + CONV_ENTRIES_HEIGHT * i, 0, 0);
|
CONV_ENTRIES_Y_OFFSET + CONV_ENTRIES_HEIGHT * i, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ void Dialog::writeChars(const char *srcLine) {
|
|||||||
strcat(line, wordStr);
|
strcat(line, wordStr);
|
||||||
|
|
||||||
lineLen = strlen(line);
|
lineLen = strlen(line);
|
||||||
lineWidth = _vm->_font->getWidth(line, DIALOG_SPACING);
|
lineWidth = _vm->_font->current()->getWidth(line, DIALOG_SPACING);
|
||||||
|
|
||||||
if (((_lineX + lineLen) > _widthChars) || ((_widthX + lineWidth) > _dialogWidth)) {
|
if (((_lineX + lineLen) > _widthChars) || ((_widthX + lineWidth) > _dialogWidth)) {
|
||||||
incLine();
|
incLine();
|
||||||
@ -146,7 +146,7 @@ void Dialog::writeChars(const char *srcLine) {
|
|||||||
*/
|
*/
|
||||||
void Dialog::appendText(const char *line) {
|
void Dialog::appendText(const char *line) {
|
||||||
_lineX += strlen(line);
|
_lineX += strlen(line);
|
||||||
_widthX += _vm->_font->getWidth(line, DIALOG_SPACING);
|
_widthX += _vm->_font->current()->getWidth(line, DIALOG_SPACING);
|
||||||
|
|
||||||
strcat(_lines[_lines.size() - 1].data, line);
|
strcat(_lines[_lines.size() - 1].data, line);
|
||||||
}
|
}
|
||||||
@ -158,7 +158,7 @@ void Dialog::addLine(const char *line, bool underlineP) {
|
|||||||
if ((_widthX > 0) || (_lineX > 0))
|
if ((_widthX > 0) || (_lineX > 0))
|
||||||
incLine();
|
incLine();
|
||||||
|
|
||||||
int lineWidth = _vm->_font->getWidth(line, DIALOG_SPACING);
|
int lineWidth = _vm->_font->current()->getWidth(line, DIALOG_SPACING);
|
||||||
int lineLen = strlen(line);
|
int lineLen = strlen(line);
|
||||||
|
|
||||||
if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars))
|
if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars))
|
||||||
@ -383,7 +383,7 @@ Dialog::Dialog(MadsM4Engine *vm, const char *msgData, const char *title): View(v
|
|||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
// Suffix provided - specifies the dialog width in number of chars
|
// Suffix provided - specifies the dialog width in number of chars
|
||||||
_widthChars = id * 2;
|
_widthChars = id * 2;
|
||||||
_dialogWidth = id * (_vm->_font->getMaxWidth() + DIALOG_SPACING) + 10;
|
_dialogWidth = id * (_vm->_font->current()->getMaxWidth() + DIALOG_SPACING) + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (matchCommand(cmdText, "UNDER")) {
|
} else if (matchCommand(cmdText, "UNDER")) {
|
||||||
@ -416,7 +416,7 @@ Dialog::Dialog(MadsM4Engine *vm, const char *msgData, const char *title): View(v
|
|||||||
Dialog::Dialog(MadsM4Engine *vm, int widthChars): View(vm, Common::Rect(0, 0, 0, 0)) {
|
Dialog::Dialog(MadsM4Engine *vm, int widthChars): View(vm, Common::Rect(0, 0, 0, 0)) {
|
||||||
_vm->_font->setFont(FONT_INTERFACE_MADS);
|
_vm->_font->setFont(FONT_INTERFACE_MADS);
|
||||||
_widthChars = widthChars * 2;
|
_widthChars = widthChars * 2;
|
||||||
_dialogWidth = widthChars * (_vm->_font->getMaxWidth() + DIALOG_SPACING) + 10;
|
_dialogWidth = widthChars * (_vm->_font->current()->getMaxWidth() + DIALOG_SPACING) + 10;
|
||||||
_screenType = LAYER_DIALOG;
|
_screenType = LAYER_DIALOG;
|
||||||
_lineX = 0;
|
_lineX = 0;
|
||||||
_widthX = 0;
|
_widthX = 0;
|
||||||
@ -439,7 +439,7 @@ void Dialog::draw() {
|
|||||||
|
|
||||||
// Calculate bounds
|
// Calculate bounds
|
||||||
int dlgWidth = _dialogWidth;
|
int dlgWidth = _dialogWidth;
|
||||||
int dlgHeight = _lines.size() * (_vm->_font->getHeight() + 1) + 10;
|
int dlgHeight = _lines.size() * (_vm->_font->current()->getHeight() + 1) + 10;
|
||||||
int dialogX = (_vm->_screen->width() - dlgWidth) / 2;
|
int dialogX = (_vm->_screen->width() - dlgWidth) / 2;
|
||||||
int dialogY = (_vm->_screen->height() - dlgHeight) / 2;
|
int dialogY = (_vm->_screen->height() - dlgHeight) / 2;
|
||||||
|
|
||||||
@ -480,26 +480,26 @@ void Dialog::draw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle drawing the text contents
|
// Handle drawing the text contents
|
||||||
_vm->_font->setColours(7, 7, 7);
|
_vm->_font->current()->setColours(7, 7, 7);
|
||||||
setColour(7);
|
setColour(7);
|
||||||
|
|
||||||
for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->getHeight() + 1) {
|
for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->current()->getHeight() + 1) {
|
||||||
|
|
||||||
if (_lines[lineCtr].barLine) {
|
if (_lines[lineCtr].barLine) {
|
||||||
// Bar separation line
|
// Bar separation line
|
||||||
hLine(5, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp);
|
hLine(5, width() - 6, ((_vm->_font->current()->getHeight() + 1) >> 1) + yp);
|
||||||
} else {
|
} else {
|
||||||
// Standard line
|
// Standard line
|
||||||
Common::Point pt(_lines[lineCtr].xp + 5, yp);
|
Common::Point pt(_lines[lineCtr].xp + 5, yp);
|
||||||
if (_lines[lineCtr].xp & 0x40)
|
if (_lines[lineCtr].xp & 0x40)
|
||||||
++pt.y;
|
++pt.y;
|
||||||
|
|
||||||
_vm->_font->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, DIALOG_SPACING);
|
_vm->_font->current()->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, DIALOG_SPACING);
|
||||||
|
|
||||||
if (_lines[lineCtr].underline)
|
if (_lines[lineCtr].underline)
|
||||||
// Underline needed
|
// Underline needed
|
||||||
hLine(pt.x, pt.x + _vm->_font->getWidth(_lines[lineCtr].data, DIALOG_SPACING),
|
hLine(pt.x, pt.x + _vm->_font->current()->getWidth(_lines[lineCtr].data, DIALOG_SPACING),
|
||||||
pt.y + _vm->_font->getHeight());
|
pt.y + _vm->_font->current()->getHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -528,7 +528,7 @@ void Dialog::display(MadsM4Engine *vm, int widthChars, const char **descEntries)
|
|||||||
dlg->incLine();
|
dlg->incLine();
|
||||||
dlg->writeChars(*descEntries);
|
dlg->writeChars(*descEntries);
|
||||||
|
|
||||||
int lineWidth = vm->_font->getWidth(*descEntries, DIALOG_SPACING);
|
int lineWidth = vm->_font->current()->getWidth(*descEntries, DIALOG_SPACING);
|
||||||
dlg->_lines[dlg->_lines.size() - 1].xp = (dlg->_dialogWidth - 10 - lineWidth) / 2;
|
dlg->_lines[dlg->_lines.size() - 1].xp = (dlg->_dialogWidth - 10 - lineWidth) / 2;
|
||||||
++descEntries;
|
++descEntries;
|
||||||
}
|
}
|
||||||
|
@ -29,28 +29,46 @@
|
|||||||
|
|
||||||
namespace M4 {
|
namespace M4 {
|
||||||
|
|
||||||
Font::Font(MadsM4Engine *vm) : _vm(vm) {
|
FontManager::~FontManager() {
|
||||||
|
for (uint i = 0; i < _entries.size(); ++i)
|
||||||
|
delete _entries[i];
|
||||||
|
_entries.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Font *FontManager::getFont(const Common::String &filename) {
|
||||||
|
// Check if the font is already loaded
|
||||||
|
for (uint i = 0; i < _entries.size(); ++i)
|
||||||
|
{
|
||||||
|
if (_entries[i]->_filename.equals(filename))
|
||||||
|
return _entries[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
Font *f = new Font(_vm, filename);
|
||||||
|
_entries.push_back(f);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FontManager::setFont(const Common::String &filename) {
|
||||||
|
_currentFont = getFont(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filename(filename) {
|
||||||
_sysFont = true;
|
_sysFont = true;
|
||||||
_filename = NULL;
|
|
||||||
//TODO: System font
|
//TODO: System font
|
||||||
_fontColors[0] = _vm->_palette->BLACK;
|
_fontColors[0] = _vm->_palette->BLACK;
|
||||||
_fontColors[1] = _vm->_palette->WHITE;
|
_fontColors[1] = _vm->_palette->WHITE;
|
||||||
_fontColors[2] = _vm->_palette->BLACK;
|
_fontColors[2] = _vm->_palette->BLACK;
|
||||||
_fontColors[3] = _vm->_palette->DARK_GRAY;
|
_fontColors[3] = _vm->_palette->DARK_GRAY;
|
||||||
}
|
|
||||||
|
|
||||||
void Font::setFont(const char *filename) {
|
|
||||||
if ((_filename != NULL) && (strcmp(filename, _filename) == 0))
|
|
||||||
// Already using specified font, so don't bother reloading
|
|
||||||
return;
|
|
||||||
|
|
||||||
_sysFont = false;
|
_sysFont = false;
|
||||||
_filename = filename;
|
|
||||||
|
|
||||||
if (_vm->isM4())
|
if (_vm->isM4())
|
||||||
setFontM4(filename);
|
setFontM4(filename.c_str());
|
||||||
else
|
else
|
||||||
setFontMads(filename);
|
setFontMads(filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::setFontM4(const char *filename) {
|
void Font::setFontM4(const char *filename) {
|
||||||
@ -134,20 +152,21 @@ Font::~Font() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::setColor(uint8 color) {
|
void Font::setColour(uint8 colour) {
|
||||||
if (_sysFont)
|
if (_sysFont)
|
||||||
_fontColors[1] = color;
|
_fontColors[1] = colour;
|
||||||
else
|
else
|
||||||
_fontColors[3] = color;
|
_fontColors[3] = colour;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Font::setColors(uint8 alt1, uint8 alt2, uint8 foreground) {
|
void Font::setColours(uint8 col1, uint8 col2, uint8 col3) {
|
||||||
if (_sysFont)
|
if (_sysFont)
|
||||||
_fontColors[1] = foreground;
|
_fontColors[1] = col3;
|
||||||
else {
|
else {
|
||||||
_fontColors[1] = alt1;
|
_fontColors[0] = 0xFF;
|
||||||
_fontColors[2] = alt2;
|
_fontColors[1] = col1;
|
||||||
_fontColors[3] = foreground;
|
_fontColors[2] = col2;
|
||||||
|
_fontColors[3] = col3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,19 +59,11 @@ namespace M4 {
|
|||||||
|
|
||||||
class Font {
|
class Font {
|
||||||
public:
|
public:
|
||||||
Font(MadsM4Engine *vm);
|
Font(MadsM4Engine *vm, const Common::String &filename);
|
||||||
~Font();
|
~Font();
|
||||||
|
|
||||||
Font *getFont(const char *filename) {
|
void setColour(uint8 colour);
|
||||||
// TODO: Proper separation of font instances
|
void setColours(uint8 col1, uint8 col2, uint8 col3);
|
||||||
setFont(filename);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
void setFont(const char *filename);
|
|
||||||
void setColor(uint8 color);
|
|
||||||
void setColors(uint8 alt1, uint8 alt2, uint8 foreground);
|
|
||||||
void setColour(uint8 colour) { setColor(colour); }
|
|
||||||
void setColours(uint8 alt1, uint8 alt2, uint8 foreground) { setColors(alt1, alt2, foreground); }
|
|
||||||
|
|
||||||
int32 getWidth(const char *text, int spaceWidth = -1);
|
int32 getWidth(const char *text, int spaceWidth = -1);
|
||||||
int32 getHeight() const { return _maxHeight; }
|
int32 getHeight() const { return _maxHeight; }
|
||||||
@ -80,7 +72,8 @@ public:
|
|||||||
int32 writeString(M4Surface *surface, const char *text, int x, int y, int width = 0, int spaceWidth = -1) {
|
int32 writeString(M4Surface *surface, const char *text, int x, int y, int width = 0, int spaceWidth = -1) {
|
||||||
return write(surface, text, x, y, width, spaceWidth, _fontColors);
|
return write(surface, text, x, y, width, spaceWidth, _fontColors);
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
const Common::String _filename;
|
||||||
private:
|
private:
|
||||||
void setFontM4(const char *filename);
|
void setFontM4(const char *filename);
|
||||||
void setFontMads(const char *filename);
|
void setFontMads(const char *filename);
|
||||||
@ -91,10 +84,39 @@ private:
|
|||||||
uint16 *_charOffs;
|
uint16 *_charOffs;
|
||||||
uint8 *_charData;
|
uint8 *_charData;
|
||||||
bool _sysFont;
|
bool _sysFont;
|
||||||
const char *_filename;
|
|
||||||
uint8 _fontColors[4];
|
uint8 _fontColors[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FontEntry {
|
||||||
|
public:
|
||||||
|
Font *_font;
|
||||||
|
|
||||||
|
FontEntry() {
|
||||||
|
_font = NULL;
|
||||||
|
}
|
||||||
|
~FontEntry() {
|
||||||
|
delete _font;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FontManager {
|
||||||
|
private:
|
||||||
|
MadsM4Engine *_vm;
|
||||||
|
Common::Array<Font *> _entries;
|
||||||
|
Font *_currentFont;
|
||||||
|
public:
|
||||||
|
FontManager(MadsM4Engine *vm): _vm(vm) { _currentFont = NULL; }
|
||||||
|
~FontManager();
|
||||||
|
|
||||||
|
Font *getFont(const Common::String &filename);
|
||||||
|
void setFont(const Common::String &filename);
|
||||||
|
|
||||||
|
Font *current() {
|
||||||
|
assert(_currentFont);
|
||||||
|
return _currentFont;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // End of namespace M4
|
} // End of namespace M4
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -69,6 +69,13 @@ void RGBList::setRange(int start, int count, const RGB8 *src) {
|
|||||||
|
|
||||||
#define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2)
|
#define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2)
|
||||||
|
|
||||||
|
M4Surface::~M4Surface() {
|
||||||
|
if (_rgbList) {
|
||||||
|
_madsVm->_palette->deleteRange(_rgbList);
|
||||||
|
delete _rgbList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void M4Surface::loadCodesM4(Common::SeekableReadStream *source) {
|
void M4Surface::loadCodesM4(Common::SeekableReadStream *source) {
|
||||||
if (!source) {
|
if (!source) {
|
||||||
free();
|
free();
|
||||||
@ -472,9 +479,18 @@ void M4Surface::loadBackground(int sceneNumber, RGBList **palData) {
|
|||||||
|
|
||||||
if (_vm->getGameType() == GType_RexNebular) {
|
if (_vm->getGameType() == GType_RexNebular) {
|
||||||
// Load Rex Nebular screen
|
// Load Rex Nebular screen
|
||||||
|
bool hasPalette = palData != NULL;
|
||||||
|
if (!hasPalette)
|
||||||
|
palData = &_rgbList;
|
||||||
|
|
||||||
sprintf(resourceName, "rm%d.art", sceneNumber);
|
sprintf(resourceName, "rm%d.art", sceneNumber);
|
||||||
stream = _vm->_resourceManager->get(resourceName);
|
stream = _vm->_resourceManager->get(resourceName);
|
||||||
rexLoadBackground(stream, palData);
|
rexLoadBackground(stream, palData);
|
||||||
|
|
||||||
|
if (!hasPalette) {
|
||||||
|
_vm->_palette->addRange(_rgbList);
|
||||||
|
this->translate(_rgbList);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Loads M4 game scene
|
// Loads M4 game scene
|
||||||
if (palData)
|
if (palData)
|
||||||
@ -617,16 +633,6 @@ void M4Surface::rexLoadBackground(Common::SeekableReadStream *source, RGBList **
|
|||||||
int sceneWidth = sourceUnc->readUint16LE();
|
int sceneWidth = sourceUnc->readUint16LE();
|
||||||
int sceneHeight = sourceUnc->readUint16LE();
|
int sceneHeight = sourceUnc->readUint16LE();
|
||||||
int sceneSize = sceneWidth * sceneHeight;
|
int sceneSize = sceneWidth * sceneHeight;
|
||||||
if (sceneWidth > this->width()) {
|
|
||||||
warning("Background width is %i, too large to fit in screen. Setting it to %i", sceneWidth, this->width());
|
|
||||||
sceneWidth = this->width();
|
|
||||||
sceneSize = sceneWidth * sceneHeight;
|
|
||||||
}
|
|
||||||
if (sceneHeight > this->height()) {
|
|
||||||
warning("Background height is %i, too large to fit in screen.Setting it to %i", sceneHeight, this->height());
|
|
||||||
sceneHeight = this->height();
|
|
||||||
sceneSize = sceneWidth * sceneHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set palette
|
// Set palette
|
||||||
if (!palData) {
|
if (!palData) {
|
||||||
@ -642,6 +648,7 @@ void M4Surface::rexLoadBackground(Common::SeekableReadStream *source, RGBList **
|
|||||||
sourceUnc = packData.getItemStream(1);
|
sourceUnc = packData.getItemStream(1);
|
||||||
assert((int)sourceUnc->size() >= sceneSize);
|
assert((int)sourceUnc->size() >= sceneSize);
|
||||||
|
|
||||||
|
create(sceneWidth, sceneHeight, 1);
|
||||||
byte *pData = (byte *)pixels;
|
byte *pData = (byte *)pixels;
|
||||||
sourceUnc->read(pData, sceneSize);
|
sourceUnc->read(pData, sceneSize);
|
||||||
|
|
||||||
@ -711,10 +718,8 @@ void M4Surface::m4LoadBackground(Common::SeekableReadStream *source) {
|
|||||||
delete tileBuffer;
|
delete tileBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M4Surface::madsloadInterface(int index, RGBList **palData) {
|
void M4Surface::madsLoadInterface(const Common::String &filename) {
|
||||||
char resourceName[20];
|
MadsPack intFile(filename.c_str(), _vm);
|
||||||
sprintf(resourceName, "i%d.int", index);
|
|
||||||
MadsPack intFile(resourceName, _vm);
|
|
||||||
RGB8 *palette = new RGB8[16];
|
RGB8 *palette = new RGB8[16];
|
||||||
|
|
||||||
// Chunk 0, palette
|
// Chunk 0, palette
|
||||||
@ -728,7 +733,7 @@ void M4Surface::madsloadInterface(int index, RGBList **palData) {
|
|||||||
intStream->readByte();
|
intStream->readByte();
|
||||||
intStream->readByte();
|
intStream->readByte();
|
||||||
}
|
}
|
||||||
*palData = new RGBList(16, palette, true);
|
_rgbList = new RGBList(16, palette, true);
|
||||||
delete intStream;
|
delete intStream;
|
||||||
|
|
||||||
// Chunk 1, data
|
// Chunk 1, data
|
||||||
@ -736,8 +741,77 @@ void M4Surface::madsloadInterface(int index, RGBList **palData) {
|
|||||||
create(320, 44, 1);
|
create(320, 44, 1);
|
||||||
intStream->read(pixels, 320 * 44);
|
intStream->read(pixels, 320 * 44);
|
||||||
delete intStream;
|
delete intStream;
|
||||||
|
|
||||||
|
// Translate the interface palette
|
||||||
|
_vm->_palette->addRange(_rgbList);
|
||||||
|
this->translate(_rgbList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M4Surface::scrollX(int xAmount) {
|
||||||
|
if (xAmount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
byte buffer[80];
|
||||||
|
int direction = (xAmount > 0) ? 1 : -1;
|
||||||
|
int xSize = ABS(xAmount);
|
||||||
|
assert(xSize <= 80);
|
||||||
|
|
||||||
|
byte *srcP = (byte *)getBasePtr(0, 0);
|
||||||
|
|
||||||
|
for (int y = 0; y < height(); ++y, srcP += pitch) {
|
||||||
|
if (direction < 0) {
|
||||||
|
// Copy area to be overwritten
|
||||||
|
Common::copy(srcP, srcP + xSize, &buffer[0]);
|
||||||
|
// Shift the remainder of the line over the given area
|
||||||
|
Common::copy(srcP + xSize, srcP + width(), srcP);
|
||||||
|
// Move buffered area to the end of the line
|
||||||
|
Common::copy(&buffer[0], &buffer[xSize], srcP + width() - xSize);
|
||||||
|
} else {
|
||||||
|
// Copy area to be overwritten
|
||||||
|
Common::copy_backward(srcP + width() - xSize, srcP + width(), &buffer[80]);
|
||||||
|
// Shift the remainder of the line over the given area
|
||||||
|
Common::copy_backward(srcP, srcP + width() - xSize, srcP + width());
|
||||||
|
// Move buffered area to the start of the line
|
||||||
|
Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M4Surface::scrollY(int yAmount) {
|
||||||
|
if (yAmount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int direction = (yAmount > 0) ? 1 : -1;
|
||||||
|
int ySize = ABS(yAmount);
|
||||||
|
assert(ySize < (height() / 2));
|
||||||
|
assert(width() == pitch);
|
||||||
|
|
||||||
|
int blockSize = ySize * width();
|
||||||
|
byte *tempData = (byte *)malloc(blockSize);
|
||||||
|
byte *pixelsP = (byte *)getBasePtr(0, 0);
|
||||||
|
|
||||||
|
if (direction > 0) {
|
||||||
|
// Buffer the lines to be overwritten
|
||||||
|
byte *srcP = (byte *)getBasePtr(0, height() - ySize);
|
||||||
|
Common::copy(srcP, srcP + (pitch * ySize), tempData);
|
||||||
|
// Vertically shift all the lines
|
||||||
|
Common::copy_backward(pixelsP, pixelsP + (pitch * (height() - ySize)),
|
||||||
|
pixelsP + (pitch * height()));
|
||||||
|
// Transfer the buffered lines top the top of the screen
|
||||||
|
Common::copy(tempData, tempData + blockSize, pixelsP);
|
||||||
|
} else {
|
||||||
|
// Buffer the lines to be overwritten
|
||||||
|
Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
|
||||||
|
// Vertically shift all the lines
|
||||||
|
Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * height()), pixelsP);
|
||||||
|
// Transfer the buffered lines to the bottom of the screen
|
||||||
|
Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (height() - ySize)));
|
||||||
|
}
|
||||||
|
|
||||||
|
::free(tempData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void M4Surface::translate(RGBList *list, bool isTransparent) {
|
void M4Surface::translate(RGBList *list, bool isTransparent) {
|
||||||
byte *p = getBasePtr(0, 0);
|
byte *p = getBasePtr(0, 0);
|
||||||
byte *palIndexes = list->palIndexes();
|
byte *palIndexes = list->palIndexes();
|
||||||
|
@ -35,6 +35,12 @@
|
|||||||
|
|
||||||
namespace M4 {
|
namespace M4 {
|
||||||
|
|
||||||
|
#define MADS_SURFACE_WIDTH 320
|
||||||
|
#define MADS_SURFACE_HEIGHT 156
|
||||||
|
#define MADS_SCREEN_HEIGHT 200
|
||||||
|
#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2)
|
||||||
|
|
||||||
|
|
||||||
struct BGR8 {
|
struct BGR8 {
|
||||||
uint8 b, g, r;
|
uint8 b, g, r;
|
||||||
};
|
};
|
||||||
@ -89,19 +95,23 @@ class M4Surface : protected Graphics::Surface {
|
|||||||
private:
|
private:
|
||||||
byte _color;
|
byte _color;
|
||||||
bool _isScreen;
|
bool _isScreen;
|
||||||
|
RGBList *_rgbList;
|
||||||
|
|
||||||
void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL);
|
void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL);
|
||||||
void madsLoadBackground(int roomNumber, RGBList **palData = NULL);
|
void madsLoadBackground(int roomNumber, RGBList **palData = NULL);
|
||||||
void m4LoadBackground(Common::SeekableReadStream *source);
|
void m4LoadBackground(Common::SeekableReadStream *source);
|
||||||
public:
|
public:
|
||||||
M4Surface(bool isScreen = false) {
|
M4Surface(bool isScreen = false) {
|
||||||
create(g_system->getWidth(), g_system->getHeight(), 1);
|
create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, 1);
|
||||||
_isScreen = isScreen;
|
_isScreen = isScreen;
|
||||||
|
_rgbList = NULL;
|
||||||
}
|
}
|
||||||
M4Surface(int width_, int height_) {
|
M4Surface(int width_, int height_) {
|
||||||
create(width_, height_, 1);
|
create(width_, height_, 1);
|
||||||
_isScreen = false;
|
_isScreen = false;
|
||||||
|
_rgbList = NULL;
|
||||||
}
|
}
|
||||||
|
virtual ~M4Surface();
|
||||||
|
|
||||||
// loads a .COD file into the M4Surface
|
// loads a .COD file into the M4Surface
|
||||||
// TODO: maybe move this to the rail system? check where it makes sense
|
// TODO: maybe move this to the rail system? check where it makes sense
|
||||||
@ -112,7 +122,8 @@ public:
|
|||||||
// loads the specified background
|
// loads the specified background
|
||||||
void loadBackground(int sceneNumber, RGBList **palData = NULL);
|
void loadBackground(int sceneNumber, RGBList **palData = NULL);
|
||||||
void loadBackgroundRiddle(const char *sceneName);
|
void loadBackgroundRiddle(const char *sceneName);
|
||||||
void madsloadInterface(int index, RGBList **palData);
|
void madsLoadInterface(int index, RGBList **palData = NULL);
|
||||||
|
void madsLoadInterface(const Common::String &filename);
|
||||||
|
|
||||||
void setColor(byte value) { _color = value; }
|
void setColor(byte value) { _color = value; }
|
||||||
void setColour(byte value) { _color = value; }
|
void setColour(byte value) { _color = value; }
|
||||||
@ -173,7 +184,8 @@ public:
|
|||||||
dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColour);
|
dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scrollX(int xAmount);
|
||||||
|
void scrollY(int yAmount);
|
||||||
|
|
||||||
void translate(RGBList *list, bool isTransparent = false);
|
void translate(RGBList *list, bool isTransparent = false);
|
||||||
};
|
};
|
||||||
|
@ -290,26 +290,26 @@ void MenuButton::onRefresh() {
|
|||||||
case OBJTYPE_SL_TEXT:
|
case OBJTYPE_SL_TEXT:
|
||||||
switch (_objectState) {
|
switch (_objectState) {
|
||||||
case OS_MOUSEOVER:
|
case OS_MOUSEOVER:
|
||||||
_vm->_font->setColors(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND,
|
_vm->_font->current()->setColours(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND,
|
||||||
TEXT_COLOR_MOUSEOVER_HILIGHT);
|
TEXT_COLOR_MOUSEOVER_HILIGHT);
|
||||||
sprite = sprites[SL_LINE_MOUSEOVER];
|
sprite = sprites[SL_LINE_MOUSEOVER];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OS_PRESSED:
|
case OS_PRESSED:
|
||||||
_vm->_font->setColors(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND,
|
_vm->_font->current()->setColours(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND,
|
||||||
TEXT_COLOR_PRESSED_HILIGHT);
|
TEXT_COLOR_PRESSED_HILIGHT);
|
||||||
sprite = sprites[SL_LINE_PRESSED];
|
sprite = sprites[SL_LINE_PRESSED];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OS_GREYED:
|
case OS_GREYED:
|
||||||
_vm->_font->setColors(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND,
|
_vm->_font->current()->setColours(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND,
|
||||||
TEXT_COLOR_GREYED_HILIGHT);
|
TEXT_COLOR_GREYED_HILIGHT);
|
||||||
sprite = sprites[SL_LINE_NORMAL];
|
sprite = sprites[SL_LINE_NORMAL];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case OS_NORMAL:
|
case OS_NORMAL:
|
||||||
_vm->_font->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
|
_vm->_font->current()->setColours(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
|
||||||
TEXT_COLOR_NORMAL_HILIGHT);
|
TEXT_COLOR_NORMAL_HILIGHT);
|
||||||
sprite = sprites[SL_LINE_NORMAL];
|
sprite = sprites[SL_LINE_NORMAL];
|
||||||
break;
|
break;
|
||||||
@ -849,11 +849,11 @@ void MenuSaveLoadText::onRefresh() {
|
|||||||
if (_displayValue != 0) {
|
if (_displayValue != 0) {
|
||||||
char tempBuffer[5];
|
char tempBuffer[5];
|
||||||
sprintf(tempBuffer, "%02d", _displayValue);
|
sprintf(tempBuffer, "%02d", _displayValue);
|
||||||
_vm->_font->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
|
_vm->_font->current()->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
|
||||||
xp = _bounds.left + 26;
|
xp = _bounds.left + 26;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vm->_font->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
|
_vm->_font->current()->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -955,18 +955,18 @@ void MenuTextField::onRefresh() {
|
|||||||
// Draw the text
|
// Draw the text
|
||||||
|
|
||||||
_vm->_font->setFont(FONT_MENU);
|
_vm->_font->setFont(FONT_MENU);
|
||||||
_vm->_font->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
|
_vm->_font->current()->setColours(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND,
|
||||||
TEXT_COLOR_NORMAL_HILIGHT);
|
TEXT_COLOR_NORMAL_HILIGHT);
|
||||||
int xp = _bounds.left + 4;
|
int xp = _bounds.left + 4;
|
||||||
|
|
||||||
if (_displayValue != 0) {
|
if (_displayValue != 0) {
|
||||||
char tempBuffer[5];
|
char tempBuffer[5];
|
||||||
sprintf(tempBuffer, "%02d", _displayValue);
|
sprintf(tempBuffer, "%02d", _displayValue);
|
||||||
_vm->_font->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
|
_vm->_font->current()->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1);
|
||||||
xp = _bounds.left + 26;
|
xp = _bounds.left + 26;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vm->_font->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
|
_vm->_font->current()->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1);
|
||||||
|
|
||||||
if (focused) {
|
if (focused) {
|
||||||
// Draw in the cursor
|
// Draw in the cursor
|
||||||
@ -975,7 +975,7 @@ void MenuTextField::onRefresh() {
|
|||||||
// Get the width of the string up to the cursor position
|
// Get the width of the string up to the cursor position
|
||||||
char tempCh = *_cursor;
|
char tempCh = *_cursor;
|
||||||
*_cursor = '\0';
|
*_cursor = '\0';
|
||||||
int stringWidth = _vm->_font->getWidth(_displayText);
|
int stringWidth = _vm->_font->current()->getWidth(_displayText);
|
||||||
*_cursor = tempCh;
|
*_cursor = tempCh;
|
||||||
|
|
||||||
parent()->setColor(TEXT_COLOR_MOUSEOVER_FOREGROUND);
|
parent()->setColor(TEXT_COLOR_MOUSEOVER_FOREGROUND);
|
||||||
@ -1015,10 +1015,10 @@ bool MenuTextField::onEvent(M4EventType event, int32 param, int x, int y, MenuOb
|
|||||||
tempP = &tempStr[tempLen];
|
tempP = &tempStr[tempLen];
|
||||||
_vm->_font->setFont(FONT_MENU);
|
_vm->_font->setFont(FONT_MENU);
|
||||||
|
|
||||||
tempLen = _vm->_font->getWidth(tempStr);
|
tempLen = _vm->_font->current()->getWidth(tempStr);
|
||||||
while ((tempP != &tempStr[0]) && (tempLen > x - _bounds.left - 26)) {
|
while ((tempP != &tempStr[0]) && (tempLen > x - _bounds.left - 26)) {
|
||||||
*--tempP = '\0';
|
*--tempP = '\0';
|
||||||
tempLen = _vm->_font->getWidth(tempStr);
|
tempLen = _vm->_font->current()->getWidth(tempStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cursor = &_displayText[tempP - &tempStr[0]];
|
_cursor = &_displayText[tempP - &tempStr[0]];
|
||||||
@ -1098,7 +1098,7 @@ bool MenuTextField::onEvent(M4EventType event, int32 param, int x, int y, MenuOb
|
|||||||
parent()->_deleteSaveDesc = false;
|
parent()->_deleteSaveDesc = false;
|
||||||
_vm->_font->setFont(FONT_MENU);
|
_vm->_font->setFont(FONT_MENU);
|
||||||
|
|
||||||
tempLen = _vm->_font->getWidth(_displayText);
|
tempLen = _vm->_font->current()->getWidth(_displayText);
|
||||||
if ((strlen(_displayText) < MAX_SAVEGAME_NAME - 1) &&
|
if ((strlen(_displayText) < MAX_SAVEGAME_NAME - 1) &&
|
||||||
(tempLen < _pixelWidth - 12) && (param >= 32) && (param <= 127)) {
|
(tempLen < _pixelWidth - 12) && (param >= 32) && (param <= 127)) {
|
||||||
|
|
||||||
@ -1140,9 +1140,9 @@ GUITextField::GUITextField(View *owner, const Common::Rect &bounds): GUIRect(own
|
|||||||
|
|
||||||
void GUITextField::onRefresh() {
|
void GUITextField::onRefresh() {
|
||||||
_parent->fillRect(_bounds, _vm->_palette->BLACK);
|
_parent->fillRect(_bounds, _vm->_palette->BLACK);
|
||||||
_vm->_font->setColors(3, 3, 3);
|
_vm->_font->current()->setColours(3, 3, 3);
|
||||||
_vm->_font->setFont(FONT_INTERFACE);
|
_vm->_font->setFont(FONT_INTERFACE);
|
||||||
_vm->_font->writeString(_parent, _text.c_str(), _bounds.left, _bounds.top, 0, 1);
|
_vm->_font->current()->writeString(_parent, _text.c_str(), _bounds.left, _bounds.top, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user